| 1352 | } |
| 1353 | |
| 1354 | int |
| 1355 | vmem_xalloc(vmem_t *vm, const vmem_size_t size0, vmem_size_t align, |
| 1356 | const vmem_size_t phase, const vmem_size_t nocross, |
| 1357 | const vmem_addr_t minaddr, const vmem_addr_t maxaddr, int flags, |
| 1358 | vmem_addr_t *addrp) |
| 1359 | { |
| 1360 | const vmem_size_t size = vmem_roundup_size(vm, size0); |
| 1361 | struct vmem_freelist *list; |
| 1362 | struct vmem_freelist *first; |
| 1363 | struct vmem_freelist *end; |
| 1364 | bt_t *bt; |
| 1365 | int error; |
| 1366 | int strat; |
| 1367 | |
| 1368 | flags &= VMEM_FLAGS; |
| 1369 | strat = flags & VMEM_FITMASK; |
| 1370 | MPASS(size0 > 0); |
| 1371 | MPASS(size > 0); |
| 1372 | MPASS(strat == M_BESTFIT || strat == M_FIRSTFIT || strat == M_NEXTFIT); |
| 1373 | MPASS((flags & (M_NOWAIT|M_WAITOK)) != (M_NOWAIT|M_WAITOK)); |
| 1374 | if ((flags & M_NOWAIT) == 0) |
| 1375 | WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "vmem_xalloc"); |
| 1376 | MPASS((align & vm->vm_quantum_mask) == 0); |
| 1377 | MPASS((align & (align - 1)) == 0); |
| 1378 | MPASS((phase & vm->vm_quantum_mask) == 0); |
| 1379 | MPASS((nocross & vm->vm_quantum_mask) == 0); |
| 1380 | MPASS((nocross & (nocross - 1)) == 0); |
| 1381 | MPASS((align == 0 && phase == 0) || phase < align); |
| 1382 | MPASS(nocross == 0 || nocross >= size); |
| 1383 | MPASS(minaddr <= maxaddr); |
| 1384 | MPASS(!VMEM_CROSS_P(phase, phase + size - 1, nocross)); |
| 1385 | if (strat == M_NEXTFIT) |
| 1386 | MPASS(minaddr == VMEM_ADDR_MIN && maxaddr == VMEM_ADDR_MAX); |
| 1387 | |
| 1388 | if (align == 0) |
| 1389 | align = vm->vm_quantum_mask + 1; |
| 1390 | *addrp = 0; |
| 1391 | |
| 1392 | /* |
| 1393 | * Next-fit allocations don't use the freelists. |
| 1394 | */ |
| 1395 | if (strat == M_NEXTFIT) |
| 1396 | return (vmem_xalloc_nextfit(vm, size0, align, phase, nocross, |
| 1397 | flags, addrp)); |
| 1398 | |
| 1399 | end = &vm->vm_freelist[VMEM_MAXORDER]; |
| 1400 | /* |
| 1401 | * choose a free block from which we allocate. |
| 1402 | */ |
| 1403 | first = bt_freehead_toalloc(vm, size, strat); |
| 1404 | VMEM_LOCK(vm); |
| 1405 | |
| 1406 | /* |
| 1407 | * Make sure we have enough tags to complete the operation. |
| 1408 | */ |
| 1409 | error = bt_fill(vm, flags); |
| 1410 | if (error != 0) |
| 1411 | goto out; |
no test coverage detected