void soput(struct socket *so) { KASSERT(!cv_has_waiters(&so->so_cv)); KASSERT(!cv_has_waiters(&so->so_rcv.sb_cv)); KASSERT(!cv_has_waiters(&so->so_snd.sb_cv)); seldestroy(&so->so_rcv.sb_sel); seldestroy(&so->so_snd.sb_sel); mutex_obj_free(so->so_lock); cv_destroy(&so->so_cv); cv_destroy(&so->so_rcv.sb_cv); cv_destroy(&so->so_snd.sb_cv); pool_cache_put(socket_cache, so); }
void cprng_strong_destroy(struct cprng_strong *cprng) { /* * Destroy the rndsink first to prevent calls to the callback. */ rndsink_destroy(cprng->cs_rndsink); KASSERT(!cv_has_waiters(&cprng->cs_cv)); #if 0 KASSERT(!select_has_waiters(&cprng->cs_selq)) /* XXX ? */ #endif nist_ctr_drbg_destroy(&cprng->cs_drbg); seldestroy(&cprng->cs_selq); cv_destroy(&cprng->cs_cv); mutex_destroy(&cprng->cs_lock); explicit_memset(cprng, 0, sizeof(*cprng)); /* paranoia */ kmem_free(cprng, sizeof(*cprng)); }
void rumpuser_cv_has_waiters(struct rumpuser_cv *cv, int *rvp) { cv_has_waiters(cv, rvp); }
static int semrealloc(int newsemmni, int newsemmns, int newsemmnu) { struct semid_ds *new_sema, *old_sema; struct __sem *new_sem; struct sem_undo *new_semu_list, *suptr, *nsuptr; int *new_semu; kcondvar_t *new_semcv; vaddr_t v; int i, j, lsemid, nmnus, sz; if (newsemmni < 1 || newsemmns < 1 || newsemmnu < 1) return EINVAL; /* Allocate the wired memory for our structures */ sz = ALIGN(newsemmni * sizeof(struct semid_ds)) + ALIGN(newsemmns * sizeof(struct __sem)) + ALIGN(newsemmni * sizeof(kcondvar_t)) + ALIGN(newsemmnu * seminfo.semusz); sz = round_page(sz); v = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_WIRED|UVM_KMF_ZERO); if (v == 0) return ENOMEM; mutex_enter(&semlock); if (sem_realloc_state) { mutex_exit(&semlock); uvm_km_free(kernel_map, v, sz, UVM_KMF_WIRED); return EBUSY; } sem_realloc_state = true; if (sem_waiters) { /* * Mark reallocation state, wake-up all waiters, * and wait while they will all exit. */ for (i = 0; i < seminfo.semmni; i++) cv_broadcast(&semcv[i]); while (sem_waiters) cv_wait(&sem_realloc_cv, &semlock); } old_sema = sema; /* Get the number of last slot */ lsemid = 0; for (i = 0; i < seminfo.semmni; i++) if (sema[i].sem_perm.mode & SEM_ALLOC) lsemid = i; /* Get the number of currently used undo structures */ nmnus = 0; for (i = 0; i < seminfo.semmnu; i++) { suptr = SEMU(semu, i); if (suptr->un_proc == NULL) continue; nmnus++; } /* We cannot reallocate less memory than we use */ if (lsemid >= newsemmni || semtot > newsemmns || nmnus > newsemmnu) { mutex_exit(&semlock); uvm_km_free(kernel_map, v, sz, UVM_KMF_WIRED); return EBUSY; } new_sema = (void *)v; new_sem = (void *)((uintptr_t)new_sema + ALIGN(newsemmni * sizeof(struct semid_ds))); new_semcv = (void *)((uintptr_t)new_sem + ALIGN(newsemmns * sizeof(struct __sem))); new_semu = (void *)((uintptr_t)new_semcv + ALIGN(newsemmni * sizeof(kcondvar_t))); /* Initialize all semaphore identifiers and condvars */ for (i = 0; i < newsemmni; i++) { new_sema[i]._sem_base = 0; new_sema[i].sem_perm.mode = 0; cv_init(&new_semcv[i], "semwait"); } for (i = 0; i < newsemmnu; i++) { nsuptr = SEMU(new_semu, i); nsuptr->un_proc = NULL; } /* * Copy all identifiers, semaphores and list of the * undo structures to the new memory allocation. */ j = 0; for (i = 0; i <= lsemid; i++) { if ((sema[i].sem_perm.mode & SEM_ALLOC) == 0) continue; memcpy(&new_sema[i], &sema[i], sizeof(struct semid_ds)); new_sema[i]._sem_base = &new_sem[j]; memcpy(new_sema[i]._sem_base, sema[i]._sem_base, (sizeof(struct __sem) * sema[i].sem_nsems)); j += sema[i].sem_nsems; } KASSERT(j == semtot); j = 0; new_semu_list = NULL; for (suptr = semu_list; suptr != NULL; suptr = suptr->un_next) { KASSERT(j < newsemmnu); nsuptr = SEMU(new_semu, j); memcpy(nsuptr, suptr, SEMUSZ); nsuptr->un_next = new_semu_list; new_semu_list = nsuptr; j++; } for (i = 0; i < seminfo.semmni; i++) { KASSERT(cv_has_waiters(&semcv[i]) == false); cv_destroy(&semcv[i]); } sz = ALIGN(seminfo.semmni * sizeof(struct semid_ds)) + ALIGN(seminfo.semmns * sizeof(struct __sem)) + ALIGN(seminfo.semmni * sizeof(kcondvar_t)) + ALIGN(seminfo.semmnu * seminfo.semusz); sz = round_page(sz); /* Set the pointers and update the new values */ sema = new_sema; sem = new_sem; semcv = new_semcv; semu = new_semu; semu_list = new_semu_list; seminfo.semmni = newsemmni; seminfo.semmns = newsemmns; seminfo.semmnu = newsemmnu; /* Reallocation completed - notify all waiters, if any */ sem_realloc_state = false; cv_broadcast(&sem_realloc_cv); mutex_exit(&semlock); uvm_km_free(kernel_map, (vaddr_t)old_sema, sz, UVM_KMF_WIRED); return 0; }