Pthread sleep
authorTomas Mudrunka <tomas@mudrunka.cz>
Fri, 2 Jul 2021 13:37:20 +0000 (15:37 +0200)
committerTomas Mudrunka <tomas@mudrunka.cz>
Fri, 2 Jul 2021 13:37:20 +0000 (15:37 +0200)
c/pthread_extra/Makefile
c/pthread_extra/pthread_extra.h
c/pthread_extra/pthread_sleep.c [new file with mode: 0644]

index 1197cca9d85dcaa98a655dba50a5528a4fa8feb4..35fac9c4c527ce25da05af4508305cde9bb39b19 100644 (file)
@@ -11,7 +11,7 @@ CXXFLAGS+=$(COPT) $(CERR) $(CDEF) -std=c++11 $(CLIB)
 LDFLAGS+=$(COPT) $(LIB)\r
 \r
 BIN=test\r
-OBJ=pthread_user_data.o pthread_pause.o pthread_multi.o pthread_msgqueue.o test.o\r
+OBJ=pthread_user_data.o pthread_sleep.o pthread_pause.o pthread_multi.o pthread_msgqueue.o test.o\r
 \r
 all: $(BIN)\r
 $(BIN): $(OBJ)\r
index 4df45d97eb6b29d3fed4398035a31756e4cf5fc0..56c440b5f03751c8c0792a3412b8308b8a8d7a9c 100644 (file)
@@ -56,6 +56,12 @@ int pthread_unpause_all();
 int pthread_pause_reschedule(pthread_t thread);
 int pthread_extra_yield();
 
+// Pause compatible sleeps
+
+void pthread_nanosleep(struct timespec t);
+void pthread_nsleep(time_t s, long ns);
+void pthread_sleep(time_t s);
+
 // Message queues
 
 //Flags
diff --git a/c/pthread_extra/pthread_sleep.c b/c/pthread_extra/pthread_sleep.c
new file mode 100644 (file)
index 0000000..12712c1
--- /dev/null
@@ -0,0 +1,49 @@
+#include <pthread_extra.h>
+#include <time.h>
+#include <errno.h>
+
+#define NSEC_PER_SEC (1000*1000*1000)
+// timespec_normalise() from https://github.com/solemnwarning/timespec/
+struct timespec timespec_normalise(struct timespec ts)
+{
+       while(ts.tv_nsec >= NSEC_PER_SEC) {
+               ++(ts.tv_sec); ts.tv_nsec -= NSEC_PER_SEC;
+       }
+       while(ts.tv_nsec <= -NSEC_PER_SEC) {
+               --(ts.tv_sec); ts.tv_nsec += NSEC_PER_SEC;
+       }
+       if(ts.tv_nsec < 0) { // Negative nanoseconds isn't valid according to POSIX.
+               --(ts.tv_sec); ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec);
+       }
+       return ts;
+}
+
+void pthread_nanosleep(struct timespec t) {
+       //Sleep calls on Linux get interrupted by signals, causing premature wake
+       //Pthread (un)pause is built using signals
+       //Therefore we need self-restarting sleep implementation
+       //IO timeouts are restarted by SA_RESTART, but sleeps do need explicit restart
+       //We also need to sleep using absolute time, because relative time is paused
+       //You should use this in any thread that gets (un)paused
+
+       struct timespec wake;
+       clock_gettime(CLOCK_MONOTONIC, &wake);
+
+       t = timespec_normalise(t);
+       wake.tv_sec += t.tv_sec;
+       wake.tv_nsec += t.tv_nsec;
+       wake = timespec_normalise(wake);
+
+       while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake, NULL)) if(errno!=EINTR) break;
+       return;
+}
+void pthread_nsleep(time_t s, long ns) {
+       struct timespec t;
+       t.tv_sec = s;
+       t.tv_nsec = ns;
+       pthread_nanosleep(t);
+}
+
+void pthread_sleep(time_t s) {
+       pthread_nsleep(s, 0);
+}
This page took 0.168701 seconds and 4 git commands to generate.