1 /*
2  * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3  * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
4  */
5 #include "cmogstored.h"
6 
7 /*
8  * we block signals in pool threads, only the main thread receives signals
9  */
10 
11 static sigset_t fullset;
12 sigset_t mog_emptyset;
13 
sig_init(void)14 __attribute__((constructor)) static void sig_init(void)
15 {
16 	CHECK(int, 0, sigfillset(&fullset));
17 	CHECK(int, 0, sigemptyset(&mog_emptyset));
18 }
19 
mog_intr_disable(void)20 void mog_intr_disable(void)
21 {
22 	CHECK(int, 0, pthread_sigmask(SIG_SETMASK, &fullset, NULL));
23 }
24 
mog_intr_enable(void)25 void mog_intr_enable(void)
26 {
27 	CHECK(int, 0, pthread_sigmask(SIG_SETMASK, &mog_emptyset, NULL));
28 }
29 
sleeper(struct timespec * tsp,const sigset_t * sigmask)30 static int sleeper(struct timespec *tsp, const sigset_t *sigmask)
31 {
32 	int err = 0;
33 
34 	/*
35 	 * pselect is a cancellation point,
36 	 * ppoll is not POSIX and is only a cancellation point on glibc.
37 	 */
38 	if (pselect(0, NULL, NULL, NULL, tsp, sigmask) < 0) {
39 		err = errno;
40 		assert((err == EINTR || err == ENOMEM) &&
41 		       "BUG in pselect usage");
42 	}
43 	return err;
44 }
45 
46 /* thread-safe, interruptible sleep, negative seconds -> sleep forever */
mog_sleep(long seconds)47 int mog_sleep(long seconds)
48 {
49 	struct timespec ts;
50 	struct timespec *tsp;
51 
52 	if (seconds < 0) {
53 		tsp = NULL;
54 	} else {
55 		ts.tv_sec = seconds;
56 		ts.tv_nsec = 0;
57 		tsp = &ts;
58 	}
59 
60 	return sleeper(tsp, &mog_emptyset);
61 }
62