/* 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 . */
/* 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
#include
#include
#include
#include
#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;
}