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 }