summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_clean.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2008-06-09 01:14:10 +0000
committerdavidxu <davidxu@FreeBSD.org>2008-06-09 01:14:10 +0000
commitf4d6ff9c5e2c00dd44c3e39b44c0000351d91c6d (patch)
tree64448ccd5c1431710c5a1f4513a5128d2db5c444 /lib/libthr/thread/thr_clean.c
parent7c70b8f716071ee1944fc97021c0857b385b755c (diff)
downloadFreeBSD-src-f4d6ff9c5e2c00dd44c3e39b44c0000351d91c6d.zip
FreeBSD-src-f4d6ff9c5e2c00dd44c3e39b44c0000351d91c6d.tar.gz
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@
Diffstat (limited to 'lib/libthr/thread/thr_clean.c')
-rw-r--r--lib/libthr/thread/thr_clean.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/lib/libthr/thread/thr_clean.c b/lib/libthr/thread/thr_clean.c
index 9922798..9cef930 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;
-
- 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;
+ struct pthread_cleanup *newbuf;
- curthread->cleanup = new;
- }
+ newbuf = (void *)info;
+ newbuf->routine = routine;
+ newbuf->routine_arg = arg;
+ newbuf->onheap = 0;
+ newbuf->prev = curthread->cleanup;
+ curthread->cleanup = newbuf;
}
void
-_pthread_cleanup_pop(int execute)
+__pthread_cleanup_pop_imp(int execute)
{
struct pthread *curthread = _get_curthread();
struct pthread_cleanup *old;
if ((old = curthread->cleanup) != NULL) {
- curthread->cleanup = old->next;
- if (execute) {
+ curthread->cleanup = old->prev;
+ if (execute)
old->routine(old->routine_arg);
- }
- if (old->onstack == 0)
+ 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)
+{
+ __pthread_cleanup_pop_imp(execute);
+}
OpenPOWER on IntegriCloud