summaryrefslogtreecommitdiff
path: root/libddekit/malloc.c
blob: 5f0ae0fc4e26dd3879cab2e045a144b19616934e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
 * \brief   Simple allocator implementation
 * \author  Christian Helmuth
 * \date    2006-10-30
 *
 * This simple allocator provides malloc() and free() using dm_mem dataspaces
 * as backing store. The actual list-based allocator implementation is from
 * l4util resp. Fiasco.
 *
 * For large allocations and slab-based OS-specific allocators
 * ddekit_large_malloc and ddekit_slab_*() should be used. The blocks
 * allocated via this allocator CANNOT be used for DMA or other device
 * operations, i.e., there exists no virt->phys mapping.
 *
 * FIXME check thread-safety and add locks where appropriate
 */

#include <l4/dde/ddekit/memory.h>
#include <l4/dde/ddekit/printf.h>
#include <l4/dde/ddekit/panic.h>

#include <l4/sys/consts.h>
#include <l4/util/list_alloc.h>
#include <l4/dm_mem/dm_mem.h>
#include <l4/lock/lock.h>

/* configuration */
#define ALLOC_SIZE     (4 * L4_PAGESIZE)

/* malloc pool is a list allocator */
static l4la_free_t *malloc_pool;
static l4lock_t     malloc_lock = L4LOCK_UNLOCKED;


/**
 * Allocate memory block via simple allocator
 *
 * \param size  block size
 * \return pointer to new memory block
 *
 * The blocks allocated via this allocator CANNOT be used for DMA or other
 * device operations, i.e., there exists no virt->phys mapping.
 *
 * Each chunk stores its size in the first word for free() to work.
 */
void *ddekit_simple_malloc(unsigned size)
{
	l4lock_lock(&malloc_lock);
	/* we store chunk size in the first word of the chunk */
	size += sizeof(unsigned);

	/* try to allocate */
	unsigned *p = l4la_alloc(&malloc_pool, size, 0);

	/* fill pool if allocation fails */
	if (!p) {
		/* size of allocated dataspace is at least ALLOC_SIZE */
		unsigned ds_size = l4_round_page(size);
		ds_size = (ds_size > ALLOC_SIZE) ? ds_size : ALLOC_SIZE;

		void *res = l4dm_mem_allocate_named(ds_size, L4RM_MAP, "ddekit malloc");
		if (!res) 
			p = NULL;
		else
		{
			l4la_free(&malloc_pool, res, ds_size);
			p = l4la_alloc(&malloc_pool, size, 0);
		}
	}

	/* store chunk size */
	if (p) {
		*p = size;
		p++;
	}

	l4lock_unlock(&malloc_lock);
	return p;
}


/**
 * Free memory block via simple allocator
 *
 * \param p  pointer to memory block
 */
void ddekit_simple_free(void *p)
{
	l4lock_lock(&malloc_lock);
	unsigned *chunk = (unsigned *)p - 1;
	if (p)
		l4la_free(&malloc_pool, chunk, *chunk);
	l4lock_unlock(&malloc_lock);
}