summaryrefslogtreecommitdiff
path: root/lib/librthread
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2005-12-14 06:07:55 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2005-12-14 06:07:55 +0000
commit32eefeb935d95a67efef35682775d19eacb04ae6 (patch)
tree2330d85b954a8e5062e1a65cb3ddd0864fc2d5d8 /lib/librthread
parent6ae4e33cbd86dce56e7209b706f25a96c5cc827c (diff)
add pthread_cleanup_push and pthread_cleanup_pop
Diffstat (limited to 'lib/librthread')
-rw-r--r--lib/librthread/rthread.c40
-rw-r--r--lib/librthread/rthread.h9
2 files changed, 47 insertions, 2 deletions
diff --git a/lib/librthread/rthread.c b/lib/librthread/rthread.c
index 6ec7af49af0..c1916bc0937 100644
--- a/lib/librthread/rthread.c
+++ b/lib/librthread/rthread.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.c,v 1.6 2005/12/14 05:44:49 tedu Exp $ */
+/* $OpenBSD: rthread.c,v 1.7 2005/12/14 06:07:54 tedu Exp $ */
/*
* Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -141,12 +141,19 @@ pthread_self(void)
void
pthread_exit(void *retval)
{
+ struct rthread_cleanup_fn *clfn;
pthread_t thread = pthread_self();
thread->retval = retval;
thread->flags |= THREAD_DONE;
_sem_post(&thread->donesem);
+ for (clfn = thread->cleanup_fns; clfn; ) {
+ struct rthread_cleanup_fn *oclfn = clfn;
+ clfn = clfn->next;
+ oclfn->fn(oclfn->arg);
+ free(oclfn);
+ }
rthread_tls_destructors(thread);
#if 0
if (thread->flags & THREAD_DETACHED)
@@ -286,6 +293,37 @@ pthread_setcanceltype(int type, int *oldtypep)
return (0);
}
+void
+pthread_cleanup_push(void (*fn)(void *), void *arg)
+{
+ struct rthread_cleanup_fn *clfn;
+ pthread_t self = pthread_self();
+
+ clfn = malloc(sizeof(*clfn));
+ if (!clfn)
+ return;
+ memset(clfn, 0, sizeof(*clfn));
+ clfn->fn = fn;
+ clfn->arg = arg;
+ clfn->next = self->cleanup_fns;
+ self->cleanup_fns = clfn;
+}
+
+void
+pthread_cleanup_pop(int execute)
+{
+ struct rthread_cleanup_fn *clfn;
+ pthread_t self = pthread_self();
+
+ clfn = self->cleanup_fns;
+ if (clfn) {
+ self->cleanup_fns = clfn->next;
+ if (execute)
+ clfn->fn(clfn->arg);
+ free(clfn);
+ }
+}
+
/*
* _np functions
*/
diff --git a/lib/librthread/rthread.h b/lib/librthread/rthread.h
index 6eac065dbcd..8b1290dbe79 100644
--- a/lib/librthread/rthread.h
+++ b/lib/librthread/rthread.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rthread.h,v 1.5 2005/12/14 04:43:04 tedu Exp $ */
+/* $OpenBSD: rthread.h,v 1.6 2005/12/14 06:07:54 tedu Exp $ */
/*
* Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
* All Rights Reserved.
@@ -83,6 +83,12 @@ struct rthread_storage {
void *data;
};
+struct rthread_cleanup_fn {
+ void (*fn)(void *);
+ void *arg;
+ struct rthread_cleanup_fn *next;
+};
+
struct pthread {
pid_t tid;
struct semaphore donesem;
@@ -97,6 +103,7 @@ struct pthread {
struct sched_param sched_param;
struct rthread_storage *local_storage;
int sigpend;
+ struct rthread_cleanup_fn *cleanup_fns;
};
#define THREAD_DONE 0x001
#define THREAD_DETACHED 0x002