summaryrefslogtreecommitdiff
path: root/cleanup.c
diff options
context:
space:
mode:
Diffstat (limited to 'cleanup.c')
-rw-r--r--cleanup.c100
1 files changed, 62 insertions, 38 deletions
diff --git a/cleanup.c b/cleanup.c
index f670b97..9ea4316 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -10,58 +10,82 @@
#include "implement.h"
void
-_pthread_cleanup_push(void (*routine)(void *), void *arg)
+_pthread_handler_push(_pthread_handler_node_t ** stacktop,
+ int poporder,
+ void (*routine)(void *),
+ void *arg)
{
- _pthread_cleanup_node_t * next;
- int t;
+ /* Place the new handler into the list so that handlers are
+ popped off in the order given by poporder. */
+ _pthread_handler_node_t * new;
+ _pthread_handler_node_t * next;
- t = _pthread_getthreadindex(pthread_self());
+ new = (_pthread_handler_node_t *) malloc(sizeof(_pthread_handler_node_t));
- next = (_pthread_cleanup_node_t *) malloc(sizeof(_pthread_cleanup_node_t));
- if (next == NULL) {
- /* FIXME: INTERNAL ERROR */
- }
+ if (new == NULL)
+ {
+ /* FIXME: INTERNAL ERROR */
+ }
- next->next = _pthread_threads_table[t]->cleanupstack->first;
- next->routine = routine;
- next->arg = arg;
- _pthread_threads_table[t]->cleanupstack->first = next;
+ new->routine = routine;
+ new->arg = arg;
+
+ if (poporder == _PTHREAD_HANDLER_POP_LIFO)
+ {
+ /* Add the new node to the start of the list. */
+ new->next = *stacktop;
+ stacktop = next;
+ }
+ else
+ {
+ /* Add the new node to the end of the list. */
+ new->next = NULL;
+
+ if (*stacktop == NULL)
+ {
+ *stacktop = new;
+ }
+ else
+ {
+ next = *stacktop;
+ while (next != NULL)
+ {
+ next = next->next;
+ }
+ next = new;
+ }
+ }
}
void
-_pthread_cleanup_pop(int execute)
+_pthread_handler_pop(_pthread_handler_node_t ** stacktop,
+ int execute)
{
- _pthread_cleanup_node_t * handler;
- void (* func)(void *);
- void * arg;
- int t;
-
- t = _pthread_getthreadindex(pthread_self());
- handler = _pthread_threads_table[t]->cleanupstack->first;
+ _pthread_handler_node_t * handler = *stacktop;
- if (handler != NULL) {
- next = handler->next;
- func = handler->routine;
- arg = handler->arg;
+ if (handler != NULL)
+ {
+ void (* func)(void *) = handler->routine;
+ void * arg = handler->arg;
- free(handler);
+ *stacktop = handler->next;
- if (execute != 0)
- (void) func(arg);
+ free(handler);
- _pthread_threads_table[t]->cleanupstack->first = next;
- }
+ if (execute != 0 && func != NULL)
+ {
+ (void) func(arg);
+ }
+ }
}
void
-_pthread_do_cancellation(int tindex)
+_pthread_handler_pop_all(_pthread_handler_node_t ** stacktop,
+ int execute)
{
- _pthread_cleanup_stack_t * stack;
-
- stack = _pthread_threads_table[tindex]->cleanupstack;
-
- /* Run all the cleanup handlers */
- while (stack->first != NULL) {
- _pthread_cleanup_pop(1);
- }
+ /* Pop and run all handlers on the given stack. */
+ while (*stacktop != NULL)
+ {
+ _pthread_handler_pop(stacktop, execute);
+ }
}