/* Written by Richard Parkins, rparkins@undo-software.com. */ /* Copyright 2009, Undo Ltd. */ /* Released under the GNU Public Licence. */ /* Futex test */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include /* Some distros have broken definitions of these. */ #undef FUTEX_WAIT_BITSET_PRIVATE #undef FUTEX_WAKE_BITSET_PRIVATE #undef FUTEX_OP #define FUTEX_WAIT_BITSET_PRIVATE (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG) #define FUTEX_WAKE_BITSET_PRIVATE (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG) #define FUTEX_OP(op, oparg, cmp, cmparg) \ ((((op) & 0xf) << 28) | (((cmp) & 0xf) << 24) \ | (((oparg) & 0xfff) << 12) | ((cmparg) & 0xfff)) /* futex, tkill, and gettid system calls are not defined in header files. */ #define futex( arg1, arg2, arg3, arg4, arg5, arg6) \ syscall(SYS_futex, arg1, arg2, arg3, arg4, arg5, arg6) #define tkill( arg1, arg2) \ syscall(SYS_tkill, arg1, arg2) #define gettid() \ syscall(SYS_gettid) static struct timespec TEN_ms = {0, 10*1000*1000}; static struct timespec ONE_sec = {1, 0}; static FILE * status; static int f1, f2; static int thread_action; struct sha { int f3; int f4; int child_action; }; static struct sha * shmem; static pid_t parent_pid, thread_pid, child_pid; static char ths[0x20000]; #define thread_stack (ths + sizeof(ths) - sizeof(long)) static int parent_sleeping(void) { /* Note when called from the child (a forked process), this is a different * copy of the FILE object from that used when called from the thread. */ rewind(status); int i; char c; int r = fscanf(status, "%d %*s %c", &i, &c); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d fscanf failed %s\n", __LINE__, strerror(errno)); } else { fprintf(stderr, "At line %d fscanf returned %d instead of 2\n", __LINE__, r); } tkill(parent_pid, SIGKILL); tkill(child_pid, SIGKILL); exit(1); } return (c == 'S'); } /* Thread waits for thread_action to be nonzero * (and for some actions for the parent to be waiting for it), * and then does the required action. */ static int thread(void * arg __attribute__ ((unused))) { int r; while (1) { switch (thread_action) { case -1: case 0: break; case 1: if (parent_sleeping()) { thread_action = 0; r = futex(&f1, FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); } else { fprintf(stderr, "At line %d futex returned %d instead of 1\n", __LINE__, r); } tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } break; case 2: if (parent_sleeping()) { thread_action = 0; r = futex(&f1, FUTEX_WAKE_PRIVATE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); } else { fprintf(stderr, "At line %d futex returned %d instead of 1\n", __LINE__, r); } tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } break; case 3: if (parent_sleeping()) { thread_action = 0; r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); } else { fprintf(stderr, "At line %d futex returned %d instead of 1\n", __LINE__, r); } tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } break; case 4: thread_action = -1; /* It is possible that a thread switch occurs here: * wait_for_thread() does an extra 10ms sleep to give this * thread a chance to start the wait, but on a busy machine * it may not get to run and the test on the number of * processes woken will fail. Of course futexes are designed * just to avoid this sort of race, but since we are testing * futexes here we can't use one. */ r = futex(&f1, FUTEX_WAIT, f1, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 5: thread_action = -1; r = futex(&f1, FUTEX_WAIT_PRIVATE, f1, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 6: thread_action = -1; r = futex(&(shmem->f3), FUTEX_WAIT, shmem->f3, &ONE_sec, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 7: thread_action = -1; r = futex(&f1, FUTEX_LOCK_PI, 0, &TEN_ms, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 8: thread_action = -1; r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, &TEN_ms, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 9: thread_action = -1; r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, &TEN_ms, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 10: if (parent_sleeping()) { thread_action = 0; r = futex(&f1, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } break; case 11: if (parent_sleeping()) { thread_action = 0; r = futex(&f1, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } break; case 12: if (parent_sleeping()) { thread_action = 0; r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } break; case 13: thread_action = -1; r = futex(&f1, FUTEX_WAIT_BITSET, f1, NULL, NULL, 0x3); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 14: thread_action = -1; r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, f1, NULL, NULL, 0x30); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 15: thread_action = -1; r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, shmem->f3, NULL, NULL, 0x300); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 16: thread_action = -1; r = futex(&f1, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 17: thread_action = -1; r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 18: thread_action = -1; r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } break; case 19: thread_action = -1; break; default: fprintf(stderr, "At line %d invalid thread_action %d\n", __LINE__, thread_action); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); tkill(parent_pid, SIGKILL); exit(1); } } } static void wft(long line) { int r; for (r = 0; thread_action; ++r) { if (r > 6000) { fprintf(stderr, "wait_for_thread from line %ld thread not responding\n", line); tkill(child_pid, SIGKILL); exit(1); } if (thread_action < 0) { thread_action = 0; } if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "wait_for_thread from line %ld nanosleep failed %s\n", line, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } } #define wait_for_thread() wft(__LINE__) /* Child process waits for shmem->child_action to be nonzero * (and for some actions for the parent to be waiting for it), * and then does the required action. */ static void child(void) { int r; while (1) { switch (shmem->child_action) { case 0: case -1: break; case 3: if (parent_sleeping()) { shmem->child_action = 0; r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); } else { fprintf(stderr, "At line %d futex returned %d instead of 1\n", __LINE__, r); } tkill(parent_pid, SIGKILL); exit(1); } } break; case 6: shmem->child_action = -1; r = futex(&(shmem->f3), FUTEX_WAIT, shmem->f3, &ONE_sec, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } break; case 9: shmem->child_action = -1; r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, &TEN_ms, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } break; case 12: if (parent_sleeping()) { shmem->child_action = 0; r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } } break; case 15: shmem->child_action = -1; r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, shmem->f3, NULL, NULL, 0x300); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } break; case 16: shmem->child_action = -1; r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, NULL, NULL, 0x3000); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } /* It is possible that a process switch occurs here: * The main program does a 10ms wait to give this process time * to set shmem->child_action, but on a busy machine it may not * get to run and the test will fail. Of course futexes are * designed just to avoid this sort of race, but since we are * testing futexes here we can't use one. */ shmem->child_action = 17; break; case 17: break; case 18: shmem->child_action = -1; r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } break; case 19: shmem->child_action = -1; break; default: fprintf(stderr, "At line %d invalid child_action %d\n", __LINE__, shmem->child_action); tkill(parent_pid, SIGKILL); exit(1); } if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(parent_pid, SIGKILL); exit(1); } } } static void wfc (long line) { int r; for (r = 0; shmem->child_action; ++r) { if (r > 6000) { fprintf(stderr, "wait_for_child from line %ld child not responding\n", line); tkill(child_pid, SIGKILL); exit(1); } if (shmem->child_action < 0) { shmem->child_action = 0; } if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "wait_for_child from line %ld nanosleep failed %s\n", line, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } } #define wait_for_child() wfc(__LINE__) int main(int argc __attribute__ ((unused)), char* argv[] __attribute__ ((unused))) { /* Get a handle on our status for the child to use. */ status = fopen("/proc/self/stat", "r"); if (!status) { fprintf(stderr, "At line %d fopen failed %s\n", __LINE__, strerror(errno)); exit(1); } /* Allocate two shared memory pages. */ shmem = (struct sha *)mmap(NULL, 2 * 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (shmem == MAP_FAILED) { fprintf(stderr, "At line %d mmap failed %s\n", __LINE__, strerror(errno)); exit(1); } /* Re-protect the second to ensure shmem+4096 is invalid. */ if (mprotect(4096 + (char *)shmem, 4096, PROT_NONE)) { fprintf(stderr, "At line %d mprotect failed %s\n", __LINE__, strerror(errno)); exit(1); } shmem->child_action = 0; thread_action = 0; /* Get an address in undodb private space */ FILE *maps = fopen("/proc/self/maps", "r"); if (!maps) { fprintf(stderr, "At line %d fopen failed %s\n", __LINE__, strerror(errno)); exit(1); } char buff[1024]; char * upriv = (char *)8; while (fgets(buff, sizeof(buff), maps)) { size_t i; for (i = 0; i < strlen(buff); ++i) { if ( (strncmp("preload1", buff + i, 8) == 0) || (strncmp("gdbmacro-release", buff + i, 8) == 0)) { if (sscanf(buff, "%lx-", (unsigned long*)&upriv) == 1) { break; } else { fprintf(stderr, "sscanf(\"%s\", \"%%lx-\") != 1", buff); } } } } if (upriv == (char *)8) { fprintf(stderr, "Could not find undodb private space\n"); /* not fatal */ } /* Create a child thread and a child process. */ parent_pid = gettid(); thread_pid = clone(thread, thread_stack, CLONE_VM | CLONE_THREAD | CLONE_SIGHAND, NULL, NULL, NULL, NULL); if (thread_pid < 0) { fprintf(stderr, "At line %d clone failed %s\n", __LINE__, strerror(errno)); exit(1); } child_pid = fork(); if (child_pid < 0) { fprintf(stderr, "At line %d fork failed %s\n", __LINE__, strerror(errno)); exit(1); } else if (child_pid == 0) { child(); } /* Otherwise continue with parent being debugged. */ int r = futex(NULL, FUTEX_WAIT, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAIT, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAIT, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAIT, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAIT_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_WAIT, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_WAIT, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } f1 = 0; r = futex(&f1, FUTEX_WAIT, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_WAIT with *uaddr != val returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_PRIVATE, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with *uaddr != val returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } shmem->f3 = 0; r = futex(&(shmem->f3), FUTEX_WAIT, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_WAIT with *uaddr != val returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT, 0, (struct timespec *)8, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad timeout returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_PRIVATE, 0, (struct timespec *)8, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with bad timeout returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT, 0, (struct timespec *)8, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad timeout returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT, 0, (struct timespec *)upriv, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad timeout returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_PRIVATE, 0, (struct timespec *)upriv, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE with bad timeout returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT, 0, (struct timespec *)upriv, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT with bad timeout returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_WAIT which should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_PRIVATE, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_WAIT_PRIVATE which should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_WAIT which should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 1; r = futex(&f1, FUTEX_WAIT, 0, &ONE_sec, &f2, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 1; r = futex(&f1, FUTEX_WAIT, 0, &ONE_sec, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 1; r = futex(&f1, FUTEX_WAIT, 0, &ONE_sec, (int *)8, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 1; r = futex(&f1, FUTEX_WAIT, 0, &ONE_sec, (int *)upriv, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 2; r = futex(&f1, FUTEX_WAIT_PRIVATE, 0, &ONE_sec, NULL, 1); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 3; r = futex(&(shmem->f3), FUTEX_WAIT, 0, &ONE_sec, NULL, 2); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } shmem->child_action = 3; r = futex(&(shmem->f3), FUTEX_WAIT, 0, &ONE_sec, NULL, 3); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } /* Curiously, the kernel returns 0 on this call, although no process can be * wakened, since futex(NULL, FUTEX_WAIT_PRIVATE, ...) fails. */ r = futex(NULL, FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "FUTEX_WAKE_PRIVATE with bad address succeeds\n"); } r = futex((int *)8, FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(-8), FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(-8), FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0); #ifdef __i386__ if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } #else if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } #endif r = futex((int *)(1 + (char *)&f1), FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d futex with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_WAKE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE, 3, (struct timespec *)upriv, (int *)upriv, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when no processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_PRIVATE, 3, (struct timespec *)upriv, (int *)upriv, 2); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when no processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 3, (struct timespec *)upriv, (int *)upriv, 1); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when no processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_WAKE, 3, (struct timespec *)upriv, (int *)upriv, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_PRIVATE, 3, (struct timespec *)upriv, (int *)upriv, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE, 3, (struct timespec *)upriv, (int *)upriv, 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE, 3, (struct timespec *)upriv, (int *)upriv, 6); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE, 3, (struct timespec *)upriv, (int *)upriv, 7); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when 2 processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE, 1, (struct timespec *)upriv, (int *)upriv, 8); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 0, NULL, NULL, 9); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "FUTEX_WAKE with zero val woke a process\n"); /* It isn't clear whether this is a bug in the kernel or the * manual page, which says "wakes at most val processes". */ } } else { r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 10); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE, -1, NULL, NULL, 11); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "FUTEX_WAKE with negative val woke a process\n"); /* It isn't clear whether this is a bug in the kernel or the * manual page, which says "wakes at most val processes". */ } } else { r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 12); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } } r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 13); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } /* Note the man page says that the arg 5 (timeout) is ignored for * FUTEX_REQUEUE and FUTEX_CMP_REQUEUE, but the kernel does use it as * the maximum number of processes to requeue. However if it is 0, the * kernel still requeues one process. * Also the man page says it returns the number of processes woken up, * but actually it returns the number of processes woken or requeued. */ r = futex(&f1, FUTEX_REQUEUE, 1, NULL, &f2, 0); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_REQUEUE not supported in this kernel\n"); /* not fatal */ } else { if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when no process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, &f2, 1); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when no process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_REQUEUE, 1, NULL, &(shmem->f4), 2); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when no process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(NULL, FUTEX_REQUEUE, 1, NULL, &f2, 3); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_REQUEUE_PRIVATE, 1, (struct timespec *)2, &f2, 4); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE, 1, NULL, NULL, 5); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, NULL, 6); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_REQUEUE, 1, NULL, &f2, 7); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_REQUEUE_PRIVATE, 1, NULL, &f2, 8); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_REQUEUE, 1, NULL, &f2, 9); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_REQUEUE_PRIVATE, 1, NULL, &f2, 10); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE, 1, NULL, (int *)8, 11); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, (int *)8, 12); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE, 1, NULL, (int *)upriv, 13); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, (int *)upriv, 14); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_REQUEUE, 1, NULL, &f2, 15); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_REQUEUE_PRIVATE, 1, NULL, &f2, 16); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE, 1, NULL, (int *)(1 + (char *)&f1), 17); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, (int *)(1 + (char *)&f1), 18); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_REQUEUE, 1, NULL, &f2, 19); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE, 1, NULL, (int *)(1 + (char *)&(shmem->f3)), 20); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_REQUEUE, 1, NULL, &f2, 21); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_REQUEUE, 1, NULL, (int *)(4094 + (char *)&(shmem->f3)), 22); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE, 0, NULL, &f2, 23); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } else { fprintf(stderr, "FUTEX_REQUEUE returns 1 when waking no processes but requeueing one\n"); /* Probably a man page error. */ } /* We woke none, so one should be requeued on f2. */ r = futex(&f2, FUTEX_WAKE, 1, NULL, NULL, 24); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 0, NULL, &f2, 25); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } /* We woke none, so one should be requeued on f2. */ r = futex(&f2, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 26); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE, 1, NULL, &f2, 27); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, &f2, 28); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE, 2, NULL, &f2, 29); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 2, NULL, &f2, 30); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); /* Requeue to same futex is allowed. */ r = futex(&f1, FUTEX_REQUEUE, 0, NULL, &f1, 31); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 0, NULL, &f1, 32); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE, 1, NULL, &f1, 33); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 1, NULL, &f1, 34); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE, 2, NULL, &f1, 35); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_REQUEUE_PRIVATE, 2, NULL, &f1, 36); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 0, NULL, &(shmem->f4), 37); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 1, NULL, NULL, 38); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d futex returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 1, NULL, &(shmem->f4), 39); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 2, NULL, &(shmem->f4), 40); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 0, NULL, &(shmem->f3), 41); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 42); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 1, NULL, &(shmem->f3), 43); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 2, NULL, &(shmem->f3), 44); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 0, NULL, &(shmem->f4), 45); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 46); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 47); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 0, (struct timeout *)1, &(shmem->f4), 48); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 49); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 50); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 0, (struct timeout *)2, &(shmem->f4), 51); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 52); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 1, NULL, &(shmem->f4), 53); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d instead of 2\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 54); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 2, NULL, &(shmem->f4), 55); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 0, NULL, &(shmem->f3), 56); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 57); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 1, NULL, &(shmem->f3), 58); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d instead of 2\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 59); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_REQUEUE, 2, NULL, &(shmem->f3), 60); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_REQUEUE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } } f1 = 0; r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f2, 0); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_CMP_REQUEUE not supported in this kernel\n"); /* not fatal */ } else { if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when no process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } f1 = 1; r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 1); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when no process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } f1 = 2; r = futex(NULL, FUTEX_CMP_REQUEUE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, NULL, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, NULL, 2); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_CMP_REQUEUE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, (int *)8, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, (int *)8, 2); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_CMP_REQUEUE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, (int *)upriv, 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, (int *)upriv, 2); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_CMP_REQUEUE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, (int *)(1 + (char *)&f1), 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, (int *)(1 + (char *)&f1), 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_CMP_REQUEUE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, (int *)(1 + (char *)&(shmem->f3)), 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_CMP_REQUEUE, 1, NULL, &f2, 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, (int *)(4094 + (char *)&(shmem->f3)), 2); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } f1 = 3; thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 0, NULL, &f2, 0); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 0, NULL, &f2, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 0, NULL, &f2, 0); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 0, NULL, &f2, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f2, 0); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f2, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 0); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f2, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f2, 0); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f2, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 2, NULL, &f2, 0); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 2, NULL, &f2, 3); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f1, 4); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } f1 = 4; r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d futex returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 0, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 0, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 2, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 2, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 0, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 0, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 0, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 0, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 1, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 1, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE, 2, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 2, NULL, &f1, 3); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_CMP_REQUEUE_PRIVATE, 2, NULL, &f1, 4); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->f3 = 5; thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, NULL, &(shmem->f4), 4); if ((r >= 0) || (errno != EAGAIN)) { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE with non match returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EAGAIN)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, NULL, &(shmem->f4), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 1, NULL, &(shmem->f4), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 2, NULL, &(shmem->f4), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, NULL, &(shmem->f3), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 1, NULL, &(shmem->f3), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 2, NULL, &(shmem->f3), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, NULL, &(shmem->f4), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, (struct timeout *)1, &(shmem->f4), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, (struct timeout *)2, &(shmem->f4), 5); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 1, NULL, &(shmem->f4), 5); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d instead of 2\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 2, NULL, &(shmem->f4), 5); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 0, NULL, &(shmem->f3), 5); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when requeueing one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 1, NULL, &(shmem->f3), 5); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d instead of 2\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE, 2, NULL, NULL, 0); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_CMP_REQUEUE, 2, NULL, &(shmem->f3), 5); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_CMP_REQUEUE returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } } /* FUTEX_WAKE_OP isn't documented in the man page. From looking at the * kernel code, it does the following * arg6 encodes an operation, an operand, a comparison type, * and a comparisonn value. * Atomically perform the comparison and then the operation on *arg5 * Wake up to max(1, arg3) processess waiting on arg1 * If comparison succeeded * Wake up to (max(1, (int)arg4) processes waiting on arg5 * Returns total number of processes awakened. */ r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_WAKE_OP not supported in this kernel\n"); /* not fatal */ } else { if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } f1 = 0; f2 = 0; r = futex(NULL, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_WAKE_OP_PRIVATE, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAKE_OP_PRIVATE, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAKE_OP_PRIVATE, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAKE_OP_PRIVATE, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, NULL, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 0, NULL, NULL, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, (int *)8, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 0, NULL, (int *)8, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, (int *)upriv, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 0, NULL, (int *)upriv, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, (int *)(1 + (char *)&f2), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 0, NULL, (int *)(1 + (char *)&f2), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, (int *)(1 + (char *)&(shmem->f3)), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, (int *)(4094 + (char *)&(shmem->f3)), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(5, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad operation returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(6, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad operation returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(7, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad operation returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(13, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad operation returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(14, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad operation returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(15, 0, FUTEX_OP_CMP_EQ, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad operation returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, 6, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad comparison returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, 7, 0)); if ((r >= 0) || (errno != ENOSYS)) { fprintf(stderr, "At line %d FUTEX_WAKE_OP with bad comparison returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ENOSYS)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_OP, 2, (struct timespec *)2, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 2, (struct timespec *)2, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_OP, 0, NULL, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f2, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 2, NULL, &f1, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 2, NULL, &f1, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->f3 = 0; thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 2, NULL, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 2, NULL, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 0, NULL, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 2, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 2, NULL, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 2, NULL, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 0, NULL, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 2, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one processs\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE_OP, 1, NULL, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 1, NULL, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_OP, 3, NULL, &(shmem->f4), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)3, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } #ifdef __i386__ if (r == 1) { /* Wake the other one. */ (void)futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)3, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0, FUTEX_OP_CMP_EQ, 0)); fprintf(stderr, "KERNELBUG? FUTEX_WAKE_OP arg4 not decoded correctly in 32-bit\n"); } #endif else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking two processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_EQ, 1)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_EQ, 1)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_OR, 1, FUTEX_OP_CMP_EQ, 3)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_OR, 1, FUTEX_OP_CMP_EQ, 3)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_ANDN, 1, FUTEX_OP_CMP_EQ, 2)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_ANDN, 1, FUTEX_OP_CMP_EQ, 2)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_XOR, 3, FUTEX_OP_CMP_EQ, 1)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_XOR, 3, FUTEX_OP_CMP_EQ, 1)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP((FUTEX_OP_SET | FUTEX_OP_OPARG_SHIFT), 4, FUTEX_OP_CMP_EQ, (1 << 4))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP((FUTEX_OP_SET | FUTEX_OP_OPARG_SHIFT), 4, FUTEX_OP_CMP_EQ, (1 << 4))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-1), FUTEX_OP_CMP_NE, (1 << 4))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-1), FUTEX_OP_CMP_NE, (1 << 4))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-2), FUTEX_OP_CMP_LT, (-1))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-2), FUTEX_OP_CMP_LT, (-1))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-3), FUTEX_OP_CMP_LE, (-3))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-3), FUTEX_OP_CMP_LE, (-3))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-5), FUTEX_OP_CMP_LE, (-4))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-5), FUTEX_OP_CMP_LE, (-4))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 4, FUTEX_OP_CMP_GT, (-5))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 4, FUTEX_OP_CMP_GT, (-5))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 6, FUTEX_OP_CMP_GE, 6)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 6, FUTEX_OP_CMP_GE, 6)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (1 << 4), FUTEX_OP_CMP_NE, 6)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (1 << 4), FUTEX_OP_CMP_NE, 6)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-1), FUTEX_OP_CMP_NE, (1 << 4))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-1), FUTEX_OP_CMP_NE, (1 << 4))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-2), FUTEX_OP_CMP_LT, (-1))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-2), FUTEX_OP_CMP_LT, (-1))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-3), FUTEX_OP_CMP_LE, (-3))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-3), FUTEX_OP_CMP_LE, (-3))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-5), FUTEX_OP_CMP_LE, (-4))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (-5), FUTEX_OP_CMP_LE, (-4))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 4, FUTEX_OP_CMP_GT, (-5))); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 4, FUTEX_OP_CMP_GT, (-5))); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 6, FUTEX_OP_CMP_GE, 6)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, 6, FUTEX_OP_CMP_GE, 6)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (1 << 4), FUTEX_OP_CMP_NE, 6)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f2, FUTEX_WAKE_OP_PRIVATE, 0, (struct timespec *)2, &f1, FUTEX_OP(FUTEX_OP_SET, (1 << 4), FUTEX_OP_CMP_NE, 6)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP_PRIVATE returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfff, FUTEX_OP_CMP_NE, 0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfff, FUTEX_OP_CMP_NE, 0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffe, FUTEX_OP_CMP_LT, 0xfff)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffe, FUTEX_OP_CMP_LT, 0xfff)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffc, FUTEX_OP_CMP_LE, 0xffc)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffc, FUTEX_OP_CMP_LE, 0xffc)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfc0, FUTEX_OP_CMP_LE, 0xfc1)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfc0, FUTEX_OP_CMP_LE, 0xfc1)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 98, FUTEX_OP_CMP_GT, 97)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 98, FUTEX_OP_CMP_GT, 97)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 100, FUTEX_OP_CMP_GE, 99)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 100, FUTEX_OP_CMP_GE, 99)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfff, FUTEX_OP_CMP_NE, 100)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfff, FUTEX_OP_CMP_NE, 100)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffe, FUTEX_OP_CMP_LT, 0xfff)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffe, FUTEX_OP_CMP_LT, 0xfff)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffc, FUTEX_OP_CMP_LE, 0xffc)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xffc, FUTEX_OP_CMP_LE, 0xffc)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfc0, FUTEX_OP_CMP_LE, 0xff0)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 0xfc0, FUTEX_OP_CMP_LE, 0xff0)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 98, FUTEX_OP_CMP_GT, 97)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 98, FUTEX_OP_CMP_GT, 97)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 100, FUTEX_OP_CMP_GE, 99)); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking no processes\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f4), FUTEX_WAKE_OP, 0, (struct timespec *)2, &(shmem->f3), FUTEX_OP(FUTEX_OP_SET, 100, FUTEX_OP_CMP_GE, 99)); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_OP returned %d when waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } } /* FUTEX_LOCK_PI, FUTEX_UNLOCK_PI, and FUTEX_TRYLOCK_PI are also not documented. * Looking at Documentation/pi-futex.txt and the kernel code, * we find that FUTEX_LOCK_PI does:- * If *arg1 is 0, it is set to this task's TID and 0 is returned. * If *arg1 is already this task's TID, -EDEADLK is returned. * If *arg1 is not some other task's TID, -ESRCH is returned. * If *arg1 is some other task's TID, * That task's priority is raised if necessary to this task's priority, * (we don't test this). * This task waits until the other task does FUTEX_UNLOCK_PI. * If arg4 is not NULL it is a timeout and if it times out ETIMEDOUT * is returned * When the other task does FUTEX_UNLOCK_PI. * *arg1 is set to this task's TID * 0 is returned. * Looking at Documentation/pi-futex.txt and the kernel code, * we find that FUTEX_UNLOCK_PI does:- * If *arg1 is this task's TID, 0 is returned and *arg1 is cleared.. * If *arg1 is this task's TID + FUTEX_WAITERS,. * That task's priority is lowered if necessary to what is was before, * (we don't test this). * The highest priority task waiting for arg1 is wakened, *arg1 is set * to its TID. and its FUTEX_LOCK_PI operation returns 0. * Meanwhile this task's FUTEX_UNLOCK_PI returns 0. * If *arg1 is anything else, -EPERM is returned * Looking at Documentation/pi-futex.txt and the kernel code, * we find that FUTEX_TRYLOCK_PI does:- * If *arg1 is 0, it is set to this task's TID and 0 is returned. * If *arg1 is already this task's TID, -EDEADLK is returned. * If *arg1 is not some other task's TID, -ESRCH is returned. * If *arg1 is some other task's TID, -EWOULDBLOCK is returned. */ f1 = 0; int trylock = futex(&f1, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if (trylock) { if (errno == ENOSYS) { fprintf(stderr, "FUTEX_TRYLOCK_PI not supported in this kernel\n"); /* not fatal */ } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } else { if (f1 != parent_pid) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI set *arg1 to %d instead of %d\n", __LINE__, f1, parent_pid); tkill(child_pid, SIGKILL); exit(1); } /* It isn't plausible that a kernel supports FUTEX_TRYLOCK_PI but not * FUTEX_UNLOCK_PI. If this happens, we catch it below. */ (void)futex(&f1, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); } r = futex(&f1, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_LOCK_PI not supported in this kernel\n"); /* not fatal */ } else { if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_LOCK_PI returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (f1 != parent_pid) { fprintf(stderr, "At line %d FUTEX_LOCK_PI set *arg1 to %d instead of %d\n", __LINE__, f1, parent_pid); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&f1, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_UNLOCK_PI not supported in this kernel\n"); /* not fatal */ } else { if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (f1) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with no waiters did not clear *arg1 (%i)\n", __LINE__, f1); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EPERM)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with no lock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EPERM)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI, 0, (struct timespec *)8, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, (struct timespec *)8, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI, 0, (struct timespec *)upriv, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, (struct timespec *)upriv, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(NULL, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (f1 != parent_pid) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE set *arg1 to %d instead of %d\n", __LINE__, f1, parent_pid); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&f1, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(NULL, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with bad address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } *(int *)(1 + (char *)&f1) = parent_pid; r = futex((int *)(1 + (char *)&f1), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } *(int *)(1 + (char *)&(shmem->f3)) = parent_pid; r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with misaligned address returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } f1 = parent_pid; r = futex(&f1, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (f1) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with no waiters did not clear *arg1 (%i)\n", __LINE__, f1); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EPERM)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with no lock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EPERM)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&f1, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (f1 != parent_pid) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE set *arg1 to %d instead of %d\n", __LINE__, f1, parent_pid); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (r != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (r != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (f1) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI_PRIVATE with no waiters did not clear *arg1 (%i)\n", __LINE__, f1); tkill(child_pid, SIGKILL); exit(1); } } shmem->f3 = 0; r = futex((int *)&(shmem->f3), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_LOCK_PI returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (shmem->f3 != parent_pid) { fprintf(stderr, "At line %d FUTEX_LOCK_PI set *arg1 to %d instead of %d\n", __LINE__, shmem->f3, parent_pid); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&(shmem->f3), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (shmem->f3) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with no waiters did not clear *arg1 (%i)\n", __LINE__, shmem->f3); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EPERM)) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with no lock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EPERM)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex((int *)&(shmem->f3), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (shmem->f3 != parent_pid) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI set *arg1 to %d instead of %d\n", __LINE__, shmem->f3, parent_pid); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (r != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (r != EDEADLK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with deadlock returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EDEADLK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI returned %d instead of 0\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (shmem->f3) { fprintf(stderr, "At line %d FUTEX_UNLOCK_PI with no waiters did not clear *arg1 (%i)\n", __LINE__, shmem->f3); tkill(child_pid, SIGKILL); exit(1); } } f1 = fork(); if (f1 < 0) { fprintf(stderr, "At line %d fork failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else if (f1 == 0) { exit(0); } else { int status; r = waitpid(f1, &status, 0); if (r < 0) { fprintf(stderr, "At line %d waitpid failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } /* At this point f1 is the pid of a process which has just exited. * Unless the system is *very* busy and has already recycled it. * f1 is not the pid of any process. */ shmem->f3 = f1; r = futex(&f1, FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != ESRCH)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with invalid pid returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ESRCH)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != ESRCH)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI with invalid pid returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ESRCH)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { f1 = fork(); if (f1 < 0) { fprintf(stderr, "At line %d fork failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else if (f1 == 0) { exit(0); } else { int status; r = waitpid(f1, &status, 0); if (r < 0) { fprintf(stderr, "At line %d waitpid failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } shmem->f3 = f1; r = futex(&f1, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != ESRCH)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with invalid pid returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ESRCH)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != ESRCH)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI with invalid pid returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ESRCH)); tkill(child_pid, SIGKILL); exit(1); } } f1 = fork(); if (f1 < 0) { fprintf(stderr, "At line %d fork failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else if (f1 == 0) { exit(0); } else { int status; r = waitpid(f1, &status, 0); if (r < 0) { fprintf(stderr, "At line %d waitpid failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != ESRCH)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE with invalid pid returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ESRCH)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { f1 = fork(); if (f1 < 0) { fprintf(stderr, "At line %d fork failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else if (f1 == 0) { exit(0); } else { int status; r = waitpid(f1, &status, 0); if (r < 0) { fprintf(stderr, "At line %d waitpid failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != ESRCH)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE with invalid pid returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ESRCH)); tkill(child_pid, SIGKILL); exit(1); } } f1 = 0; thread_action = 7; wait_for_thread(); r = futex(&f1, FUTEX_LOCK_PI, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&f1, FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 10; int count; for (count = 0; count < 100; ++count) { r = futex(&f1, FUTEX_LOCK_PI, 0, &ONE_sec, NULL, 0); if (r) { if ((errno == ETIMEDOUT) && (count < 99)) { if ((count == 0) && (thread_action == 10)) { fprintf(stderr, "KERNELBUG? FUTEX_LOCK_PI with timer returns ETIMEDOUT immediately\n"); } /* Give the thread some time to do it. */ if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } continue; } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } break; } thread_action = 16; wait_for_thread(); r = futex(&f1, FUTEX_WAKE, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_BITSET, 1, NULL, NULL, 1); if ((r >= 0) || ((errno != EINVAL) && (errno != ENOSYS))) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 19; wait_for_thread(); if (f1) { fprintf(stderr, "At line %d f1 is %d instead of zero after unlocking\n", __LINE__, f1); tkill(child_pid, SIGKILL); exit(1); } thread_action = 8; wait_for_thread(); r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI_PRIVATE should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&f1, FUTEX_TRYLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 11; for (count = 0; count < 100; ++count) { r = futex(&f1, FUTEX_LOCK_PI_PRIVATE, 0, &ONE_sec, NULL, 0); if (r) { if ((errno == ETIMEDOUT) && (count < 99)) { if ((count == 0) && (thread_action == 11)) { fprintf(stderr, "KERNELBUG? FUTEX_LOCK_PI_PRIVATE with timer returns ETIMEDOUT immediately\n"); } /* Give the thread some time to do it. */ if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } continue; } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } break; } thread_action = 17; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_PRIVATE on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_BITSET_PRIVATE, 1, NULL, NULL, 1); if ((r >= 0) || ((errno != EINVAL) && (errno != ENOSYS))) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 19; wait_for_thread(); if (f1) { fprintf(stderr, "At line %d f1 is %d instead of zero after unlocking\n", __LINE__, f1); tkill(child_pid, SIGKILL); exit(1); } shmem->f3 = 0; thread_action = 9; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&(shmem->f3), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 12; for (count = 0; count < 100; ++count) { r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, &ONE_sec, NULL, 0); if (r) { if ((errno == ETIMEDOUT) && (count < 99)) { /* Give the thread some time to do it. */ if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } continue; } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } break; } thread_action = 18; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 1, NULL, NULL, 1); if ((r >= 0) || ((errno != EINVAL) && (errno != ENOSYS))) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 19; wait_for_thread(); if (shmem->f3) { fprintf(stderr, "At line %d shmem->f3 is %d instead of zero after unlocking\n", __LINE__, f1); tkill(child_pid, SIGKILL); exit(1); } shmem->child_action = 9; wait_for_child(); r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, &TEN_ms, NULL, 0); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_LOCK_PI should time out returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } if (trylock) { r = futex(&(shmem->f3), FUTEX_TRYLOCK_PI, 0, NULL, NULL, 0); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_TRYLOCK_PI returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 12; for (count = 0; count < 100; ++count) { r = futex(&(shmem->f3), FUTEX_LOCK_PI, 0, &ONE_sec, NULL, 0); if (r) { if ((errno == ETIMEDOUT) && (count < 99)) { /* Give the child some time to do it. */ if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } continue; } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } break; } shmem->child_action = 18; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE, 1, NULL, NULL, 0); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 1, NULL, NULL, 1); if ((r >= 0) || ((errno != EINVAL) && (errno != ENOSYS))) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET on pi-locked returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_UNLOCK_PI, 0, NULL, NULL, 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } shmem->child_action = 19; wait_for_child(); if (shmem->f3) { fprintf(stderr, "At line %d shmem->f3 is %d instead of zero after unlocking\n", __LINE__, shmem->f3); tkill(child_pid, SIGKILL); exit(1); } } } /* FUTEX_WAIT_BITSET and FUTEX_WAKE_BITSET are also not documented. * Looking at the kernel code, * we find that FUTEX_WAIT_BITSET does:- * If arg6 is zero, -EINVAL is returned. * If *arg1 is not equal to arg3, -EWOULDBLOCK is returned. * If arg4 is not NULL it is pointer to a timeout: if the timeout expires * before we are woken as below, -ETIMEDOUT is returned. * Otherwise wait for some other process to do FUTEX_WAKE_BITSET * on arg1 with its arg6 having some bit(s) set which were also * set in our arg6. If that happens, we return 0. * we find that FUTEX_WAIT_BITSET does:- * If arg6 is zero, -EINVAL is returned. * If some process holds a PI lock on arg1, -EINVAL is returned * (this is tested under FUTEX_LOCK_PI above). * Otherwise, wake up to arg3 processes which were waiting in * FUTEX_WAIT_BITSET for the same arg1 with their arg6 having some * bit(s) set which were also set in our arg6, and return the number * of processes awakened. * Note all this is exactly like FUTEX_WAIT and FUTEX_WAKE except for * the arg6 masking, and in fact these are implemented by the kernel as * if they were FUTEX_WAIT_BITSET and FUTEX_WAKE_BITSET with arg6 set to * all ones: thus it is possible for FUTEX_WAKE_BITSET to wake a process * which is sleeping in FUTEX_WAIT or FUTEX_WAKE to wake a process which * is sleeping in FUTEX_WAIT_BITSET. */ f1 = 0; r = futex(&f1, FUTEX_WAIT_BITSET, 0, NULL, NULL, 0); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_WAIT_BITSET not supported in this kernel\n"); /* not fatal */ } else { if (r >= 0) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %d instead of EINVAL\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } else if (errno != EINVAL) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_BITSET, 0, NULL, NULL, 0); if ((r < 0) && (errno == ENOSYS)) { fprintf(stderr, "FUTEX_WAKE_BITSET not supported in this kernel\n"); /* not fatal */ } else { if (r >= 0) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d instead of EINVAL\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } else if (errno != EINVAL) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 0); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_WAIT_BITSET_PRIVATE, 0, NULL, NULL, 1 << 1); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 2); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAIT_BITSET_PRIVATE, 0, NULL, NULL, 1 << 3); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 4); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAIT_BITSET_PRIVATE, 0, NULL, NULL, 1 << 5); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 6); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAIT_BITSET_PRIVATE, 0, NULL, NULL, 1 << 7); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } shmem->f3 = 0; r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 8); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 8); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET, 1, NULL, NULL, 1 << 9); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, 1, NULL, NULL, 1 << 10); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 2, NULL, NULL, 1 << 11); if ((r >= 0) || (errno != EWOULDBLOCK)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EWOULDBLOCK)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET, 0, (struct timespec *)8, NULL, 1 << 12); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, 0, (struct timespec *)8, NULL, 1 << 13); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, (struct timespec *)8, NULL, 1 << 14); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET, 0, (struct timespec *)upriv, NULL, 1 << 15); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, 0, (struct timespec *)upriv, NULL, 1 << 16); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, (struct timespec *)upriv, NULL, 1 << 17); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET, 0, &TEN_ms, NULL, 1 << 19); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, 0, &TEN_ms, NULL, 1 << 20); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, &TEN_ms, NULL, 1 << 21); if ((r >= 0) || (errno != ETIMEDOUT)) { fprintf(stderr, "At line %d FUTEX_WAIT_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(ETIMEDOUT)); tkill(child_pid, SIGKILL); exit(1); } thread_action = 1; r = futex(&f1, FUTEX_WAIT_BITSET, 0, &ONE_sec, &f2, 1 << 22); if (r) { if (errno == ETIMEDOUT) { int ta = thread_action; /* Try without timer, may wait forever. */ r = futex(&f1, FUTEX_WAIT_BITSET, 0, NULL, &f2, 1 << 22); if (ta == 1) { fprintf(stderr, "KERNELBUG? FUTEX_WAIT_BITSET with timer returns ETIMEDOUT immediately\n"); } if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 1; r = futex(&f1, FUTEX_WAIT_BITSET, 0, &ONE_sec, NULL, 1 << 23); if (r) { if (errno == ETIMEDOUT) { r = futex(&f1, FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 23); } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 1; r = futex(&f1, FUTEX_WAIT_BITSET, 0, &ONE_sec, (int *)8, 1 << 24); if (r) { if ((errno == ETIMEDOUT) && (thread_action == 1)) { r = futex(&f1, FUTEX_WAIT_BITSET, 0, NULL, (int *)8, 1 << 24); } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 1; r = futex(&f1, FUTEX_WAIT_BITSET, 0, &ONE_sec, (int *)upriv, 1 << 25); if (r) { if (errno == ETIMEDOUT) { r = futex(&f1, FUTEX_WAIT_BITSET, 0, NULL, (int *)upriv, 1 << 25); } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 2; r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, 0, &ONE_sec, NULL, 1 << 26); if (r) { if (errno == ETIMEDOUT) { if (thread_action == 2) { fprintf(stderr, "KERNELBUG? FUTEX_WAIT_BITSET_PRIVATE with timer returns ETIMEDOUT immediately\n"); } r = futex(&f1, FUTEX_WAIT_BITSET_PRIVATE, 0, NULL, NULL, 1 << 26); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 3; r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, &ONE_sec, NULL, 1 << 27); if (r) { if (errno == ETIMEDOUT) { r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 27); } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 3; r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, &ONE_sec, NULL, 1 << 28); if (r) { if (errno == ETIMEDOUT) { /* Give the thread some time to do it. */ r = futex(&(shmem->f3), FUTEX_WAIT_BITSET, 0, NULL, NULL, 1 << 28); } else { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } } r = futex(NULL, FUTEX_WAKE_BITSET, 0, NULL, NULL, 1 << 29); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex(NULL, FUTEX_WAKE_BITSET_PRIVATE, 0, NULL, NULL, 1 << 30); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAKE_BITSET, 0, NULL, NULL, 1 << 31); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)8, FUTEX_WAKE_BITSET_PRIVATE, 0, NULL, NULL, 3 << 0); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAKE_BITSET, 0, NULL, NULL, 3 << 1); if ((r >= 0) || (errno != EFAULT)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EFAULT)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)upriv, FUTEX_WAKE_BITSET_PRIVATE, 0, NULL, NULL, 3 << 2); if (r) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAKE_BITSET, 0, NULL, NULL, 3 << 3); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&f1), FUTEX_WAKE_BITSET_PRIVATE, 0, NULL, NULL, 3 << 4); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_WAKE_BITSET, 0, NULL, NULL, 3 << 5); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(1 + (char *)&(shmem->f3)), FUTEX_WAKE_BITSET_PRIVATE, 0, NULL, NULL, 3 << 6); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_WAKE_BITSET, 0, NULL, NULL, 3 << 5); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex((int *)(4094 + (char *)&(shmem->f3)), FUTEX_WAKE_BITSET_PRIVATE, 0, NULL, NULL, 3 << 6); if ((r >= 0) || (errno != EINVAL)) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %s instead of %s\n", __LINE__, strerror(errno), strerror(EINVAL)); tkill(child_pid, SIGKILL); exit(1); } r = futex(&f1, FUTEX_WAKE_BITSET, 3, (struct timespec *)upriv, (int *)upriv, 3 << 7); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when no processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_BITSET_PRIVATE, 3, (struct timespec *)upriv, (int *)upriv, 3 << 8); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %d when no processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, (struct timespec *)upriv, (int *)upriv, 3 << 9); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when no processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 4; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_BITSET, 3, (struct timespec *)upriv, (int *)upriv, 3 << 10); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 5; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_BITSET_PRIVATE, 3, (struct timespec *)upriv, (int *)upriv, 3 << 11); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, (struct timespec *)upriv, (int *)upriv, 3 << 12); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, (struct timespec *)upriv, (int *)upriv, 3 << 13); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when 1 process to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, (struct timespec *)upriv, (int *)upriv, 3 << 14); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when 2 processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 6; wait_for_thread(); shmem->child_action = 6; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 1, (struct timespec *)upriv, (int *)upriv, 3 << 15); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 0, (struct timespec *)upriv, (int *)upriv, 3 << 16); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 13; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_BITSET, 3, NULL, NULL, 0xFFFFFFFC); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when waking no process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_BITSET, 3, NULL, NULL, 0x6); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 14; wait_for_thread(); r = futex(&f1, FUTEX_WAKE_BITSET_PRIVATE, 3, NULL, NULL, 0xFFFFFFC0); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %d when waking no process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&f1, FUTEX_WAKE_BITSET_PRIVATE, 3, NULL, NULL, 0x1F); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET_PRIVATE returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 15; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0xFFFFFC00); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when waking no process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0xFFFFFD00); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 15; wait_for_thread(); shmem->child_action = 15; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0xFFFFFC00); if (r) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when waking no process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0xFFFFFD00); if (r != 2) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when 2 processes to wake\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } thread_action = 15; wait_for_thread(); shmem->child_action = 16; wait_for_child(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0x300); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d when only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (shmem->child_action) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET woke wrong process\n", __LINE__); tkill(child_pid, SIGKILL); exit(1); } thread_action = 15; wait_for_thread(); r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0x3000); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } if (nanosleep(&TEN_ms, NULL)) { fprintf(stderr, "At line %d nanosleep failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } if (shmem->child_action != 17) { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET woke wrong process\n", __LINE__); tkill(child_pid, SIGKILL); exit(1); } r = futex(&(shmem->f3), FUTEX_WAKE_BITSET, 3, NULL, NULL, 0x300); if (r != 1) { if (r < 0) { fprintf(stderr, "At line %d futex failed %s\n", __LINE__, strerror(errno)); tkill(child_pid, SIGKILL); exit(1); } else { fprintf(stderr, "At line %d FUTEX_WAKE_BITSET returned %d only waking one process\n", __LINE__, r); tkill(child_pid, SIGKILL); exit(1); } } } } fprintf(stdout, "Test succeeded\n"); exit(0); }