9os

Experimental kernel using plan9 ideas for embedded device
git clone git://git.simple-cc.org/9os
Log | Files | Refs | README | LICENSE

alloc.c (4321B)


      1 #include <os9/os9.h>
      2 
      3 #include <libk.h>
      4 
      5 #include <errno.h>
      6 #include <string.h>
      7 
      8 union bucket {
      9 	long long ll;
     10 	uintptr_t up;
     11 	union bucket *next;
     12 };
     13 
     14 struct pool {
     15 	void *list;
     16 	mutex_t m;
     17 };
     18 
     19 static union bucket *heap;
     20 static struct pool bufpool;
     21 static struct pool pagepool;
     22 static struct pool nspool;
     23 static struct pool mappool;
     24 static struct pool fdspool;
     25 static struct pool chanpool;
     26 static struct pool mpointpool;
     27 
     28 void
     29 freeb(void *bp)
     30 {
     31 	union bucket *p = bp;
     32 
     33 	if (!p)
     34 		return;
     35 
     36 	lock(&bufpool.m);
     37 	p->next = bufpool.list;
     38 	bufpool.list = p;
     39 	unlock(&bufpool.m);
     40 }
     41 
     42 void *
     43 allocb(void)
     44 {
     45 	union bucket *bp = NULL;
     46 
     47 	lock(&bufpool.m);
     48 	if (!bufpool.list) {
     49 		seterror(ENOMEM);
     50 	} else {
     51 		bp = bufpool.list;
     52 		bufpool.list = bp->next;
     53 	}
     54 	unlock(&bufpool.m);
     55 
     56 	return bp;
     57 }
     58 
     59 void *
     60 alloc(size_t size)
     61 {
     62 	size_t n;
     63 	static size_t used;
     64 	static mutex_t m;
     65 	void  *bp;
     66 
     67 	if (size == 0) {
     68 		seterror(EINVAL);
     69 		return NULL;
     70 	}
     71 
     72 	lock(&m);
     73 	n = (size-1) / sizeof(union bucket) + 1;
     74 	size = n * sizeof(union bucket);
     75 
     76 	if (used > PAGESIZE*HEAPSIZ - size) {
     77 		bp = NULL;
     78 		seterror(ENOMEM);
     79 	} else {
     80 		bp = (char *) heap + used;
     81 		used += size;
     82 	}
     83 	unlock(&m);
     84 
     85 	return bp;
     86 }
     87 
     88 Nspace *
     89 allocspace(void)
     90 {
     91 	Nspace *ns;
     92 
     93 	lock(&nspool.m);
     94 	if (nspool.list) {
     95 		ns = nspool.list;
     96 		nspool.list = ns->next;
     97 	} else {
     98 		if ((ns = alloc(sizeof(*ns))) == NULL)
     99 			return NULL;
    100 	}
    101 	unlock(&nspool.m);
    102 
    103 	return ns;
    104 }
    105 
    106 void
    107 freespace(Nspace *ns)
    108 {
    109 	lock(&nspool.m);
    110 	ns->next = nspool.list;
    111 	nspool.list = ns;
    112 	unlock(&nspool.m);
    113 }
    114 
    115 Map *
    116 allocmap(void)
    117 {
    118 	Map *mp;
    119 
    120 	lock(&mappool.m);
    121 	if (mappool.list) {
    122 		mp = mappool.list;
    123 		mappool.list = mp->next;
    124 	} else {
    125 		if ((mp = alloc(sizeof(*mp))) == NULL)
    126 			return NULL;
    127 	}
    128 	unlock(&mappool.m);
    129 
    130 	return mp;
    131 }
    132 
    133 void
    134 freemap(Map *mp)
    135 {
    136         lock(&mappool.m);
    137         mp->next = mappool.list;
    138         mappool.list = mp;
    139         unlock(&mappool.m);
    140 }
    141 
    142 Fdset *
    143 allocfds(void)
    144 {
    145 	Fdset *fds;
    146 
    147 	lock(&fdspool.m);
    148 	if (fdspool.list) {
    149 		fds = fdspool.list;
    150 		fdspool.list = fds->next;
    151 	} else {
    152 		if ((fds = alloc(sizeof(*fds))) == NULL)
    153 			return NULL;
    154 	}
    155 	unlock(&fdspool.m);
    156 
    157 	return fds;
    158 }
    159 
    160 void
    161 freefds(Fdset *fds)
    162 {
    163 	if (!fds)
    164 		return;
    165 
    166 	lock(&fdspool.m);
    167 	fds->next = fdspool.list;
    168 	fdspool.list = fds;
    169 	unlock(&fdspool.m);
    170 }
    171 
    172 /*
    173  * This functions is always called with the page pool locked
    174  */
    175 static int
    176 morepages(void)
    177 {
    178 	Page *p, *bp;
    179 
    180 	if (pagepool.list)
    181 		return 1;
    182 
    183 	if ((bp = allocb()) == NULL)
    184 		return 0;
    185 
    186 	for (p = bp; p < &bp[PAGESIZE/sizeof(Page)]; ++p)
    187 		p->next = p+1;
    188 	p->next = NULL;
    189 
    190 	pagepool.list = bp;
    191 
    192 	return 1;
    193 }
    194 
    195 Page *
    196 allocp(phyaddr_t pa)
    197 {
    198 	int alloc = 0;
    199 	void *bp = NULL;
    200 	Page *p;
    201 
    202 	if (pa == -1) {
    203 		if ((bp = allocb()) == NULL)
    204 			return NULL;
    205 		pa = (phyaddr_t) PMEM(bp);
    206 		alloc = 1;
    207 	}
    208 
    209 	lock(&pagepool.m);
    210 
    211 	if (!morepages()) {
    212 		freeb(bp);
    213 		unlock(&pagepool.m);
    214 		return NULL;
    215 	}
    216 
    217 	p = pagepool.list;
    218 	pagepool.list = p->next;
    219 
    220 	unlock(&pagepool.m);
    221 
    222 	p->pa = pa;
    223 	p->va = -1;
    224 	p->allocated = alloc;
    225 	p->next = NULL;
    226 
    227 	return p;
    228 }
    229 
    230 void
    231 freep(Page *p)
    232 {
    233 	if (!p)
    234 		return;
    235 
    236 	if (p->allocated)
    237 		freeb(VMEM(p->pa));
    238 
    239 	lock(&pagepool.m);
    240 	p->next = pagepool.list;
    241 	pagepool.list = p;
    242 	unlock(&pagepool.m);
    243 }
    244 
    245 Chan *
    246 allocchan(void)
    247 {
    248 	Chan *c;
    249 
    250 	lock(&chanpool.m);
    251 	if (chanpool.list) {
    252 		c = chanpool.list;
    253 		chanpool.list = c->next;
    254 	} else {
    255 		if ((c = alloc(sizeof(*c))) == NULL)
    256 			return NULL;
    257 	}
    258 	unlock(&chanpool.m);
    259 
    260 	return c;
    261 }
    262 
    263 void
    264 freechan(Chan *c)
    265 {
    266 	if (!c)
    267 		return;
    268 
    269 	lock(&chanpool.m);
    270 	c->next = chanpool.list;
    271 	chanpool.list = c;
    272 	unlock(&chanpool.m);
    273 }
    274 
    275 Mpoint *
    276 allocmpoint(void)
    277 {
    278 	Mpoint *mp;
    279 
    280 	lock(&mpointpool.m);
    281 	if (mpointpool.list) {
    282 		mp = mpointpool.list;
    283 		mpointpool.list = mp->next;
    284 	} else {
    285 		if ((mp = alloc(sizeof(*mp))) == NULL)
    286 			return NULL;
    287 	}
    288 	unlock(&mpointpool.m);
    289 
    290 	return mp;
    291 }
    292 
    293 void
    294 freempoint(Mpoint *mp)
    295 {
    296 	if (!mp)
    297 		return;
    298 
    299 	lock(&mpointpool.m);
    300 	mp->next = mpointpool.list;
    301 	mpointpool.list = mp;
    302 	unlock(&mpointpool.m);
    303 }
    304 
    305 void
    306 ialloc(void)
    307 {
    308 	int i;
    309 	union bucket *bp, *prev;
    310 
    311 	heap = (union bucket *) buffertab;
    312 
    313 	prev = NULL;
    314 	for (i = HEAPSIZ; i < NR_BUFFERS; i++) {
    315 		bp = (union bucket *) buffertab[i];
    316 		bp->next = prev;
    317 		prev = bp;
    318 	}
    319 	bufpool.list = bp;
    320 
    321 	kprint("%d available buffers: %d heap, %d buffer pool\n",
    322 	       NR_BUFFERS, HEAPSIZ, NR_BUFFERS - HEAPSIZ);
    323 }