X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=blobdiff_plain;f=sleeps.cc;h=2b70582ddb776ec31ea2087a9d6e9241cf348694;hp=0b4d32f65673285a75951d107aa2007e2c0d4356;hb=25d73096cfc14c655f94b01bb235cc5efd1d5696;hpb=74ac6c2fab9f394a9992431079ed2dbede1144c0 diff --git a/sleeps.cc b/sleeps.cc index 0b4d32f6..2b70582d 100644 --- a/sleeps.cc +++ b/sleeps.cc @@ -1,5 +1,6 @@ #include #include +#include #include "action.h" #include "model.h" @@ -8,21 +9,33 @@ 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) - ); - return 0; -} - unsigned int sleep(unsigned int seconds) { - return __sleep(seconds); + /* 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; } -int usleep (useconds_t useconds) +int usleep(useconds_t useconds) { + /* 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, @@ -30,13 +43,14 @@ int usleep (useconds_t useconds) return nanosleep(&ts, NULL); } -int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ 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_to_master(new ModelAction(THREAD_SLEEP, std::memory_order_seq_cst, time, lcurrtime)); + 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;