man page for robust mutexes

From: Sebastian Andrzej Siewior
Date: Mon Dec 01 2008 - 16:35:26 EST


Robust mutexes are available since a few days, so here is a man page for
them. I used pthread_mutexattr_setprotocol.3p as a template and sneaked a
few phrases from there. That's my first man-page however, so some things
might be wrong :)

Sebastian
--- /dev/null
+++ b/man3p/pthread_mutexattr_setrobust_np.3p
@@ -0,0 +1,240 @@
+.\" Copyright (c) 2008 Sebastian Andrzej Siewior
+.TH "ROBUST MUTEXES" P 2008 "" "POSIX Programmer's Manual"
+.\" pthread_mutexattr_setrobust_np
+.SH NAME
+pthread_mutexattr_setrobust_np, pthread_mutexattr_getrobust_np \- set or get
+the robustness of a mutex
+.SH SYNOPSIS
+.LP
+\fB#include <pthread.h>
+.br
+.sp
+#define __USE_GNU
+.sp
+int pthread_mutexattr_getrobust_np(pthread_mutexattr_t *\fP\fIattr\fP\fB, int
+\fP\fIrobustness\fP\fB);
+.br
+int pthread_mutexattr_setrobust_np(pthread_mutexattr_t *\fP\fIattr\fP\fB, int
+\fP\fIrobustness\fP\fB);
+.br
+int pthread_mutex_consistent_np(pthread_mutex_t *\fP\fImutex\fP\fB);
+\fP
+\fB
+.br
+\fP
+.SH DESCRIPTION
+.LP
+The \fIpthread_mutexattr_getrobust_np\fP() and
+\fIpthread_mutexattr_setrobust_np\fP() functions, respectively, shall get and
+set the robustness attribute of a mutex attributes object pointed to by
+\fIattr\fP which was previously created by the function
+\fIpthread_mutexattr_init\fP().
+.LP
+The \fIrobustness\fP attribute defines the robustness to be used in utilizing
+mutexes. The value of \fIrobustness\fP may be one of:
+.LP
+.sp
+PTHREAD_MUTEX_STALLED_NP
+.br
+.sp
+PTHREAD_MUTEX_ROBUST_NP
+.br
+.sp
+.LP
+which are defined in the \fI<pthread.h>\fP header if the GNU extensions are
+used.
+.LP
+The default attribute is PTHREAD_MUTEX_STALLED_NP.
+.LP
+When a mutex is created with PTHREAD_MUTEX_STALLED_NP is locked and the owner
+dies, then the next call to pthread_mutex_lock() will block forever. Also,
+the already waiting waiters will wait for ever.
+.LP
+The behavior is different if the mutex is created with
+PTHREAD_MUTEX_ROBUST_NP. If the owner dies while holding the lock, the
+next call to \fIpthread_mutex_lock\fP() will return EOWNERDEAD and the caller
+will acquire lock. The new owner should call
+\fIpthread_mutex_consistent_np\fP() on the mutex once the internal state of
+the protected variables are consistent again. If this is not done, future
+calls to pthread_mutex_lock() will continue to return EOWNERDEAD (although
+locking will function correctly).
+.SH RETURN VALUE
+.LP
+Upon successful completion, \fIpthread_mutexattr_setrobust_np\fP(),
+\fIpthread_mutexattr_getrobust_np\fP() and
+\fIpthread_mutex_consistent_np\fP()shall return zero; otherwise,
+an error number shall be returned to indicate the error.
+.SH ERRORS
+.LP
+The \fIpthread_mutexattr_destroy\fP() function may fail if:
+.TP 7
+.B EINVAL
+The value specified by \fIrobustness\fP is invalid.
+.LP
+The \fIpthread_mutex_consistent_np\fp() function may fail if:
+.TP 7
+.B EINVAL
+The mutex specified by \fImutex\fP is either not PTHREAD_MUTEX_ROBUST_NP or is
+in consistent state.
+\fIThe following sections are informative.\fP
+.SH EXAMPLES
+.LP
+The robost mutexes could be used to share a common lock accross multiple
+process and avoid IPC communication. Here is an example:
+.sp
+.RS
+.nf
+\fB
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#define __USE_GNU
+#include <pthread.h>
+
+static const char *lock_name = "/dev/shm/limi_lock";
+static int lock_fd;
+static void *limi_ressource;
+static pthread_mutex_t *limi_mutex;
+
+.sp
+
+static int open_existing_lock(void)
+{
+ int fd;
+ int ret;
+ struct stat buf;
+ int retry = 5;
+
+ fd = open(lock_name, O_RDWR);
+ if (fd < 0)
+ return fd;
+ do {
+
+ ret = fstat(fd, &buf);
+ if (ret < 0)
+ return ret;
+
+ if (buf.st_size == sizeof(*limi_mutex))
+ return fd;
+
+ sleep(1);
+ retry--;
+ } while (retry);
+
+ close(fd);
+ return -1;
+}
+
+.sp
+
+static int create_new_lock(void)
+{
+ int fd;
+ pthread_mutex_t cmutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutexattr_t attr;
+ int ret;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP);
+ pthread_mutex_init(&cmutex, &attr);
+
+ fd = open(lock_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP);
+ if (fd < 0)
+ return fd;
+
+ ret = write(fd, &cmutex, sizeof(cmutex));
+ if (ret < 0) {
+ fprintf(stderr, "Write to %s failed: %s\n",
+ lock_name, strerror(errno));
+ exit(1);
+ }
+ return fd;
+}
+
+.sp
+
+void limi_lock_init(void)
+{
+ lock_fd = open_existing_lock();
+ if (lock_fd < 0) {
+ lock_fd = create_new_lock();
+ if (lock_fd < 0) {
+ lock_fd = open_existing_lock();
+ if (lock_fd < 0) {
+ fprintf(stderr, "Can't open %s: %s\n",
+ lock_name, strerror(errno));
+ exit(1);
+ }
+ }
+ }
+
+ limi_lock_mmap = mmap(NULL, sizeof(*limi_mutex),
+ PROT_READ | PROT_WRITE, MAP_SHARED, lock_fd, 0);
+
+ if (limi_lock_mmap == MAP_FAILED) {
+ fprintf(stderr, "failed to mmap limi lock: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ limi_mutex = limi_lock_mmap;
+}
+
+.sp
+
+void limi_lock(void)
+{
+ int ret;
+
+ ret = pthread_mutex_lock(limi_mutex);
+ if (!ret)
+ return;
+
+ if (ret == EOWNERDEAD) {
+ pthread_mutex_consistent_np(limi_mutex);
+ return;
+ }
+
+ fprintf(stderr, "Can not grab lock: %s\n", strerror(ret));
+ exit(1);
+}
+
+.sp
+
+void limi_unlock(void)
+{
+ int ret;
+
+ ret = pthread_mutex_unlock(limi_mutex);
+ if (!ret)
+ return;
+
+ fprintf(stderr, "Can not unlock: %s\n", strerror(ret));
+ exit(1);
+}
+
+\fP
+.fi
+.RE
+.LP
+The code example shows how to share a lock between two applications without
+classic IPC. If one of the applications dies while holding the lock or the
+system reboots unexpectly, the new owner of lock marks the lock state
+consistent. In this example the lock owner does not need to perform any
+validation of the resource protected by the lock. The lock owner knows if
+the previous owner unlocked successfully or died.
+.f
+.SH SEE ALSO
+.LP
+\fIpthread_mutex_create\fP(), \fIpthread_mutex_destroy\fP(),
+\fIpthread_mutexattr_init\fP(), \fIpthread_mutexattr_destroy\fP(),
+\fIpthread_mutex_lock\fP(), \fIpthread_mutex_unlock\fP(), \fI<pthread.h>\fP
+.SH COPYRIGHT
+This man page was contributed by Sebastian Andrzej Siewior.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/