From 83a07587898c460f4444b85725f2dbdf26cf6f33 Mon Sep 17 00:00:00 2001 From: David Xu Date: Mon, 9 Jun 2008 01:14:10 +0000 Subject: [PATCH] Make pthread_cleanup_push() and pthread_cleanup_pop() as a pair of macros, use stack space to keep cleanup information, this eliminates overhead of calling malloc() and free() in thread library. Discussed on: thread@ --- include/pthread.h | 23 ++++++++++-- lib/libc/include/namespace.h | 2 -- lib/libc/include/un-namespace.h | 2 -- lib/libthr/pthread.map | 2 ++ lib/libthr/thread/thr_clean.c | 63 ++++++++++++++++++++++----------- lib/libthr/thread/thr_private.h | 15 ++++---- 6 files changed, 75 insertions(+), 32 deletions(-) diff --git a/include/pthread.h b/include/pthread.h index 215b88258fec..fad12b1be218 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -135,6 +135,10 @@ enum pthread_mutextype { #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK +struct _pthread_cleanup_info { + __uintptr_t pthread_cleanup_pad[8]; +}; + /* * Thread function prototype definitions: */ @@ -162,8 +166,19 @@ int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *); int pthread_barrierattr_init(pthread_barrierattr_t *); int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); -void pthread_cleanup_pop(int); -void pthread_cleanup_push(void (*) (void *), void *); + +#define pthread_cleanup_push(cleanup_routine, cleanup_arg) \ + { \ + struct _pthread_cleanup_info __cleanup_info__; \ + __pthread_cleanup_push_imp(cleanup_routine, cleanup_arg,\ + &__cleanup_info__); \ + { + +#define pthread_cleanup_pop(execute) \ + } \ + __pthread_cleanup_pop_imp(execute); \ + } + int pthread_condattr_destroy(pthread_condattr_t *); int pthread_condattr_getclock(const pthread_condattr_t *, clockid_t *); @@ -268,6 +283,10 @@ int pthread_setschedparam(pthread_t, int, const struct sched_param *); int pthread_getconcurrency(void); int pthread_setconcurrency(int); + +void __pthread_cleanup_push_imp(void (*)(void *), void *, + struct _pthread_cleanup_info *); +void __pthread_cleanup_pop_imp(int); __END_DECLS #endif diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index 22c3f6402e23..a65b929bbc07 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -114,8 +114,6 @@ #define pthread_barrierattr_init _pthread_barrierattr_init #define pthread_barrierattr_setpshared _pthread_barrierattr_setpshared #define pthread_cancel _pthread_cancel -#define pthread_cleanup_pop _pthread_cleanup_pop -#define pthread_cleanup_push _pthread_cleanup_push #define pthread_cond_broadcast _pthread_cond_broadcast #define pthread_cond_destroy _pthread_cond_destroy #define pthread_cond_init _pthread_cond_init diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index 64d16764ceb2..6b7f49a2764b 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -95,8 +95,6 @@ #undef pthread_barrierattr_init #undef pthread_barrierattr_setpshared #undef pthread_cancel -#undef pthread_cleanup_pop -#undef pthread_cleanup_push #undef pthread_cond_broadcast #undef pthread_cond_destroy #undef pthread_cond_init diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 21a013590845..79bbd4c11a81 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -393,6 +393,8 @@ FBSDprivate_1.0 { }; FBSD_1.1 { + __pthread_cleanup_pop_imp; + __pthread_cleanup_push_imp; pthread_attr_getaffinity_np; pthread_attr_setaffinity_np; pthread_getaffinity_np; diff --git a/lib/libthr/thread/thr_clean.c b/lib/libthr/thread/thr_clean.c index 992279816954..9cef930e32a6 100644 --- a/lib/libthr/thread/thr_clean.c +++ b/lib/libthr/thread/thr_clean.c @@ -38,38 +38,61 @@ #include "thr_private.h" +#undef pthread_cleanup_push +#undef pthread_cleanup_pop + +/* old binary compatible interfaces */ __weak_reference(_pthread_cleanup_push, pthread_cleanup_push); __weak_reference(_pthread_cleanup_pop, pthread_cleanup_pop); void -_pthread_cleanup_push(void (*routine) (void *), void *routine_arg) +__pthread_cleanup_push_imp(void (*routine)(void *), void *arg, + struct _pthread_cleanup_info *info) { struct pthread *curthread = _get_curthread(); - struct pthread_cleanup *new; + struct pthread_cleanup *newbuf; - if ((new = (struct pthread_cleanup *) - malloc(sizeof(struct pthread_cleanup))) != NULL) { - new->routine = routine; - new->routine_arg = routine_arg; - new->onstack = 0; - new->next = curthread->cleanup; + newbuf = (void *)info; + newbuf->routine = routine; + newbuf->routine_arg = arg; + newbuf->onheap = 0; + newbuf->prev = curthread->cleanup; + curthread->cleanup = newbuf; +} - curthread->cleanup = new; +void +__pthread_cleanup_pop_imp(int execute) +{ + struct pthread *curthread = _get_curthread(); + struct pthread_cleanup *old; + + if ((old = curthread->cleanup) != NULL) { + curthread->cleanup = old->prev; + if (execute) + old->routine(old->routine_arg); + if (old->onheap) + free(old); + } +} + +void +_pthread_cleanup_push(void (*routine) (void *), void *arg) +{ + struct pthread *curthread = _get_curthread(); + struct pthread_cleanup *newbuf; + + if ((newbuf = (struct pthread_cleanup *) + malloc(sizeof(struct _pthread_cleanup_info))) != NULL) { + newbuf->routine = routine; + newbuf->routine_arg = arg; + newbuf->onheap = 1; + newbuf->prev = curthread->cleanup; + curthread->cleanup = newbuf; } } void _pthread_cleanup_pop(int execute) { - struct pthread *curthread = _get_curthread(); - struct pthread_cleanup *old; - - if ((old = curthread->cleanup) != NULL) { - curthread->cleanup = old->next; - if (execute) { - old->routine(old->routine_arg); - } - if (old->onstack == 0) - free(old); - } + __pthread_cleanup_pop_imp(execute); } diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index e84ba232058a..e336b2cd6645 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -176,10 +176,10 @@ struct pthread_spinlock { * Cleanup definitions. */ struct pthread_cleanup { - struct pthread_cleanup *next; - void (*routine)(void *args); + struct pthread_cleanup *prev; + void (*routine)(void *); void *routine_arg; - int onstack; + int onheap; }; #define THR_CLEANUP_PUSH(td, func, arg) { \ @@ -187,12 +187,12 @@ struct pthread_cleanup { \ __cup.routine = func; \ __cup.routine_arg = arg; \ - __cup.onstack = 1; \ - __cup.next = (td)->cleanup; \ + __cup.onheap = 0; \ + __cup.prev = (td)->cleanup; \ (td)->cleanup = &__cup; #define THR_CLEANUP_POP(td, exec) \ - (td)->cleanup = __cup.next; \ + (td)->cleanup = __cup.prev; \ if ((exec) != 0) \ __cup.routine(__cup.routine_arg); \ } @@ -661,6 +661,9 @@ void _thread_bp_create(void); void _thread_bp_death(void); int _sched_yield(void); +void _pthread_cleanup_push(void (*)(void *), void *); +void _pthread_cleanup_pop(int); + /* #include */ #ifdef _SYS_FCNTL_H_ int __sys_fcntl(int, int, ...);