Added a public domain malloc temporarily.

More changes to fs0, still improvising.
This commit is contained in:
Bahadir Balban
2008-01-16 18:12:20 +00:00
parent c921197e69
commit 66abb3d7f8
4 changed files with 497 additions and 17 deletions

View File

@@ -59,7 +59,7 @@ struct dentry {
struct dentry *parent; /* Parent dentry */
struct list_head child; /* List of dentries with same parent */
struct list_head children; /* List of children dentries */
struct list_head dref_list; /* For vnode's dirent reference list */
struct list_head vref; /* For vnode's dirent reference list */
struct vnode *vnode; /* The vnode associated with dirent */
struct dentry_ops ops;
};

View File

@@ -0,0 +1,7 @@
#ifndef __PRIVATE_MALLOC_H__
#define __PRIVATE_MALLOC_H__
void *kmalloc(size_t size);
void kfree(void *blk);
#endif /*__PRIVATE_MALLOC_H__ */

View File

@@ -1,24 +1,90 @@
/*
* An imaginary filesystem for reading the in-memory
* server tasks loaded out of the initial elf executable.
* A pseudo-filesystem for reading the in-memory
* server tasks loaded from the initial elf executable.
*
* Copyright (C) 2007, 2008 Bahadir Balban
*/
#include <fs.h>
#include <l4/lib/list.h>
#include <malloc.h>
struct dentry *bootfs_dentry_lookup(struct dentry *d, char *dname)
{
struct dentry *this;
list_for_each_entry(this, child, &d->children) {
if (this->compare(this, dname))
return this;
}
return 0;
}
struct dentry *path_lookup(struct superblock *sb, char *pathstr)
{
char *dname;
char *splitpath;
struct dentry *this, *next;
/* First dentry is root */
this = sb->root;
/* Get next path component from path string */
dname = path_next_dentry_name(pathstr);
if (!this->compare(dname))
return;
while(!(dname = path_next_dentry_name(pathstr))) {
if ((d = this->lookup(this, dname)))
return 0;
}
}
/*
* These are preallocated structures for forging a filesystem tree
* from the elf loaded server segments available from kdata info.
* This creates a pseudo-filesystem tree from the loaded
* server elf images whose information is available from
* initdata.
*/
#define BOOTFS_IMG_MAX 10
struct vnode bootfs_vnode[BOOTFS_IMG_MAX];
struct dentry bootfs_dentry[BOOTFS_IMG_MAX];
struct file bootfs_file[BOOTFS_IMG_MAX];
void bootfs_populate(struct initdata *initdata, struct superblock *sb)
{
struct bootdesc *bd = initdata->bootdesc;
struct svc_image *img;
struct dentry *d;
struct vnode *v;
struct file *f;
/* These are for the root */
struct dentry bootfs_root;
struct vnode bootfs_rootvn;
for (int i = 0; i < bd->total_images; i++) {
img = &bd->images[i];
d = malloc(sizeof(struct dentry));
v = malloc(sizeof(struct vnode));
f = malloc(sizeof(struct file));
/* Initialise dentry for image */
d->refcnt = 0;
d->vnode = v;
d->parent = sb->root;
strncpy(d->name, img->name, VFS_DENTRY_NAME_MAX);
INIT_LIST_HEAD(&d->child);
INIT_LIST_HEAD(&d->children);
list_add(&d->child, &sb->root->children);
/* Initialise vnode for image */
v->refcnt = 0;
v->id = img->phys_start;
v->size = img->phys_end - img->phys_start;
INIT_LIST_HEAD(&v->dirents);
list_add(&d->v_ref, &v->dirents);
/* Initialise file struct for image */
f->refcnt = 0;
f->dentry = d;
img_d++;
img_vn++;
img_f++;
}
}
void bootfs_init_root(struct dentry *r)
{
@@ -43,8 +109,8 @@ void bootfs_init_root(struct dentry *r)
struct superblock *bootfs_init_sb(struct superblock *sb)
{
sb->root = &bootfs_root;
sb->root->vnode = &bootfs_rootvn;
sb->root = malloc(sizeof(struct dentry));
sb->root->vnode = malloc(sizeof(struct vnode));
bootfs_init_root(&sb->root);
@@ -75,8 +141,7 @@ struct file_system_type bootfs_type = {
void init_bootfs()
{
struct superblock *sb;
bootfs_init_sb(&bootfs_sb);
sb = bootfs_type.get_sb();
bootfs_populate(&bootfs_sb);
}

408
tasks/fs0/src/malloc.c Normal file
View File

@@ -0,0 +1,408 @@
/*****************************************************************************
Simple malloc
Chris Giese <geezer@execpc.com> http://www.execpc.com/~geezer
Release date: Oct 30, 2002
This code is public domain (no copyright).
You can do whatever you want with it.
Features:
- First-fit
- free() coalesces adjacent free blocks
- Uses variable-sized heap, enlarged with kbrk()/sbrk() function
- Does not use mmap()
- Can be easily modified to use fixed-size heap
- Works with 16- or 32-bit compilers
Build this program with either of the two main() functions, then run it.
Messages that indicate a software error will contain three asterisks (***).
*****************************************************************************/
#include <string.h> /* memcpy(), memset() */
#include <stdio.h> /* printf() */
#define _32BIT 1
/* use small (32K) heap for 16-bit compilers,
large (500K) heap for 32-bit compilers */
#if defined(_32BIT)
#define HEAP_SIZE 500000uL
#else
#define HEAP_SIZE 32768u
#endif
#define MALLOC_MAGIC 0x6D92 /* must be < 0x8000 */
typedef struct _malloc /* Turbo C DJGPP */
{
size_t size; /* 2 bytes 4 bytes */
struct _malloc *next; /* 2 bytes 4 bytes */
unsigned magic : 15; /* 2 bytes total 4 bytes total */
unsigned used : 1;
} malloc_t; /* total 6 bytes 12 bytes */
static char *g_heap_bot, *g_kbrk, *g_heap_top;
/*****************************************************************************
*****************************************************************************/
static void dump_heap(void)
{
unsigned blks_used = 0, blks_free = 0;
size_t bytes_used = 0, bytes_free = 0;
malloc_t *m;
int total;
printf("===============================================\n");
for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)
{
printf("blk %5p: %6u bytes %s\n", m,
m->size, m->used ? "used" : "free");
if(m->used)
{
blks_used++;
bytes_used += m->size;
}
else
{
blks_free++;
bytes_free += m->size;
}
}
printf("blks: %6u used, %6u free, %6u total\n", blks_used,
blks_free, blks_used + blks_free);
printf("bytes: %6u used, %6u free, %6u total\n", bytes_used,
bytes_free, bytes_used + bytes_free);
printf("g_heap_bot=0x%p, g_kbrk=0x%p, g_heap_top=0x%p\n",
g_heap_bot, g_kbrk, g_heap_top);
total = (bytes_used + bytes_free) +
(blks_used + blks_free) * sizeof(malloc_t);
if(total != g_kbrk - g_heap_bot)
printf("*** some heap memory is not accounted for\n");
printf("===============================================\n");
}
/*****************************************************************************
POSIX sbrk() looks like this
void *sbrk(int incr);
Mine is a bit different so I can signal the calling function
if more memory than desired was allocated (e.g. in a system with paging)
If your kbrk()/sbrk() always allocates the amount of memory you ask for,
this code can be easily changed.
int brk( void *sbrk( void *kbrk(
function void *adr); int delta); int *delta);
---------------------- ------------ ------------ -------------
POSIX? yes yes NO
return value if error -1 -1 NULL
get break value . sbrk(0) int x=0; kbrk(&x);
set break value to X brk(X) sbrk(X - sbrk(0)) int x=X, y=0; kbrk(&x) - kbrk(&y);
enlarge heap by N bytes . sbrk(+N) int x=N; kbrk(&x);
shrink heap by N bytes . sbrk(-N) int x=-N; kbrk(&x);
can you tell if you're
given more memory
than you wanted? no no yes
*****************************************************************************/
static void *kbrk(int *delta)
{
static char heap[HEAP_SIZE];
/**/
char *new_brk, *old_brk;
/* heap doesn't exist yet */
if(g_heap_bot == NULL)
{
g_heap_bot = g_kbrk = heap;
g_heap_top = g_heap_bot + HEAP_SIZE;
}
new_brk = g_kbrk + (*delta);
/* too low: return NULL */
if(new_brk < g_heap_bot)
return NULL;
/* too high: return NULL */
if(new_brk >= g_heap_top)
return NULL;
/* success: adjust brk value... */
old_brk = g_kbrk;
g_kbrk = new_brk;
/* ...return actual delta... (for this sbrk(), they are the same)
(*delta) = (*delta); */
/* ...return old brk value */
return old_brk;
}
/*****************************************************************************
kmalloc() and kfree() use g_heap_bot, but not g_kbrk nor g_heap_top
*****************************************************************************/
void *kmalloc(size_t size)
{
unsigned total_size;
malloc_t *m, *n;
int delta;
if(size == 0)
return NULL;
total_size = size + sizeof(malloc_t);
/* search heap for free block (FIRST FIT) */
m = (malloc_t *)g_heap_bot;
/* g_heap_bot == 0 == NULL if heap does not yet exist */
if(m != NULL)
{
if(m->magic != MALLOC_MAGIC)
// panic("kernel heap is corrupt in kmalloc()");
{
printf("*** kernel heap is corrupt in kmalloc()\n");
return NULL;
}
for(; m->next != NULL; m = m->next)
{
if(m->used)
continue;
/* size == m->size is a perfect fit */
if(size == m->size)
m->used = 1;
else
{
/* otherwise, we need an extra sizeof(malloc_t) bytes for the header
of a second, free block */
if(total_size > m->size)
continue;
/* create a new, smaller free block after this one */
n = (malloc_t *)((char *)m + total_size);
n->size = m->size - total_size;
n->next = m->next;
n->magic = MALLOC_MAGIC;
n->used = 0;
/* reduce the size of this block and mark it used */
m->size = size;
m->next = n;
m->used = 1;
}
return (char *)m + sizeof(malloc_t);
}
}
/* use kbrk() to enlarge (or create!) heap */
delta = total_size;
n = kbrk(&delta);
/* uh-oh */
if(n == NULL)
return NULL;
if(m != NULL)
m->next = n;
n->size = size;
n->magic = MALLOC_MAGIC;
n->used = 1;
/* did kbrk() return the exact amount of memory we wanted?
cast to make "gcc -Wall -W ..." shut the hell up */
if((int)total_size == delta)
n->next = NULL;
else
{
/* it returned more than we wanted (it will never return less):
create a new, free block */
m = (malloc_t *)((char *)n + total_size);
m->size = delta - total_size - sizeof(malloc_t);
m->next = NULL;
m->magic = MALLOC_MAGIC;
m->used = 0;
n->next = m;
}
return (char *)n + sizeof(malloc_t);
}
/*****************************************************************************
*****************************************************************************/
void kfree(void *blk)
{
malloc_t *m, *n;
/* get address of header */
m = (malloc_t *)((char *)blk - sizeof(malloc_t));
if(m->magic != MALLOC_MAGIC)
// panic("attempt to kfree() block at 0x%p "
// "with bad magic value", blk);
{
printf("*** attempt to kfree() block at 0x%p "
"with bad magic value\n", blk);
return;
}
/* find this block in the heap */
n = (malloc_t *)g_heap_bot;
if(n->magic != MALLOC_MAGIC)
// panic("kernel heap is corrupt in kfree()");
{
printf("*** kernel heap is corrupt in kfree()\n");
return;
}
for(; n != NULL; n = n->next)
{
if(n == m)
break;
}
/* not found? bad pointer or no heap or something else? */
if(n == NULL)
// panic("attempt to kfree() block at 0x%p "
// "that is not in the heap", blk);
{
printf("*** attempt to kfree() block at 0x%p "
"that is not in the heap\n", blk);
return;
}
/* free the block */
m->used = 0;
/* coalesce adjacent free blocks
Hard to spell, hard to do */
for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)
{
while(!m->used && m->next != NULL && !m->next->used)
{
/* resize this block */
m->size += sizeof(malloc_t) + m->next->size;
/* merge with next block */
m->next = m->next->next;
}
}
}
/*****************************************************************************
*****************************************************************************/
void *krealloc(void *blk, size_t size)
{
void *new_blk;
malloc_t *m;
/* size == 0: free block */
if(size == 0)
{
if(blk != NULL)
kfree(blk);
new_blk = NULL;
}
else
{
/* allocate new block */
new_blk = kmalloc(size);
/* if allocation OK, and if old block exists, copy old block to new */
if(new_blk != NULL && blk != NULL)
{
m = (malloc_t *)((char *)blk - sizeof(malloc_t));
if(m->magic != MALLOC_MAGIC)
// panic("attempt to krealloc() block at "
// "0x%p with bad magic value", blk);
{
printf("*** attempt to krealloc() block at "
"0x%p with bad magic value\n", blk);
return NULL;
}
/* copy minimum of old and new block sizes */
if(size > m->size)
size = m->size;
memcpy(new_blk, blk, size);
/* free the old block */
kfree(blk);
}
}
return new_blk;
}
/*****************************************************************************
*****************************************************************************/
#if 0
#include <stdlib.h> /* rand() */
#define SLOTS 17
int main(void)
{
unsigned lifetime[SLOTS];
void *blk[SLOTS];
int i, j, k;
dump_heap();
memset(lifetime, 0, sizeof(lifetime));
memset(blk, 0, sizeof(blk));
for(i = 0; i < 1000; i++)
{
printf("Pass %6u\n", i);
for(j = 0; j < SLOTS; j++)
{
/* age the block */
if(lifetime[j] != 0)
{
(lifetime[j])--;
continue;
}
/* too old; free it */
if(blk[j] != NULL)
{
kfree(blk[j]);
blk[j] = NULL;
}
/* alloc new block of random size
Note that size_t==unsigned, but kmalloc() uses integer math,
so block size must be positive integer */
#if defined(_32BIT)
k = rand() % 40960 + 1;
#else
k = rand() % 4096 + 1;
#endif
blk[j] = kmalloc(k);
if(blk[j] == NULL)
printf("failed to alloc %u bytes\n", k);
else
/* give it a random lifetime 0-20 */
lifetime[j] = rand() % 21;
}
}
/* let's see what we've wrought */
printf("\n\n");
dump_heap();
/* free everything */
for(j = 0; j < SLOTS; j++)
{
if(blk[j] != NULL)
{
kfree(blk[j]);
blk[j] = NULL;
}
(lifetime[j]) = 0;
}
/* after all that, we should have a single, unused block */
dump_heap();
return 0;
}
/*****************************************************************************
*****************************************************************************/
int main(void)
{
void *b1, *b2, *b3;
dump_heap();
b1 = kmalloc(42);
dump_heap();
b2 = kmalloc(23);
dump_heap();
b3 = kmalloc(7);
dump_heap();
b2 = krealloc(b2, 24);
dump_heap();
kfree(b1);
dump_heap();
b1 = kmalloc(5);
dump_heap();
kfree(b2);
dump_heap();
kfree(b3);
dump_heap();
kfree(b1);
dump_heap();
return 0;
}
#endif