Get rid of uninitialized actions and just use non-atomic writes instead
[c11tester.git] / sleeps.cc
1 #include <time.h>
2 #include <unistd.h>
3 #include <sys/param.h>
4
5 #include "action.h"
6 #include "model.h"
7
8 extern "C" {
9 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
10 }
11
12 unsigned int sleep(unsigned int seconds)
13 {
14         /* https://code.woboq.org/userspace/glibc/sysdeps/posix/sleep.c.html */
15         const unsigned int max
16                 = (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1);
17
18         struct timespec ts = { 0, 0 };
19         do {
20                 if (sizeof (ts.tv_sec) <= sizeof (seconds)) {
21                         /* Since SECONDS is unsigned assigning the value to .tv_sec can
22                            overflow it.  In this case we have to wait in steps.  */
23                         ts.tv_sec += MIN (seconds, max);
24                         seconds -= (unsigned int) ts.tv_sec;
25                 } else {
26                         ts.tv_sec = (time_t) seconds;
27                         seconds = 0;
28                 }
29
30                 nanosleep(&ts, &ts);
31         } while (seconds > 0);
32
33         return 0;
34 }
35
36 int usleep(useconds_t useconds)
37 {
38         /* https://code.woboq.org/userspace/glibc/sysdeps/posix/usleep.c.html */
39         struct timespec ts = {
40                 .tv_sec = (long int) (useconds / 1000000),
41                 .tv_nsec = (long int) (useconds % 1000000) * 1000l,
42         };
43         return nanosleep(&ts, NULL);
44 }
45
46 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
47 {
48         if (model) {
49                 uint64_t time = rqtp->tv_sec * 1000000000 + rqtp->tv_nsec;
50                 struct timespec currtime;
51                 clock_gettime(CLOCK_MONOTONIC, &currtime);
52                 uint64_t lcurrtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
53                 model->switch_to_master(new ModelAction(THREAD_SLEEP, std::memory_order_seq_cst, time, lcurrtime));
54                 if (rmtp != NULL) {
55                         clock_gettime(CLOCK_MONOTONIC, &currtime);
56                         uint64_t lendtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
57                         uint64_t elapsed = lendtime - lcurrtime;
58                         rmtp->tv_sec = elapsed / 1000000000;
59                         rmtp->tv_nsec = elapsed - rmtp->tv_sec * 1000000000;
60                 }
61         }
62
63         return 0;
64 }