summaryrefslogtreecommitdiffstats
path: root/man-pages-posix-2013/man3p/pthread_cleanup_pop.3p
diff options
context:
space:
mode:
Diffstat (limited to 'man-pages-posix-2013/man3p/pthread_cleanup_pop.3p')
-rw-r--r--man-pages-posix-2013/man3p/pthread_cleanup_pop.3p335
1 files changed, 335 insertions, 0 deletions
diff --git a/man-pages-posix-2013/man3p/pthread_cleanup_pop.3p b/man-pages-posix-2013/man3p/pthread_cleanup_pop.3p
new file mode 100644
index 0000000..19c80c6
--- /dev/null
+++ b/man-pages-posix-2013/man3p/pthread_cleanup_pop.3p
@@ -0,0 +1,335 @@
+'\" et
+.TH PTHREAD_CLEANUP_POP "3P" 2013 "IEEE/The Open Group" "POSIX Programmer's Manual"
+.SH PROLOG
+This manual page is part of the POSIX Programmer's Manual.
+The Linux implementation of this interface may differ (consult
+the corresponding Linux manual page for details of Linux behavior),
+or the interface may not be implemented on Linux.
+
+.SH NAME
+pthread_cleanup_pop,
+pthread_cleanup_push
+\(em establish cancellation handlers
+.SH SYNOPSIS
+.LP
+.nf
+#include <pthread.h>
+.P
+void pthread_cleanup_pop(int \fIexecute\fP);
+void pthread_cleanup_push(void (*\fIroutine\fP)(void*), void *\fIarg\fP);
+.fi
+.SH DESCRIPTION
+The
+\fIpthread_cleanup_pop\fR()
+function shall remove the routine at the top of the calling thread's
+cancellation cleanup stack and optionally invoke it (if
+.IR execute
+is non-zero).
+.P
+The
+\fIpthread_cleanup_push\fR()
+function shall push the specified cancellation cleanup handler
+.IR routine
+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
+.IR arg
+when:
+.IP " *" 4
+The thread exits (that is, calls
+\fIpthread_exit\fR()).
+.IP " *" 4
+The thread acts upon a cancellation request.
+.IP " *" 4
+The thread calls
+\fIpthread_cleanup_pop\fR()
+with a non-zero
+.IR execute
+argument.
+.P
+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\fR()
+macro may be thought to expand to a token list whose first token is
+.BR '{'
+with
+\fIpthread_cleanup_pop\fR()
+expanding to a token list whose last token is the corresponding
+.BR '}' ).
+.P
+The effect of calling
+\fIlongjmp\fR()
+or
+\fIsiglongjmp\fR()
+is undefined if there have been any calls to
+\fIpthread_cleanup_push\fR()
+or
+\fIpthread_cleanup_pop\fR()
+made without the matching call since the jump buffer was filled. The
+effect of calling
+\fIlongjmp\fR()
+or
+\fIsiglongjmp\fR()
+from inside a cancellation cleanup handler is also undefined unless the
+jump buffer was also filled in the cancellation cleanup handler.
+.P
+The effect of the use of
+.BR return ,
+.BR break ,
+.BR continue ,
+and
+.BR goto
+to prematurely leave a code block described by a pair of
+\fIpthread_cleanup_push\fR()
+and
+\fIpthread_cleanup_pop\fR()
+functions calls is undefined.
+.SH "RETURN VALUE"
+The
+\fIpthread_cleanup_push\fR()
+and
+\fIpthread_cleanup_pop\fR()
+functions shall not return a value.
+.SH ERRORS
+No errors are defined.
+.P
+These functions shall not return an error code of
+.BR [EINTR] .
+.LP
+.IR "The following sections are informative."
+.SH EXAMPLES
+The following is an example using thread primitives to implement a
+cancelable, writers-priority read-write lock:
+.sp
+.RS 4
+.nf
+\fB
+typedef 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;
+.P
+void
+waiting_reader_cleanup(void *arg)
+{
+ rwlock *l;
+.P
+ l = (rwlock *) arg;
+ pthread_mutex_unlock(&l->lock);
+}
+.P
+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);
+}
+.P
+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->lock);
+}
+.P
+void
+waiting_writer_cleanup(void *arg)
+{
+ rwlock *l;
+.P
+ l = (rwlock *) arg;
+ if ((-\|-l->waiting_writers == 0) && (l->lock_count >= 0)) {
+ /*
+ * This only happens if we have been canceled. If the
+ * lock is not held by a writer, there may be readers who
+ * were blocked because waiting_writers was positive; they
+ * can now be unblocked.
+ */
+ pthread_cond_broadcast(&l->rcond);
+ }
+ pthread_mutex_unlock(&l->lock);
+}
+.P
+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 = \(mi1;
+ /*
+ * Note the pthread_cleanup_pop executes
+ * waiting_writer_cleanup.
+ */
+ pthread_cleanup_pop(1);
+}
+.P
+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);
+}
+.P
+/*
+ * 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;
+}
+.P
+reader_thread()
+{
+ lock_for_read(&lock);
+ pthread_cleanup_push(release_read_lock, &lock);
+ /*
+ * Thread has read lock.
+ */
+ pthread_cleanup_pop(1);
+}
+.P
+writer_thread()
+{
+ lock_for_write(&lock);
+ pthread_cleanup_push(release_write_lock, &lock);
+ /*
+ * Thread has write lock.
+ */
+pthread_cleanup_pop(1);
+}
+.fi \fR
+.P
+.RE
+.SH "APPLICATION USAGE"
+The two routines that push and pop cancellation cleanup handlers,
+\fIpthread_cleanup_push\fR()
+and
+\fIpthread_cleanup_pop\fR(),
+can be thought of as left and right-parentheses. They always need to
+be matched.
+.SH RATIONALE
+The restriction that the two routines that push and pop
+cancellation cleanup handlers,
+\fIpthread_cleanup_push\fR()
+and
+\fIpthread_cleanup_pop\fR(),
+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 4
+.nf
+\fB
+#define pthread_cleanup_push(rtn,arg) { \e
+ struct _pthread_handler_rec __cleanup_handler, **__head; \e
+ __cleanup_handler.rtn = rtn; \e
+ __cleanup_handler.arg = arg; \e
+ (void) pthread_getspecific(_pthread_handler_key, &__head); \e
+ __cleanup_handler.next = *__head; \e
+ *__head = &__cleanup_handler;
+.P
+#define pthread_cleanup_pop(ex) \e
+ *__head = __cleanup_handler.next; \e
+ if (ex) (*__cleanup_handler.rtn)(__cleanup_handler.arg); \e
+}
+.fi \fR
+.P
+.RE
+.P
+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.
+.P
+This volume of POSIX.1\(hy2008 currently leaves unspecified the effect of calling
+\fIlongjmp\fR()
+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\fR()
+function has to call all cancellation cleanup handlers that have been
+pushed but not popped since the time
+\fIsetjmp\fR()
+was called.
+.P
+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\fR()
+and that handler were to call
+\fIlongjmp\fR()
+(which, in turn, did
+.IR not
+call the cancellation cleanup handlers) the helper threads created by
+the
+\fIqsort\fR()
+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.
+.P
+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.
+.P
+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"
+None.
+.SH "SEE ALSO"
+.IR "\fIpthread_cancel\fR\^(\|)",
+.IR "\fIpthread_setcancelstate\fR\^(\|)"
+.P
+The Base Definitions volume of POSIX.1\(hy2008,
+.IR "\fB<pthread.h>\fP"
+.SH COPYRIGHT
+Portions of this text are reprinted and reproduced in electronic form
+from IEEE Std 1003.1, 2013 Edition, Standard for Information Technology
+-- Portable Operating System Interface (POSIX), The Open Group Base
+Specifications Issue 7, Copyright (C) 2013 by the Institute of
+Electrical and Electronics Engineers, Inc and The Open Group.
+(This is POSIX.1-2008 with the 2013 Technical Corrigendum 1 applied.) 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.unix.org/online.html .
+
+Any typographical or formatting errors that appear
+in this page are most likely
+to have been introduced during the conversion of the source files to
+man page format. To report such errors, see
+https://www.kernel.org/doc/man-pages/reporting_bugs.html .