X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=blobdiff_plain;f=sleeps.cc;h=2b70582ddb776ec31ea2087a9d6e9241cf348694;hp=0528374b3ac4c2a053fd756413dcd180e8b48430;hb=25d73096cfc14c655f94b01bb235cc5efd1d5696;hpb=aa653d6ec854b70b92b9cbb0fe452fbb0e300979 diff --git a/sleeps.cc b/sleeps.cc index 0528374b..2b70582d 100644 --- a/sleeps.cc +++ b/sleeps.cc @@ -1,26 +1,64 @@ #include #include +#include #include "action.h" #include "model.h" -unsigned int __sleep (unsigned int seconds) +extern "C" { +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); +} + +unsigned int sleep(unsigned int seconds) { - model->switch_to_master( - new ModelAction(NOOP, std::memory_order_seq_cst, NULL) - ); + /* https://code.woboq.org/userspace/glibc/sysdeps/posix/sleep.c.html */ + const unsigned int max + = (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1); + + struct timespec ts = { 0, 0 }; + do { + if (sizeof (ts.tv_sec) <= sizeof (seconds)) { + /* Since SECONDS is unsigned assigning the value to .tv_sec can + overflow it. In this case we have to wait in steps. */ + ts.tv_sec += MIN (seconds, max); + seconds -= (unsigned int) ts.tv_sec; + } else { + ts.tv_sec = (time_t) seconds; + seconds = 0; + } + + nanosleep(&ts, &ts); + } while (seconds > 0); + return 0; } -unsigned int sleep(unsigned int seconds) +int usleep(useconds_t useconds) { - return __sleep(seconds); + /* https://code.woboq.org/userspace/glibc/sysdeps/posix/usleep.c.html */ + struct timespec ts = { + .tv_sec = (long int) (useconds / 1000000), + .tv_nsec = (long int) (useconds % 1000000) * 1000l, + }; + return nanosleep(&ts, NULL); } -int usleep (useconds_t useconds) +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { - model->switch_to_master( - new ModelAction(NOOP, std::memory_order_seq_cst, NULL) - ); + if (model) { + uint64_t time = rqtp->tv_sec * 1000000000 + rqtp->tv_nsec; + struct timespec currtime; + clock_gettime(CLOCK_MONOTONIC, &currtime); + uint64_t lcurrtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec; + model->switch_thread(new ModelAction(THREAD_SLEEP, std::memory_order_seq_cst, time, lcurrtime)); + if (rmtp != NULL) { + clock_gettime(CLOCK_MONOTONIC, &currtime); + uint64_t lendtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec; + uint64_t elapsed = lendtime - lcurrtime; + rmtp->tv_sec = elapsed / 1000000000; + rmtp->tv_nsec = elapsed - rmtp->tv_sec * 1000000000; + } + } + return 0; }