2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1994-2021, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure, Markus Armbruster
6 * Empire is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * See files README, COPYING and CREDITS in the root of the source
22 * tree for related information and legal notices. It is expected
23 * that future projects/authors will amend these files as needed.
27 * sig.c: Wait for signals
29 * Known contributors to this file:
30 * Markus Armbruster, 2006-2020
43 * Awaited signal numbers, terminated with 0.
45 static int *LwpAwaitedSig;
48 * Pending awaited signals.
49 * Access only with signals blocked!
51 static volatile int *LwpPendingSig;
54 * Is there anything in LwpPendingSig[]?
56 static volatile sig_atomic_t LwpSigCheck;
58 /* The thread waiting for signals in lwpSigWait() */
59 static struct lwpProc *LwpSigWaiter;
61 static void lwpHandleAwaitedSig(int);
64 * Initialize waiting for signals in @sig[].
65 * @sig[] contains signal numbers, terminated with 0. It must have
66 * static storage duration.
69 lwpInitSigWait(int sig[])
77 act.sa_handler = lwpHandleAwaitedSig;
78 sigemptyset(&act.sa_mask);
79 for (i = 0; sig[i]; i++)
80 sigaddset(&act.sa_mask, sig[i]);
82 LwpPendingSig = calloc(i, sizeof(*LwpPendingSig));
84 for (i = 0; sig[i]; i++)
85 sigaction(sig[i], &act, NULL);
89 * Signal handler for awaited signals.
90 * Set @LwpPendingSig[] for @sig, and set @LwpSigCheck.
91 * Not reentrant; lwpInitSigWait() guards.
94 lwpHandleAwaitedSig(int sig)
98 for (i = 0; LwpAwaitedSig[i]; i++) {
99 if (sig == LwpAwaitedSig[i])
100 LwpPendingSig[i] = 1;
106 * Test whether an awaited signal is pending.
107 * If yes, remove that signal from the set of pending signals, and
119 for (i = 0; LwpAwaitedSig[i]; i++)
120 sigaddset(&set, LwpAwaitedSig[i]);
121 sigprocmask(SIG_BLOCK, &set, &save);
123 for (i = 0; LwpAwaitedSig[i]; i++) {
124 if (LwpPendingSig[i]) {
125 lwpStatus(LwpCurrent, "Got awaited signal %d", LwpPendingSig[i]);
126 ret = LwpAwaitedSig[i];
127 LwpPendingSig[i] = 0;
131 for (; LwpAwaitedSig[i] && LwpPendingSig[i]; i++) ;
132 if (!LwpPendingSig[i])
135 sigprocmask(SIG_SETMASK, &save, NULL);
140 * Wait until one of the signals passed to lwpInitSigWait() arrives.
141 * Return its signal number.
142 * If another thread is already waiting for signals, return -1
156 lwpStatus(LwpCurrent, "Waiting for signals");
157 LwpSigWaiter = LwpCurrent;
164 * Wake up the thread awaiting signals if one arrived.
165 * To be called from lwpReschedule().
170 if (LwpSigWaiter && LwpSigCheck) {
171 lwpReady(LwpSigWaiter);