summaryrefslogtreecommitdiffstats
path: root/man3p/pthread_cleanup_push.3p
diff options
context:
space:
mode:
Diffstat (limited to 'man3p/pthread_cleanup_push.3p')
-rw-r--r--man3p/pthread_cleanup_push.3p295
1 files changed, 295 insertions, 0 deletions
diff --git a/man3p/pthread_cleanup_push.3p b/man3p/pthread_cleanup_push.3p
new file mode 100644
index 000000000..e8bdcb6bf
--- /dev/null
+++ b/man3p/pthread_cleanup_push.3p
@@ -0,0 +1,295 @@
+.\" Copyright (c) 2001-2003 The Open Group, All Rights Reserved
+.TH "PTHREAD_CLEANUP_POP" P 2003 "IEEE/The Open Group" "POSIX Programmer's Manual"
+.\" pthread_cleanup_pop
+.SH NAME
+pthread_cleanup_pop, pthread_cleanup_push \- establish cancellation
+handlers
+.SH SYNOPSIS
+.LP
+\fB#include <pthread.h>
+.br
+.sp
+void pthread_cleanup_pop(int\fP \fIexecute\fP\fB);
+.br
+void pthread_cleanup_push(void (*\fP\fIroutine\fP\fB)(void*), void
+*\fP\fIarg\fP\fB); \fP
+\fB
+.br
+\fP
+.SH DESCRIPTION
+.LP
+The \fIpthread_cleanup_pop\fP() function shall remove the routine
+at the top of the calling thread's cancellation cleanup stack
+and optionally invoke it (if \fIexecute\fP is non-zero).
+.LP
+The \fIpthread_cleanup_push\fP() function shall push the specified
+cancellation cleanup handler \fIroutine\fP onto the calling
+thread's cancellation cleanup stack. The cancellation cleanup handler
+shall be popped from the cancellation cleanup stack and
+invoked with the argument \fIarg\fP when:
+.IP " *" 3
+The thread exits (that is, calls \fIpthread_exit\fP()).
+.LP
+.IP " *" 3
+The thread acts upon a cancellation request.
+.LP
+.IP " *" 3
+The thread calls \fIpthread_cleanup_pop\fP() with a non-zero \fIexecute\fP
+argument.
+.LP
+.LP
+These functions may be implemented as macros. The application shall
+ensure that they appear as statements, and in pairs within
+the same lexical scope (that is, the \fIpthread_cleanup_push\fP()
+macro may be thought to expand to a token list whose first token
+is \fB'{'\fP with \fIpthread_cleanup_pop\fP() expanding to a token
+list whose last token is the corresponding \fB'}'\fP
+).
+.LP
+The effect of calling \fIlongjmp\fP() or \fIsiglongjmp\fP() is undefined
+if there have been any calls to \fIpthread_cleanup_push\fP()
+or \fIpthread_cleanup_pop\fP() made without the matching call since
+the jump buffer was filled. The effect of calling \fIlongjmp\fP()
+or \fIsiglongjmp\fP() from inside a
+cancellation cleanup handler is also undefined unless the jump buffer
+was also filled in the cancellation cleanup handler.
+.SH RETURN VALUE
+.LP
+The \fIpthread_cleanup_push\fP() and \fIpthread_cleanup_pop\fP() functions
+shall not return a value.
+.SH ERRORS
+.LP
+No errors are defined.
+.LP
+These functions shall not return an error code of [EINTR].
+.LP
+\fIThe following sections are informative.\fP
+.SH EXAMPLES
+.LP
+The following is an example using thread primitives to implement a
+cancelable, writers-priority read-write lock:
+.sp
+.RS
+.nf
+
+\fBtypedef struct {
+ pthread_mutex_t lock;
+ pthread_cond_t rcond,
+ wcond;
+ int lock_count; /* < 0 .. Held by writer. */
+ /* > 0 .. Held by lock_count readers. */
+ /* = 0 .. Held by nobody. */
+ int waiting_writers; /* Count of waiting writers. */
+} rwlock;
+.sp
+
+void
+waiting_reader_cleanup(void *arg)
+{
+ rwlock *l;
+.sp
+
+ l = (rwlock *) arg;
+ pthread_mutex_unlock(&l->lock);
+}
+.sp
+
+void
+lock_for_read(rwlock *l)
+{
+ pthread_mutex_lock(&l->lock);
+ pthread_cleanup_push(waiting_reader_cleanup, l);
+ while ((l->lock_count < 0) && (l->waiting_writers != 0))
+ pthread_cond_wait(&l->rcond, &l->lock);
+ l->lock_count++;
+ /*
+ * Note the pthread_cleanup_pop executes
+ * waiting_reader_cleanup.
+ */
+ pthread_cleanup_pop(1);
+}
+.sp
+
+void
+release_read_lock(rwlock *l)
+{
+ pthread_mutex_lock(&l->lock);
+ if (--l->lock_count == 0)
+ pthread_cond_signal(&l->wcond);
+ pthread_mutex_unlock(l);
+}
+.sp
+
+void
+waiting_writer_cleanup(void *arg)
+{
+ rwlock *l;
+.sp
+
+ l = (rwlock *) arg;
+ if ((--l->waiting_writers == 0) && (l->lock_count >= 0)) {
+ /*
+ * This only happens if we have been canceled.
+ */
+ pthread_cond_broadcast(&l->wcond);
+}
+ pthread_mutex_unlock(&l->lock);
+}
+.sp
+
+void
+lock_for_write(rwlock *l)
+{
+ pthread_mutex_lock(&l->lock);
+ l->waiting_writers++;
+ pthread_cleanup_push(waiting_writer_cleanup, l);
+ while (l->lock_count != 0)
+ pthread_cond_wait(&l->wcond, &l->lock);
+ l->lock_count = -1;
+ /*
+ * Note the pthread_cleanup_pop executes
+ * waiting_writer_cleanup.
+ */
+ pthread_cleanup_pop(1);
+}
+.sp
+
+void
+release_write_lock(rwlock *l)
+{
+ pthread_mutex_lock(&l->lock);
+ l->lock_count = 0;
+ if (l->waiting_writers == 0)
+ pthread_cond_broadcast(&l->rcond)
+ else
+ pthread_cond_signal(&l->wcond);
+ pthread_mutex_unlock(&l->lock);
+}
+.sp
+
+/*
+ * This function is called to initialize the read/write lock.
+ */
+void
+initialize_rwlock(rwlock *l)
+{
+ pthread_mutex_init(&l->lock, pthread_mutexattr_default);
+ pthread_cond_init(&l->wcond, pthread_condattr_default);
+ pthread_cond_init(&l->rcond, pthread_condattr_default);
+ l->lock_count = 0;
+ l->waiting_writers = 0;
+}
+.sp
+
+reader_thread()
+{
+ lock_for_read(&lock);
+ pthread_cleanup_push(release_read_lock, &lock);
+ /*
+ * Thread has read lock.
+ */
+ pthread_cleanup_pop(1);
+}
+.sp
+
+writer_thread()
+{
+ lock_for_write(&lock);
+ pthread_cleanup_push(release_write_lock, &lock);
+ /*
+ * Thread has write lock.
+ */
+pthread_cleanup_pop(1);
+}
+\fP
+.fi
+.RE
+.SH APPLICATION USAGE
+.LP
+The two routines that push and pop cancellation cleanup handlers,
+\fIpthread_cleanup_push\fP() and
+\fIpthread_cleanup_pop\fP(), can be thought of as left and right parentheses.
+They always need to be matched.
+.SH RATIONALE
+.LP
+The restriction that the two routines that push and pop cancellation
+cleanup handlers, \fIpthread_cleanup_push\fP() and
+\fIpthread_cleanup_pop\fP(), have to appear in the same lexical scope
+allows for efficient macro or compiler implementations and
+efficient storage management. A sample implementation of these routines
+as macros might look like this:
+.sp
+.RS
+.nf
+
+\fB#define pthread_cleanup_push(rtn,arg) { \\
+ struct _pthread_handler_rec __cleanup_handler, **__head; \\
+ __cleanup_handler.rtn = rtn; \\
+ __cleanup_handler.arg = arg; \\
+ (void) pthread_getspecific(_pthread_handler_key, &__head); \\
+ __cleanup_handler.next = *__head; \\
+ *__head = &__cleanup_handler;
+.sp
+
+#define pthread_cleanup_pop(ex) \\
+ *__head = __cleanup_handler.next; \\
+ if (ex) (*__cleanup_handler.rtn)(__cleanup_handler.arg); \\
+}
+\fP
+.fi
+.RE
+.LP
+A more ambitious implementation of these routines might do even better
+by allowing the compiler to note that the cancellation
+cleanup handler is a constant and can be expanded inline.
+.LP
+This volume of IEEE\ Std\ 1003.1-2001 currently leaves unspecified
+the effect of calling \fIlongjmp\fP() from a signal handler executing
+in a POSIX System Interfaces function. If an
+implementation wants to allow this and give the programmer reasonable
+behavior, the \fIlongjmp\fP() function has to call all cancellation
+cleanup handlers that have been pushed but
+not popped since the time \fIsetjmp\fP() was called.
+.LP
+Consider a multi-threaded function called by a thread that uses signals.
+If a signal were delivered to a signal handler during
+the operation of \fIqsort\fP() and that handler were to call \fIlongjmp\fP()
+(which, in turn, did \fInot\fP call the cancellation cleanup handlers)
+the helper
+threads created by the \fIqsort\fP() function would not be canceled.
+Instead, they would
+continue to execute and write into the argument array even though
+the array might have been popped off the stack.
+.LP
+Note that the specified cleanup handling mechanism is especially tied
+to the C language and, while the requirement for a uniform
+mechanism for expressing cleanup is language-independent, the mechanism
+used in other languages may be quite different. In
+addition, this mechanism is really only necessary due to the lack
+of a real exception mechanism in the C language, which would be
+the ideal solution.
+.LP
+There is no notion of a cancellation cleanup-safe function. If an
+application has no cancellation points in its signal handlers,
+blocks any signal whose handler may have cancellation points while
+calling async-unsafe functions, or disables cancellation while
+calling async-unsafe functions, all functions may be safely called
+from cancellation cleanup routines.
+.SH FUTURE DIRECTIONS
+.LP
+None.
+.SH SEE ALSO
+.LP
+\fIpthread_cancel\fP() , \fIpthread_setcancelstate\fP() , the Base
+Definitions volume of IEEE\ Std\ 1003.1-2001,
+\fI<pthread.h>\fP
+.SH COPYRIGHT
+Portions of this text are reprinted and reproduced in electronic form
+from IEEE Std 1003.1, 2003 Edition, Standard for Information Technology
+-- Portable Operating System Interface (POSIX), The Open Group Base
+Specifications Issue 6, Copyright (C) 2001-2003 by the Institute of
+Electrical and Electronics Engineers, Inc and The Open Group. In the
+event of any discrepancy between this version and the original IEEE and
+The Open Group Standard, the original IEEE and The Open Group Standard
+is the referee document. The original Standard can be obtained online at
+http://www.opengroup.org/unix/online.html .