* Fill the vmem's boundary tag cache. We guarantee that boundary tag * allocation will not fail once bt_fill() passes. To do so we cache * at least the maximum possible tag allocations in the arena. */
| 267 | * at least the maximum possible tag allocations in the arena. |
| 268 | */ |
| 269 | static __noinline int |
| 270 | _bt_fill(vmem_t *vm, int flags) |
| 271 | { |
| 272 | bt_t *bt; |
| 273 | |
| 274 | VMEM_ASSERT_LOCKED(vm); |
| 275 | |
| 276 | /* |
| 277 | * Only allow the kernel arena and arenas derived from kernel arena to |
| 278 | * dip into reserve tags. They are where new tags come from. |
| 279 | */ |
| 280 | flags &= BT_FLAGS; |
| 281 | if (vm != kernel_arena && vm->vm_arg != kernel_arena) |
| 282 | flags &= ~M_USE_RESERVE; |
| 283 | |
| 284 | /* |
| 285 | * Loop until we meet the reserve. To minimize the lock shuffle |
| 286 | * and prevent simultaneous fills we first try a NOWAIT regardless |
| 287 | * of the caller's flags. Specify M_NOVM so we don't recurse while |
| 288 | * holding a vmem lock. |
| 289 | */ |
| 290 | while (vm->vm_nfreetags < BT_MAXALLOC) { |
| 291 | bt = uma_zalloc(vmem_bt_zone, |
| 292 | (flags & M_USE_RESERVE) | M_NOWAIT | M_NOVM); |
| 293 | if (bt == NULL) { |
| 294 | VMEM_UNLOCK(vm); |
| 295 | bt = uma_zalloc(vmem_bt_zone, flags); |
| 296 | VMEM_LOCK(vm); |
| 297 | if (bt == NULL) |
| 298 | break; |
| 299 | } |
| 300 | LIST_INSERT_HEAD(&vm->vm_freetags, bt, bt_freelist); |
| 301 | vm->vm_nfreetags++; |
| 302 | } |
| 303 | |
| 304 | if (vm->vm_nfreetags < BT_MAXALLOC) |
| 305 | return ENOMEM; |
| 306 | |
| 307 | return 0; |
| 308 | } |
| 309 | |
| 310 | static inline int |
| 311 | bt_fill(vmem_t *vm, int flags) |