View of xos/mm/mapping.c


XOS | Parent Directory | View | Download

/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
/* Cette implementation est gourmande en memoire, surtout pour les petits
 * fichiers. La memoire allouee pour la structure ne fait que croitre, jusqu'a
 * la destruction du fichier. */
 
#include <mapping_struct.h>
#include <kmalloc.h>
#include <i386.h>
#include <string.h>
#include <stddef.h>
 
#define TABLE_INDEX(offset) ((offset) / PAGE_SIZE)
#define DIR_INDEX(offset)   ((offset) / PAGE_SIZE / (PAGE_SIZE / 4))
 
void mapping_init(struct mapping_struct *mapping)
{
  mapping->directory = NULL;
}
 
void mapping_destroy(struct mapping_struct *mapping)
{
  unsigned long **dir_ent;
 
  if (mapping->directory) {
    for (dir_ent = &mapping->directory[0]; dir_ent < &mapping->directory[PAGE_SIZE / 4]; dir_ent++)
      if (*dir_ent)
        kfree(*dir_ent, PAGE_SIZE);
    kfree(mapping->directory, PAGE_SIZE);
  }
}
 
/* Transfert src dans dest. */
void mapping_copy(const struct mapping_struct *src, struct mapping_struct *dest)
{
  dest->directory = src->directory;
}
 
unsigned long mapping_get_page_frame(const struct mapping_struct *mapping, unsigned long offset)
{
  unsigned long *table;
 
  if (!mapping->directory)
    return 0;
  if (!(table = mapping->directory[DIR_INDEX(offset)]))
    return 0;
  return table[TABLE_INDEX(offset)];
}
 
/* L'entree correspondant a offset doit etre vide (sinon elle est ecrasee).
 * Cette fonction ne garantie pas que l'operation a reussie, en particulier
 * s'il n'y a plus de memoire. */
void mapping_set_page_frame(struct mapping_struct *mapping, unsigned long offset, unsigned long page_frame)
{
  unsigned long *table;
 
  if (!mapping->directory) {
    if (!(mapping->directory = kmalloc(PAGE_SIZE)))
      return;
    memset(mapping->directory, 0, PAGE_SIZE);
  }
  if (!(table = mapping->directory[DIR_INDEX(offset)])) {
    if (!(table = kmalloc(PAGE_SIZE)))
      return;
    memset(table, 0, PAGE_SIZE);
    mapping->directory[DIR_INDEX(offset)] = table;
  }
  table[TABLE_INDEX(offset)] = page_frame;
}
 
/* Si le cadre de page n'est pas dans la projection, aucune operation n'est
 * effectuee. */
void mapping_delete_page_frame(struct mapping_struct *mapping, unsigned long offset, unsigned long page_frame)
{
  unsigned long *table;
 
  if (!mapping->directory)
    return;
  if (!(table = mapping->directory[DIR_INDEX(offset)]))
    return;
  if (table[TABLE_INDEX(offset)] == page_frame)
    table[TABLE_INDEX(offset)] = 0;
}