View of xos/mm/kmalloc.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/>. */
 
#include "lowmem.h"
 
#include <slab.h>
#include <cache_struct.h>
#include <assert.h>
#include <i386.h>
#include <misc.h>
#include <stddef.h>
 
/* pour controler la valadite d'un kfree() */
struct kmalloc_header_struct {
  unsigned long size;
};
 
static struct cache_struct cache_table[LOG_PAGE_SIZE];
 
void kmalloc_init()
{
  unsigned int k;
 
  /* cache_table[0..1] ne sont pas utilises. */
  for (k = 2; k < LOG_PAGE_SIZE; k++)
    kmem_cache_init(&cache_table[k], exp2(k));
}
 
void kmalloc_check_empty()
{
  unsigned int k;
 
  for (k = 2; k < LOG_PAGE_SIZE; k++)
    kmem_cache_check_empty(&cache_table[k]);
}
 
/* Si size >= PAGE_SIZE, le resultat est garanti etre aligne sur PAGE_SIZE. */
void *kmalloc(unsigned long size)
{
  unsigned int k;
  void *p;
 
  if (size == 0)
    return NULL;
  k = ulog2(size + sizeof (struct kmalloc_header_struct));
  if (k < 2)
    k = 2;
  if (k < LOG_PAGE_SIZE) {
    if (!(p = kmem_cache_alloc(&cache_table[k])))
      return NULL;
    ((struct kmalloc_header_struct *)p)->size = size;
    return p + sizeof (struct kmalloc_header_struct);
  }
  else
    return alloc_page_frames(k - LOG_PAGE_SIZE);
}
 
void kfree(void *ptr, unsigned long size)
{
  unsigned int k;
  struct kmalloc_header_struct *hdr;
 
  if (!ptr || size == 0)
    return;
  k = ulog2(size + sizeof (struct kmalloc_header_struct));
  if (k < 2)
    k = 2;
  if (k < LOG_PAGE_SIZE) {
    hdr = ptr - sizeof (struct kmalloc_header_struct);
    assert(hdr->size == size); /* controle de validite */
    hdr->size = 0;
    return kmem_cache_free(&cache_table[k], ptr - sizeof (struct kmalloc_header_struct));
  }
  else
    return free_page_frames(ptr, k - LOG_PAGE_SIZE);
}