retire nonsymbolic rootdev, dev2name
[minix.git] / lib / libddekit / src / mem.c
blob769c3a133f7a41dc06de7c17f09656749ec6db86
1 #include "common.h"
3 #include <ddekit/lock.h>
4 #include <ddekit/memory.h>
5 #include <ddekit/panic.h>
6 #include <ddekit/pgtab.h>
7 #include <ddekit/inline.h>
8 #include <ddekit/types.h>
10 #ifdef DDEKIT_DEBUG_MEM
11 #undef DDEBUG
12 #define DDEBUG DDEKIT_DEBUG_MEM
13 #endif
14 #include "debug.h"
15 #include "util.h"
17 #define SLAB_SIZE (4096*4)
19 struct ddekit_slab;
21 struct ddekit_slab_slab {
22 struct ddekit_slab * cache;
23 unsigned long free;
24 void *objects;
25 void *mem;
26 struct ddekit_slab_slab *next;
27 struct ddekit_slab_slab *prev;
30 struct ddekit_slab {
31 ddekit_lock_t lock;
32 void * data; /* user pointer */
33 int contiguous; /* is it coniguous mem*/
34 unsigned size; /* the size of he objects */
35 unsigned number; /* the number of objects stored per slab */
36 struct ddekit_slab_slab full;
37 struct ddekit_slab_slab partial;
38 struct ddekit_slab_slab empty;
41 static void ddekit_slab_lock(struct ddekit_slab * sc);
42 static void ddekit_slab_unlock(struct ddekit_slab * sc);
43 static struct ddekit_slab_slab * ddekit_slab_find_slab(struct
44 ddekit_slab * sc, void * obj);
45 static void ddekit_slab_slab_insert(struct ddekit_slab_slab *list,
46 struct ddekit_slab_slab *s);
47 static void ddekit_slab_slab_remove(struct ddekit_slab_slab *s);
48 static void ddekit_slab_grow(struct ddekit_slab * sc);
49 static void *ddekit_slab_getobj(struct ddekit_slab_slab *s);
50 static void ddekit_slab_free_slab(struct ddekit_slab_slab * sl, int
51 cont);
53 /******************************************************************************
54 * ddekit_simple_malloc *
55 *****************************************************************************/
56 void *ddekit_simple_malloc(unsigned size)
58 /* Simple memory allocation... malloc and free should be ok... */
59 void * r = malloc(size);
60 if (!r) {
61 ddekit_panic("out of mem?");
63 DDEBUG_MSG_VERBOSE("%p", r);
64 return r;
67 /******************************************************************************
68 * ddekit_simple_free *
69 *****************************************************************************/
70 void ddekit_simple_free(void *p)
72 DDEBUG_MSG_VERBOSE("%p", p);
73 free(p);
76 /******************************************************************************
77 * ddekit_large_malloc *
78 *****************************************************************************/
79 void *ddekit_large_malloc(int size)
81 ddekit_addr_t phys;
82 /* allocate a piece of coniguous memory */
83 void * r = alloc_contig(size, AC_ALIGN4K, &phys);
84 if (!r) {
85 ddekit_panic("out of mem?");
87 ddekit_pgtab_set_region_with_size(r, phys, size, PTE_TYPE_LARGE);
88 DDEBUG_MSG_VERBOSE("%p, phys: %p, size: %p.",r, phys, size);
89 DDEBUG_MSG_VERBOSE("%p", r);
90 return r;
93 /******************************************************************************
94 * ddekit_large_free *
95 *****************************************************************************/
96 void ddekit_large_free(void *p)
98 unsigned len;
99 DDEBUG_MSG_VERBOSE("get size of region %x", p);
100 len= ddekit_pgtab_get_size(p);
101 DDEBUG_MSG_VERBOSE("freeing %x, len %d...", p , len);
102 ddekit_pgtab_clear_region(p, 0); /* type is not used here... */
103 DDEBUG_MSG_VERBOSE("cleared region", p , len);
104 free_contig(p, len);
105 DDEBUG_MSG_VERBOSE("freed mem", p , len);
106 DDEBUG_MSG_VERBOSE("%p", p);
109 /******************************************************************************
110 * ddekit_contig_malloc *
111 *****************************************************************************/
112 void *ddekit_contig_malloc(unsigned long size, unsigned long low,
113 unsigned long high, unsigned long aligment,
114 unsigned long boundary)
116 WARN_UNIMPL;
117 return 0;
120 /******************************************************************************
121 * ddekit_slab_lock *
122 *****************************************************************************/
123 static DDEKIT_INLINE void ddekit_slab_lock(struct ddekit_slab * sc) {
124 ddekit_lock_lock(&sc->lock);
127 /******************************************************************************
128 * ddekit_slab_unlock *
129 *****************************************************************************/
130 static DDEKIT_INLINE void ddekit_slab_unlock(struct ddekit_slab * sc) {
131 ddekit_lock_unlock(&sc->lock);
134 /******************************************************************************
135 * ddekit_slab_find_slab *
136 *****************************************************************************/
137 static struct ddekit_slab_slab *
138 ddekit_slab_find_slab(struct ddekit_slab * sc, void * obj)
141 struct ddekit_slab_slab *s;
143 for( s = sc->full.next; s!=&sc->full; s = s->next )
145 if (s->mem <= obj && obj < s->mem+(SLAB_SIZE))
147 return s;
151 for( s = sc->partial.next; s!=&sc->partial; s = s->next )
153 if (s->mem <= obj && obj < s->mem+(SLAB_SIZE))
155 return s;
159 return 0;
162 /******************************************************************************
163 * ddekit_slab_slab_insert *
164 *****************************************************************************/
165 static void ddekit_slab_slab_insert(struct ddekit_slab_slab *list,
166 struct ddekit_slab_slab *s)
168 s->prev = list;
169 s->next = list->next;
170 list->next->prev = s;
171 list->next = s;
174 /******************************************************************************
175 * ddekit_slab_slab_remove *
176 *****************************************************************************/
177 static void ddekit_slab_slab_remove(struct ddekit_slab_slab *s)
179 s->next->prev = s->prev;
180 s->prev->next = s->next;
181 s->next = s->prev = 0;
185 /******************************************************************************
186 * ddekit_slab_grow *
187 *****************************************************************************/
188 static void ddekit_slab_grow(struct ddekit_slab *sc)
191 * NOTE:
192 * As it doesn't seem to make problems ddekit_slabs are disregarding
193 * alignment. However this should be revisited, maybe this leads to
194 * performance degregation somewhere.
195 * Further the ddekit_slab doesn't have to be real slab, as the entries are
196 * initialized in the personalized DDEs. (slab is simple the wrong name.)
198 int i;
199 char *p;
200 void **p1;
201 struct ddekit_slab_slab *s;
203 /* allocate slab control structure */
205 s = (struct ddekit_slab_slab *)
206 ddekit_simple_malloc(sizeof(struct ddekit_slab_slab));
208 s->cache = sc;
210 if(sc->contiguous)
211 s->mem = ddekit_large_malloc(SLAB_SIZE);
212 else
213 s->mem = ddekit_simple_malloc(SLAB_SIZE);
215 /* setup the object list */
217 s->free = sc->number;
219 /* put obj into list */
220 p1 = s->mem;
221 *p1 = s->mem;
222 s->objects = p1;
224 DDEBUG_MSG_VERBOSE("obj size: %d, memory at: %p , first obj: %p, %p ",
225 sc->size, s->mem, s->objects);
227 for (i = 0; i < s->free; i++)
229 p = *p1;
230 p1 = (void **) (p + sc->size);
232 if ( i != s->free-1 )
234 *p1 = p1+1;
235 DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1);
237 else
239 *p1 = 0;
240 DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1);
244 /* add new slab to free list */
245 ddekit_slab_slab_insert(&sc->empty, s);
249 /******************************************************************************
250 * ddekit_slab_getobj *
251 *****************************************************************************/
252 static void *ddekit_slab_getobj(struct ddekit_slab_slab *s)
254 struct ddekit_slab *sc;
255 void *ret = 0;
257 sc = s->cache;
258 ret = s->objects;
260 /* get pointer to next object */
262 s->objects = *(void **)((char *) ret + sc->size);
263 s->free--;
265 DDEBUG_MSG_VERBOSE("old: %p new: %p", ret, s->objects);
267 /* if no more objects move to full */
269 if (!s->free)
271 ddekit_slab_slab_remove(s);
272 ddekit_slab_slab_insert(&sc->full,s);
275 if (s->free == sc->number-1)
277 ddekit_slab_slab_remove(s);
278 ddekit_slab_slab_insert(&sc->partial,s);
281 return ret;
284 /******************************************************************************
285 * ddekit_slab_alloc *
286 *****************************************************************************/
287 void *ddekit_slab_alloc(struct ddekit_slab * sc)
289 struct ddekit_slab_slab *s=0;
291 ddekit_slab_lock(sc);
293 DDEBUG_MSG_VERBOSE("from slab %p", sc);
295 /* first try from partial */
296 if (sc->partial.next != &sc->partial) {
297 DDEBUG_MSG_VERBOSE("from slab %p partial (next=%p)", sc,sc->partial.next);
298 s = sc->partial.next;
301 /* must grow? */
302 if (!s && (sc->empty.next == &sc->empty )){
303 DDEBUG_MSG_VERBOSE("slab %p has to grow", sc);
304 ddekit_slab_grow(sc);
307 /* take from free? */
308 if (!s) {
309 DDEBUG_MSG_VERBOSE("from slab %p empty", sc);
310 s = sc->empty.next;
313 ddekit_slab_unlock(sc);
315 return ddekit_slab_getobj(s);
318 /******************************************************************************
319 * ddekit_slab_free *
320 *****************************************************************************/
321 void ddekit_slab_free(struct ddekit_slab *sc, void* obj)
323 void **p;
325 struct ddekit_slab_slab *s = 0;
327 ddekit_slab_lock(sc);
328 /* first find slab the obj came from */
330 s = ddekit_slab_find_slab(sc, obj);
332 p = (void **)((char *) obj + sc->size);
334 *p= s->objects;
335 s->objects=obj;
337 DDEBUG_MSG_VERBOSE("old: %p, new: %p",*p,s->objects );
339 s->free++;
341 if (s->free == sc->number) {
342 ddekit_slab_slab_remove(s);
343 ddekit_slab_slab_insert(&sc->empty, s);
346 if (s->free == 1) {
347 ddekit_slab_slab_remove(s);
348 ddekit_slab_slab_insert(&sc->partial, s);
351 ddekit_slab_unlock(sc);
354 /******************************************************************************
355 * ddekit_slab_set_data *
356 *****************************************************************************/
357 void ddekit_slab_set_data(struct ddekit_slab * sc, void *data)
359 ddekit_slab_lock(sc);
360 sc->data = data;
361 ddekit_slab_unlock(sc);
364 /******************************************************************************
365 * ddekit_slab_get_data *
366 *****************************************************************************/
367 void *ddekit_slab_get_data (struct ddekit_slab *sc)
369 void *ret;
370 ddekit_slab_lock(sc);
371 ret=sc->data;
372 ddekit_slab_unlock(sc);
373 return ret;
377 /******************************************************************************
378 * ddekit_slab_init *
379 *****************************************************************************/
380 struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous)
383 struct ddekit_slab * sc = 0;
385 sc = (struct ddekit_slab *)
386 ddekit_simple_malloc(sizeof(struct ddekit_slab));
388 sc->data = 0;
389 sc->contiguous = contiguous;
390 sc->size = size;
391 sc->number = SLAB_SIZE/(size+sizeof(void*));
393 if (sc->number == 0) {
394 ddekit_panic("objects too big!");
397 sc->empty.next = sc->empty.prev = &sc->empty;
398 sc->partial.next = sc->partial.prev = &sc->partial;
399 sc->full.next = sc->full.prev = &sc->full;
401 ddekit_lock_init(&sc->lock);
403 DDEBUG_MSG_VERBOSE("initialzed slab cache %p: size %x, number %d ",
404 sc, sc->size, sc->number);
406 DDEBUG_MSG_VERBOSE("partial %p next %p", &sc->partial, sc->partial.next);
407 return sc ;
412 /******************************************************************************
413 * ddekit_slab_free_slab *
414 *****************************************************************************/
415 static void ddekit_slab_free_slab(struct ddekit_slab_slab * sl, int cont)
418 struct ddekit_slab_slab *s,*t;
420 if (!sl) {
421 ddekit_panic("no slab to free!");
424 for ( s = sl->next; s != sl; )
426 DDEBUG_MSG_VERBOSE("cont: %d, %p, s->mem", cont, s->mem);
427 if(cont)
429 ddekit_large_free(s->mem);
431 else
433 ddekit_simple_free(s->mem);
435 t = s;
436 s = s->next;
437 ddekit_simple_free(t);
442 /******************************************************************************
443 * ddekit_slab_destroy *
444 *****************************************************************************/
445 void ddekit_slab_destroy(struct ddekit_slab *sc)
447 DDEBUG_MSG_VERBOSE("%p full", sc);
448 ddekit_slab_free_slab(&sc->full,sc->contiguous);
450 DDEBUG_MSG_VERBOSE("%p empty", sc);
451 ddekit_slab_free_slab(&sc->empty,sc->contiguous);
453 DDEBUG_MSG_VERBOSE("%p partial", sc);
454 ddekit_slab_free_slab(&sc->partial,sc->contiguous);
456 ddekit_lock_deinit(&sc->lock);
458 ddekit_simple_free(sc);