.
[kopensolaris-gnu/glibc.git] / linuxthreads / restart.h
1 /* Linuxthreads - a simple clone()-based implementation of Posix        */
2 /* threads for Linux.                                                   */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4 /*                                                                      */
5 /* This program is free software; you can redistribute it and/or        */
6 /* modify it under the terms of the GNU Library General Public License  */
7 /* as published by the Free Software Foundation; either version 2       */
8 /* of the License, or (at your option) any later version.               */
9 /*                                                                      */
10 /* This program is distributed in the hope that it will be useful,      */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
13 /* GNU Library General Public License for more details.                 */
14
15 #include <signal.h>
16
17 /* Primitives for controlling thread execution */
18
19 static inline void restart(pthread_descr th)
20 {
21   kill(th->p_pid, __pthread_sig_restart);
22 }
23
24 static inline void suspend(pthread_descr self)
25 {
26   sigset_t mask;
27
28   sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
29   sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
30   do {
31     self->p_signal = 0;
32     sigsuspend(&mask);                   /* Wait for signal */
33   } while (self->p_signal !=__pthread_sig_restart );
34 }
35
36 static inline void suspend_with_cancellation(pthread_descr self)
37 {
38   sigset_t mask;
39   sigjmp_buf jmpbuf;
40
41   sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
42   sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
43   /* No need to save the signal mask, we'll restore it ourselves */
44   if (sigsetjmp(jmpbuf, 0) == 0) {
45     self->p_cancel_jmp = &jmpbuf;
46     if (! (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE)) {
47       do {
48         self->p_signal = 0;
49         sigsuspend(&mask);               /* Wait for a signal */
50       } while (self->p_signal != __pthread_sig_restart);
51     }
52     self->p_cancel_jmp = NULL;
53   } else {
54     sigaddset(&mask, __pthread_sig_restart); /* Reblock the restart signal */
55     sigprocmask(SIG_SETMASK, &mask, NULL);
56   }
57 }