Index: sys/kern/imgact_binmisc.c =================================================================== --- sys/kern/imgact_binmisc.c +++ sys/kern/imgact_binmisc.c @@ -98,68 +98,11 @@ SLIST_HEAD_INITIALIZER(interpreter_list); static int interp_list_entry_count = 0; -static int interp_list_rcount = 0; -static struct mtx interp_list_mtx; -int imgact_binmisc_exec(struct image_params *imgp); - -static inline void -interp_list_rlock() -{ - - /* Don't use atomic_add() here. We must block if the mutex is held. */ - mtx_lock(&interp_list_mtx); - interp_list_rcount++; - mtx_unlock(&interp_list_mtx); -} - -static inline void -interp_list_runlock() -{ - - /* Decrement the reader count and wake up one writer, if any. */ - atomic_subtract_int(&interp_list_rcount, 1); - if (interp_list_rcount == 0) - wakeup_one(&interp_list_rcount); -} +static struct sx interp_list_sx; -static inline void -interp_list_wlock() -{ - - /* Wait until there are no readers. */ - mtx_lock(&interp_list_mtx); - while (interp_list_rcount) - mtx_sleep(&interp_list_rcount, &interp_list_mtx, 0, "IABM", 0); -} - -static inline void -interp_list_wunlock() -{ - - mtx_unlock(&interp_list_mtx); -} - -#define interp_list_assert_rlocked() \ - KASSERT(interp_list_rcount > 0, ("%s: interp_list lock not held " \ - "for read", __func__)) - -#define interp_list_assert_wlocked() mtx_assert(&interp_list_mtx, MA_OWNED) - -#ifdef INVARIANTS -#define interp_list_assert_locked() do { \ - if (interp_list_rcount == 0) \ - mtx_assert(&interp_list_mtx, MA_OWNED); \ - else \ - KASSERT(interp_list_rcount > 0, \ - ("%s: interp_list lock not held", __func__)); \ -} while(0) - -#else /* ! INVARIANTS */ +int imgact_binmisc_exec(struct image_params *imgp); -#define interp_list_assert_locked() do { \ -} while(0) -#endif /* ! INVARIANTS */ /* * Populate the entry with the information about the interpreter. @@ -261,7 +204,7 @@ { imgact_binmisc_entry_t *ibe; - interp_list_assert_locked(); + sx_assert(&interp_list_sx, SA_LOCKED); SLIST_FOREACH(ibe, &interpreter_list, link) { if (strncmp(name, ibe->ibe_name, IBE_NAME_MAX) == 0) @@ -323,16 +266,16 @@ if (!ibe) return (ENOMEM); - interp_list_wlock(); + sx_xlock(&interp_list_sx); if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { - interp_list_wunlock(); + sx_xunlock(&interp_list_sx); imgact_binmisc_destroy_entry(ibe); return (EEXIST); } SLIST_INSERT_HEAD(&interpreter_list, ibe, link); interp_list_entry_count++; - interp_list_wunlock(); + sx_xunlock(&interp_list_sx); return (0); } @@ -346,14 +289,14 @@ { imgact_binmisc_entry_t *ibe; - interp_list_wlock(); + sx_xlock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - interp_list_wunlock(); + sx_xunlock(&interp_list_sx); return (ENOENT); } SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); interp_list_entry_count--; - interp_list_wunlock(); + sx_xunlock(&interp_list_sx); imgact_binmisc_destroy_entry(ibe); @@ -369,14 +312,14 @@ { imgact_binmisc_entry_t *ibe; - interp_list_rlock(); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (ENOENT); } atomic_clear_32(&ibe->ibe_flags, IBF_ENABLED); - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (0); } @@ -390,14 +333,14 @@ { imgact_binmisc_entry_t *ibe; - interp_list_rlock(); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (ENOENT); } atomic_set_32(&ibe->ibe_flags, IBF_ENABLED); - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (0); } @@ -408,7 +351,7 @@ { uint32_t i; - interp_list_assert_rlocked(); + sx_assert(&interp_list_sx, SA_LOCKED); memset(xbe, 0, sizeof(*xbe)); strlcpy(xbe->xbe_name, ibe->ibe_name, IBE_NAME_MAX); @@ -440,14 +383,14 @@ imgact_binmisc_entry_t *ibe; int error = 0; - interp_list_rlock(); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_entry(name)) == NULL) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (ENOENT); } error = imgact_binmisc_populate_xbe(xbe, ibe); - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (error); } @@ -462,12 +405,12 @@ imgact_binmisc_entry_t *ibe; int error = 0, count; - interp_list_rlock(); + sx_slock(&interp_list_sx); count = interp_list_entry_count; /* Don't block in malloc() while holding lock. */ xbe = malloc(sizeof(*xbe) * count, M_BINMISC, M_NOWAIT|M_ZERO); if (!xbe) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (ENOMEM); } @@ -477,7 +420,7 @@ if (error) break; } - interp_list_runlock(); + sx_sunlock(&interp_list_sx); if (!error) error = SYSCTL_OUT(req, xbe, sizeof(*xbe) * count); @@ -614,7 +557,7 @@ int i; size_t sz; - interp_list_assert_rlocked(); + sx_assert(&interp_list_sx, SA_LOCKED); SLIST_FOREACH(ibe, &interpreter_list, link) { if (!(IBF_ENABLED & ibe->ibe_flags)) @@ -651,15 +594,15 @@ char *s, *d; /* Do we have an interpreter for the given image header? */ - interp_list_rlock(); + sx_slock(&interp_list_sx); if ((ibe = imgact_binmisc_find_interpreter(image_header)) == NULL) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (-1); } /* No interpreter nesting allowed. */ if (imgp->interpreted & IMGACT_BINMISC) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); return (ENOEXEC); } @@ -707,7 +650,7 @@ default: /* Hmm... This shouldn't happen. */ - interp_list_runlock(); + sx_sunlock(&interp_list_sx); printf("%s: Unknown macro #%c sequence in " "interpreter string\n", KMOD_NAME, *(s + 1)); error = EINVAL; @@ -718,15 +661,12 @@ /* Check to make sure we won't overrun the stringspace. */ if (offset > imgp->args->stringspace) { - interp_list_runlock(); + sx_sunlock(&interp_list_sx); error = E2BIG; goto done; } - /* - * Make room for the interpreter. Doing an overlapping copy so - * bcopy() must be used. - */ + /* Make room for the interpreter */ bcopy(imgp->args->begin_argv, imgp->args->begin_argv + offset, imgp->args->endp - imgp->args->begin_argv); @@ -781,7 +721,7 @@ s++; } *d = '\0'; - interp_list_runlock(); + sx_sunlock(&interp_list_sx); if (!error) imgp->interpreter_name = imgp->args->begin_argv; @@ -797,7 +737,7 @@ imgact_binmisc_init(void *arg) { - mtx_init(&interp_list_mtx, KMOD_NAME, NULL, MTX_DEF); + sx_init(&interp_list_sx, KMOD_NAME); } static void @@ -806,15 +746,15 @@ imgact_binmisc_entry_t *ibe, *ibe_tmp; /* Free all the interpreters. */ - interp_list_wlock(); + sx_xlock(&interp_list_sx); SLIST_FOREACH_SAFE(ibe, &interpreter_list, link, ibe_tmp) { SLIST_REMOVE(&interpreter_list, ibe, imgact_binmisc_entry, link); imgact_binmisc_destroy_entry(ibe); } - interp_list_wunlock(); + sx_xunlock(&interp_list_sx); - mtx_destroy(&interp_list_mtx); + sx_destroy(&interp_list_sx); } SYSINIT(imgact_binmisc, SI_SUB_EXEC, SI_ORDER_MIDDLE, imgact_binmisc_init, 0);