Date: Sun, 17 Mar 2013 15:14:14 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 222974 for review Message-ID: <201303171514.r2HFEEqZ065760@skunkworks.freebsd.org>
index | next in thread | raw e-mail
http://p4web.freebsd.org/@@222974?ac=10 Change 222974 by rwatson@rwatson_cinnamon on 2013/03/17 15:13:24 A number of changes to libtesla to get it compiling (but not yet running) in the kernel runtime environment: - Remove a large chunk of code that supported dynamic registration of new automata classes at runtime; this was left over from a previous iteration, and the new version of tesla doesn't support this yet. - Use tesla_store_init() to set up per-thread TESLA state, requiring that this be non-static. We require a not-yet-present tesla_store_destroy(), which will arrive in the next merge of libtesla to the kernel (thanks Jon!). - Expose global_store to _KERNEL; this should probably be static but isn't yet. - Use #define's for hard-coded class and instance count maxima, rather than numbers in code. This is pertinent because we will initialise per-thread storage in quite a different place in the kernel, so as to avoid malloc() at arbitrary instrumentation points. Affected files ... .. //depot/projects/ctsrd/tesla/src/sys/libtesla/state-perthread.c#2 edit .. //depot/projects/ctsrd/tesla/src/sys/libtesla/store.c#2 edit .. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_internal.h#3 edit .. //depot/projects/ctsrd/tesla/src/sys/libtesla/update.c#3 edit Differences ... ==== //depot/projects/ctsrd/tesla/src/sys/libtesla/state-perthread.c#2 (text+ko) ==== @@ -48,259 +48,50 @@ #ifdef _KERNEL /* - * Global state used to manage per-thread storage slots for TESLA per-thread - * assertions. tspd_tesla_classp is non-NULL when a slot has been allocated. - */ -static struct tesla_class_perthread_desc { - struct tesla_class *tspd_tesla_classp; - size_t tspd_len; -} tesla_class_perthread_desc[TESLA_PERTHREAD_MAX]; -static struct sx tesla_class_perthread_sx; - -/* * Registration state for per-thread storage. */ -static eventhandler_tag tesla_class_perthread_ctor_tag; -static eventhandler_tag tesla_class_perthread_dtor_tag; +static eventhandler_tag tesla_perthread_ctor_tag; +static eventhandler_tag tesla_perthread_dtor_tag; static void -tesla_class_perthread_ctor(__unused void *arg, struct thread *td) +tesla_perthread_ctor(__unused void *arg, struct thread *td) { - struct tesla_class_perthread_desc *tspdp; - struct tesla_class *tsp; - struct tesla_table *ttp; - u_int index; + struct tesla_store *store; + uint32_t error; - sx_slock(&tesla_class_perthread_sx); - for (index = 0; index < TESLA_PERTHREAD_MAX; index++) { - tspdp = &tesla_class_perthread_desc[index]; - tsp = tspdp->tspd_tesla_classp; - if (tsp == NULL) { - td->td_tesla[index] = NULL; - continue; - } - ttp = malloc(tspdp->tspd_len, M_TESLA, M_WAITOK | M_ZERO); - ttp->tt_length = tsp->ts_limit; - ttp->tt_free = tsp->ts_limit; - td->td_tesla[index] = ttp; - } - sx_sunlock(&tesla_class_perthread_sx); + store = tesla_malloc(sizeof(*store)); + error = tesla_store_init(store, TESLA_SCOPE_PERTHREAD, + TESLA_MAX_CLASSES, TESLA_MAX_INSTANCES); + tesla_assert(error == TESLA_SUCCESS, ("tesla_store_init failed")); + curthread->td_tesla = store; } static void -tesla_class_perthread_dtor_locked(struct thread *td) +tesla_perthread_dtor(struct thread *td) { - u_int index; + struct tesla_store *store; - sx_assert(&tesla_class_perthread_sx, SX_LOCKED); - for (index = 0; index < TESLA_PERTHREAD_MAX; index++) { - if (td->td_tesla[index] == NULL) - continue; - free(M_TESLA, td->td_tesla[index]); - td->td_tesla[index] = NULL; - } + store = curthread->td_tesla; + curthread->td_tesla = NULL; + tesla_store_destroy(store); + tesla_free(store); } static void -tesla_class_perthread_dtor(__unused void *arg, struct thread *td) +tesla_perthread_sysinit(__unused void *arg) { - sx_slock(&tesla_class_perthread_sx); - tesla_class_perthread_dtor_locked(td); - sx_sunlock(&tesla_class_perthread_sx); + tesla_perthread_ctor_tag = EVENTHANDLER_REGISTER(thread_ctor, + tesla_perthread_ctor, NULL, EVENTHANDLER_PRI_ANY); + tesla_perthread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor, + tesla_perthread_dtor, NULL, EVENTHANDLER_PRI_ANY); } +SYSINIT(tesla_perthread, SI_SUB_TESLA, SI_ORDER_FIRST, + tesla_perthread_sysinit, NULL); -static void -tesla_class_perthread_sysinit(__unused void *arg) -{ +#endif /* !_KERNEL */ - sx_init(&tesla_class_perthread_sx, "tesla_class_perthread_sx"); - tesla_class_perthread_ctor_tag = EVENTHANDLER_REGISTER(thread_ctor, - tesla_class_perthread_ctor, NULL, EVENTHANDLER_PRI_ANY); - tesla_class_perthread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor, - tesla_class_perthread_dtor, NULL, EVENTHANDLER_PRI_ANY); -} -SYSINIT(tesla_class_perthread, SI_SUB_TESLA, SI_ORDER_FIRST, - tesla_class_perthread_sysinit, NULL); - -static void -tesla_class_perthread_sysuninit(__unused void *arg) -{ - struct proc *p; - struct thread *td; - - /* - * XXXRW: Possibility of a race for in-flight handlers and - * instrumentation? - */ - EVENTHANDLER_DEREGISTER(tesla_class_perthread_ctor, - tesla_class_perthread_ctor_tag); - EVENTHANDLER_DEREGISTER(tesla_class_perthread_dtor, - tesla_class_perthread_dtor_tag); - - sx_xlock(&allproc_lock); - sx_xlock(&tesla_class_perthread_sx); - FOREACH_PROC_IN_SYSTEM(p) { - PROC_LOCK(p); - FOREACH_THREAD_IN_PROC(p, td) { - tesla_class_perthread_dtor_locked(td); - } - PROC_UNLOCK(p); - } - sx_xunlock(&tesla_class_perthread_sx); - sx_xunlock(&allproc_lock); - sx_destroy(&tesla_class_perthread_sx); -} -SYSUNINIT(tesla_class_perthread, SI_SUB_TESLA, SI_ORDER_FIRST, - tesla_class_perthread_sysuninit, NULL); - int -tesla_class_perthread_new(struct tesla_class *tsp) -{ - struct tesla_class_perthread_desc *tspdp; - struct tesla_table *ttp; - struct proc *p; - struct thread *td; - int looped; - u_int index; - - /* - * First, allocate a TESLA per-thread storage slot, if available. - */ - tspdp = NULL; - sx_xlock(&tesla_class_perthread_sx); - for (index = 0; index < TESLA_PERTHREAD_MAX; index++) { - if (tesla_class_perthread_desc[index].tspd_tesla_classp - == NULL) { - tspdp = &tesla_class_perthread_desc[index]; - break; - } - } - if (tspdp == NULL) { - sx_xunlock(&tesla_class_perthread_sx); - return (TESLA_ERROR_ENOMEM); - } - tsp->ts_perthread_index = index; - tspdp->tspd_tesla_classp = tsp; - tspdp->tspd_len = sizeof(*ttp) + sizeof(struct tesla_instance) * - tsp->ts_limit; - - /* - * Walk all existing threads and add required allocations. If we - * can't allocate under the process lock, we have to loop out, use - * M_WAITOK, and then repeat. This looks starvation-prone, but - * actually isn't: holding tesla_class_perthread_sx blocks further - * thread allocations from taking place, so the main concern is - * in-progress allocations, which will be bounded in number. - */ - ttp = NULL; - looped = 0; - sx_slock(&allproc_lock); - FOREACH_PROC_IN_SYSTEM(p) { -loop: - if (looped) { - KASSERT(ttp == NULL, - ("tesla_class_perthread_new: ttp not NULL")); - ttp = malloc(tspdp->tspd_len, M_TESLA, - M_WAITOK | M_ZERO); - looped = 0; - } - PROC_LOCK(p); - FOREACH_THREAD_IN_PROC(p, td) { - /* - * If we looped, then some threads may already have - * memory; skip them. - */ - if (td->td_tesla[index] != NULL) - continue; - if (ttp == NULL) - ttp = malloc(tspdp->tspd_len, M_TESLA, - M_NOWAIT | M_ZERO); - if (ttp == NULL) { - PROC_UNLOCK(p); - looped = 1; - goto loop; - } - ttp->tt_length = tsp->ts_limit; - ttp->tt_free = tsp->ts_limit; - td->td_tesla[index] = ttp; - ttp = NULL; - } - PROC_UNLOCK(p); - } - sx_sunlock(&allproc_lock); - /* Due to races, we may have allocated an extra, so free it now. */ - if (ttp != NULL) - free(ttp, M_TESLA); - sx_xunlock(&tesla_class_perthread_sx); - return (TESLA_SUCCESS); -} - -void -tesla_class_perthread_destroy(struct tesla_class *tsp) -{ - struct tesla_class_perthread_desc *tspdp; - struct proc *p; - struct thread *td; - u_int index; - - sx_xlock(&tesla_class_perthread_sx); - index = tsp->ts_perthread_index; - tspdp = &tesla_class_perthread_desc[index]; - - /* - * First, walk all threads and release resources. This is easier on - * free than alloc due to the non-blocking nature of free. - * - * XXXRW: Do we need a test for td->td_tesla[index] == NULL and a - * continue? I think probably not. - */ - sx_slock(&allproc_lock); - FOREACH_PROC_IN_SYSTEM(p) { - PROC_LOCK(p); - FOREACH_THREAD_IN_PROC(p, td) { - free(M_TESLA, td->td_tesla[index]); - td->td_tesla[index] = NULL; - } - PROC_UNLOCK(p); - } - sx_unlock(&allproc_lock); - - /* - * Finally, release the reservation. - */ - tspdp->tspd_tesla_classp = NULL; - tspdp->tspd_len = 0; - sx_xunlock(&tesla_class_perthread_sx); -} - -void -tesla_class_perthread_flush(struct tesla_class *tsp) -{ - struct tesla_table *ttp; - - ttp = curthread->td_tesla[tsp->ts_perthread_index]; - bzero(&ttp->tt_instances, - sizeof(struct tesla_instance) * ttp->tt_length); - ttp->tt_free = ttp->tt_length; -} - -int -tesla_class_perthread_gettable(struct tesla_class *tsp, - struct tesla_table **ttpp) -{ - struct tesla_table *ttp; - - ttp = curthread->td_tesla[tsp->ts_perthread_index]; - KASSERT(ttp != NULL, - ("tesla_class_perthread_gettable: NULL tesla thread state")); - *ttpp = ttp; - return (TESLA_SUCCESS); -} - -#else /* !_KERNEL */ - -int tesla_class_perthread_postinit(__unused struct tesla_class *c) { return 0; @@ -320,5 +111,3 @@ tesla_class_perthread_destroy(__unused struct tesla_class *c) { } - -#endif /* _KERNEL */ ==== //depot/projects/ctsrd/tesla/src/sys/libtesla/store.c#2 (text+ko) ==== @@ -38,17 +38,14 @@ #ifndef _KERNEL #include <errno.h> -struct tesla_store global_store = { .length = 0 }; - /** The pthreads key used to identify TESLA data. */ pthread_key_t pthread_key(void); #endif +struct tesla_store global_store = { .length = 0 }; + static void tesla_class_acquire(tesla_class*); -static int tesla_store_init(tesla_store*, - uint32_t context, uint32_t classes, uint32_t instances); - int32_t tesla_store_get(uint32_t context, uint32_t classes, uint32_t instances, tesla_store* *storep) @@ -101,7 +98,7 @@ } -static int32_t +int32_t tesla_store_init(tesla_store *store, uint32_t context, uint32_t classes, uint32_t instances) { ==== //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_internal.h#3 (text+ko) ==== @@ -221,12 +221,26 @@ }; /** + * Initialise @ref tesla_store internals. + * Locking is the responsibility of the caller. + */ +int tesla_store_init(tesla_store*, uint32_t context, uint32_t classes, + uint32_t instances); +void tesla_store_destroy(tesla_store*); + +/** * Initialize @ref tesla_class internals. * Locking is the responsibility of the caller. */ int tesla_class_init(struct tesla_class*, uint32_t context, uint32_t instances); +/* + * XXXRW: temporarily, maximum number of classes and instances are hard-coded + * constants. In the future, this should somehow be more dynamic. + */ +#define TESLA_MAX_CLASSES 12 +#define TESLA_MAX_INSTANCES 8 /* * When the assertion fails, what to do? ==== //depot/projects/ctsrd/tesla/src/sys/libtesla/update.c#3 (text+ko) ==== @@ -69,7 +69,8 @@ } struct tesla_store *store; - CHECK(tesla_store_get, tesla_context, 12, 8, &store); + CHECK(tesla_store_get, tesla_context, TESLA_MAX_CLASSES, + TESLA_MAX_INSTANCES, &store); VERBOSE_PRINT("store: 0x%tx", (intptr_t) store); VERBOSE_PRINT("\n----\n");help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303171514.r2HFEEqZ065760>
