static int bt_refill(vmem_t *vm, vm_flag_t flags) { bt_t *bt; VMEM_LOCK(vm); if (vm->vm_nfreetags > BT_MINRESERVE) { VMEM_UNLOCK(vm); return 0; } mutex_enter(&vmem_btag_lock); while (!LIST_EMPTY(&vmem_btag_freelist) && vm->vm_nfreetags <= BT_MINRESERVE) { bt = LIST_FIRST(&vmem_btag_freelist); LIST_REMOVE(bt, bt_freelist); LIST_INSERT_HEAD(&vm->vm_freetags, bt, bt_freelist); vm->vm_nfreetags++; vmem_btag_freelist_count--; VMEM_EVCNT_INCR(static_bt_inuse); } mutex_exit(&vmem_btag_lock); while (vm->vm_nfreetags <= BT_MINRESERVE) { VMEM_UNLOCK(vm); mutex_enter(&vmem_btag_refill_lock); bt = pool_get(&vmem_btag_pool, (flags & VM_SLEEP) ? PR_WAITOK: PR_NOWAIT); mutex_exit(&vmem_btag_refill_lock); VMEM_LOCK(vm); if (bt == NULL && (flags & VM_SLEEP) == 0) break; LIST_INSERT_HEAD(&vm->vm_freetags, bt, bt_freelist); vm->vm_nfreetags++; } VMEM_UNLOCK(vm); if (vm->vm_nfreetags == 0) { return ENOMEM; } if (kmem_meta_arena != NULL) { bt_refill(kmem_arena, (flags & ~VM_FITMASK) | VM_INSTANTFIT | VM_POPULATING); bt_refill(kmem_va_meta_arena, (flags & ~VM_FITMASK) | VM_INSTANTFIT | VM_POPULATING); bt_refill(kmem_meta_arena, (flags & ~VM_FITMASK) | VM_INSTANTFIT | VM_POPULATING); } return 0; }
static int bt_refill(vmem_t *vm) { bt_t *bt; VMEM_LOCK(vm); if (vm->vm_nfreetags > BT_MINRESERVE) { VMEM_UNLOCK(vm); return 0; } mutex_enter(&vmem_btag_lock); while (!LIST_EMPTY(&vmem_btag_freelist) && vm->vm_nfreetags <= BT_MINRESERVE) { bt = LIST_FIRST(&vmem_btag_freelist); LIST_REMOVE(bt, bt_freelist); LIST_INSERT_HEAD(&vm->vm_freetags, bt, bt_freelist); vm->vm_nfreetags++; vmem_btag_freelist_count--; VMEM_EVCNT_INCR(static_bt_inuse); } mutex_exit(&vmem_btag_lock); while (vm->vm_nfreetags <= BT_MINRESERVE) { VMEM_UNLOCK(vm); mutex_enter(&vmem_btag_refill_lock); bt = pool_get(&vmem_btag_pool, PR_NOWAIT); mutex_exit(&vmem_btag_refill_lock); VMEM_LOCK(vm); if (bt == NULL) break; LIST_INSERT_HEAD(&vm->vm_freetags, bt, bt_freelist); vm->vm_nfreetags++; } if (vm->vm_nfreetags <= BT_MINRESERVE) { VMEM_UNLOCK(vm); return ENOMEM; } VMEM_UNLOCK(vm); if (kmem_meta_arena != NULL) { (void)bt_refill(kmem_arena); (void)bt_refill(kmem_va_meta_arena); (void)bt_refill(kmem_meta_arena); } return 0; }
static void vmem_bootstrap(void) { mutex_init(&vmem_list_lock, MUTEX_DEFAULT, IPL_VM); mutex_init(&vmem_btag_lock, MUTEX_DEFAULT, IPL_VM); mutex_init(&vmem_btag_refill_lock, MUTEX_DEFAULT, IPL_VM); while (static_bt_count-- > 0) { bt_t *bt = &static_bts[static_bt_count]; LIST_INSERT_HEAD(&vmem_btag_freelist, bt, bt_freelist); VMEM_EVCNT_INCR(static_bt_count); vmem_btag_freelist_count++; } vmem_bootstrapped = TRUE; }