futex_timeout.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #include <errno.h>
  2. #include <linux/futex.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <sys/syscall.h>
  6. #include <sys/time.h>
  7. #include <unistd.h>
  8. #define SLEEP_SEC 1
  9. int main(int argc, const char** argv) {
  10. int myfutex = 0;
  11. int ret;
  12. int futex_errno = 0;
  13. struct timespec t = {.tv_sec = SLEEP_SEC, .tv_nsec = 0};
  14. struct timeval tv1 = { 0 };
  15. struct timeval tv2 = { 0 };
  16. printf("invoke futex syscall with a %d second timeout\n", SLEEP_SEC);
  17. if (gettimeofday(&tv1, NULL)) {
  18. printf("Cannot get time 1: %m\n");
  19. return 1;
  20. }
  21. ret = syscall(SYS_futex, &myfutex, FUTEX_WAIT, 0, &t, NULL, 0);
  22. futex_errno = errno;
  23. if (gettimeofday(&tv2, NULL)) {
  24. printf("Cannot get time 2: %m\n");
  25. return 1;
  26. }
  27. if (ret != -1 || futex_errno != ETIMEDOUT) {
  28. printf("futex syscall returned: %d with errno: %d (%s)\n", ret, futex_errno, strerror(futex_errno));
  29. return 1;
  30. }
  31. long long diff = (tv2.tv_sec - tv1.tv_sec) * 1000000ll;
  32. diff += tv2.tv_usec - tv1.tv_usec;
  33. if (diff < 0) {
  34. printf("Just moved back in time (%lld), better call Ghostbusters!\n", diff);
  35. return 1;
  36. }
  37. if (diff < 1000000ll * SLEEP_SEC) {
  38. printf("Slept for %lld microseconds, which is less than %d seconds\n", diff, SLEEP_SEC);
  39. return 1;
  40. }
  41. puts("futex correctly timed out");
  42. return 0;
  43. }