summaryrefslogtreecommitdiffstats
path: root/man2/futex.2
diff options
context:
space:
mode:
Diffstat (limited to 'man2/futex.2')
-rw-r--r--man2/futex.264
1 files changed, 32 insertions, 32 deletions
diff --git a/man2/futex.2 b/man2/futex.2
index eb4abac9e..559990e27 100644
--- a/man2/futex.2
+++ b/man2/futex.2
@@ -1781,10 +1781,10 @@ Child (18535) 4
.\" SRC BEGIN (futex.c)
.EX
/* futex_demo.c
-
+\&
Usage: futex_demo [nloops]
(Default: 5)
-
+\&
Demonstrate the use of futexes in a program where parent and child
use a pair of futexes located inside a shared anonymous mapping to
synchronize access to a shared resource: the terminal. The two
@@ -1805,9 +1805,9 @@ Child (18535) 4
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
-
+\&
static uint32_t *futex1, *futex2, *iaddr;
-
+\&
static int
futex(uint32_t *uaddr, int futex_op, uint32_t val,
const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3)
@@ -1815,111 +1815,111 @@ futex(uint32_t *uaddr, int futex_op, uint32_t val,
return syscall(SYS_futex, uaddr, futex_op, val,
timeout, uaddr2, val3);
}
-
+\&
/* Acquire the futex pointed to by \[aq]futexp\[aq]: wait for its value to
become 1, and then set the value to 0. */
-
+\&
static void
fwait(uint32_t *futexp)
{
long s;
const uint32_t one = 1;
-
+\&
/* atomic_compare_exchange_strong(ptr, oldval, newval)
atomically performs the equivalent of:
-
+\&
if (*ptr == *oldval)
*ptr = newval;
-
+\&
It returns true if the test yielded true and *ptr was updated. */
-
+\&
while (1) {
-
+\&
/* Is the futex available? */
if (atomic_compare_exchange_strong(futexp, &one, 0))
break; /* Yes */
-
+\&
/* Futex is not available; wait. */
-
+\&
s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0);
if (s == \-1 && errno != EAGAIN)
err(EXIT_FAILURE, "futex\-FUTEX_WAIT");
}
}
-
+\&
/* Release the futex pointed to by \[aq]futexp\[aq]: if the futex currently
has the value 0, set its value to 1 and then wake any futex waiters,
so that if the peer is blocked in fwait(), it can proceed. */
-
+\&
static void
fpost(uint32_t *futexp)
{
long s;
const uint32_t zero = 0;
-
+\&
/* atomic_compare_exchange_strong() was described
in comments above. */
-
+\&
if (atomic_compare_exchange_strong(futexp, &zero, 1)) {
s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0);
if (s == \-1)
err(EXIT_FAILURE, "futex\-FUTEX_WAKE");
}
}
-
+\&
int
main(int argc, char *argv[])
{
pid_t childPid;
unsigned int nloops;
-
+\&
setbuf(stdout, NULL);
-
+\&
nloops = (argc > 1) ? atoi(argv[1]) : 5;
-
+\&
/* Create a shared anonymous mapping that will hold the futexes.
Since the futexes are being shared between processes, we
subsequently use the "shared" futex operations (i.e., not the
ones suffixed "_PRIVATE"). */
-
+\&
iaddr = mmap(NULL, sizeof(*iaddr) * 2, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, \-1, 0);
if (iaddr == MAP_FAILED)
err(EXIT_FAILURE, "mmap");
-
+\&
futex1 = &iaddr[0];
futex2 = &iaddr[1];
-
+\&
*futex1 = 0; /* State: unavailable */
*futex2 = 1; /* State: available */
-
+\&
/* Create a child process that inherits the shared anonymous
mapping. */
-
+\&
childPid = fork();
if (childPid == \-1)
err(EXIT_FAILURE, "fork");
-
+\&
if (childPid == 0) { /* Child */
for (unsigned int j = 0; j < nloops; j++) {
fwait(futex1);
printf("Child (%jd) %u\en", (intmax_t) getpid(), j);
fpost(futex2);
}
-
+\&
exit(EXIT_SUCCESS);
}
-
+\&
/* Parent falls through to here. */
-
+\&
for (unsigned int j = 0; j < nloops; j++) {
fwait(futex2);
printf("Parent (%jd) %u\en", (intmax_t) getpid(), j);
fpost(futex1);
}
-
+\&
wait(NULL);
-
+\&
exit(EXIT_SUCCESS);
}
.EE