resetting manifest requested domain to floor
[platform/upstream/pth.git] / pth_cancel.c
1 /*
2 **  GNU Pth - The GNU Portable Threads
3 **  Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
4 **
5 **  This file is part of GNU Pth, a non-preemptive thread scheduling
6 **  library which can be found at http://www.gnu.org/software/pth/.
7 **
8 **  This library is free software; you can redistribute it and/or
9 **  modify it under the terms of the GNU Lesser General Public
10 **  License as published by the Free Software Foundation; either
11 **  version 2.1 of the License, or (at your option) any later version.
12 **
13 **  This library is distributed in the hope that it will be useful,
14 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 **  Lesser General Public License for more details.
17 **
18 **  You should have received a copy of the GNU Lesser General Public
19 **  License along with this library; if not, write to the Free Software
20 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 **  USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
22 **
23 **  pth_cancel.c: Pth thread cancellation
24 */
25                              /* ``Study it forever and you'll still wonder.
26                                   Fly it once and you'll know.''
27                                                        -- Henry Spencer */
28 #include "pth_p.h"
29
30 /* set cancellation state */
31 void pth_cancel_state(int newstate, int *oldstate)
32 {
33     if (oldstate != NULL)
34         *oldstate = pth_current->cancelstate;
35     if (newstate != 0)
36         pth_current->cancelstate = newstate;
37     return;
38 }
39
40 /* enter a cancellation point */
41 void pth_cancel_point(void)
42 {
43     if (   pth_current->cancelreq == TRUE
44         && pth_current->cancelstate & PTH_CANCEL_ENABLE) {
45         /* avoid looping if cleanup handlers contain cancellation points */
46         pth_current->cancelreq = FALSE;
47         pth_debug2("pth_cancel_point: terminating cancelled thread \"%s\"", pth_current->name);
48         pth_exit(PTH_CANCELED);
49     }
50     return;
51 }
52
53 /* cancel a thread (the friendly way) */
54 int pth_cancel(pth_t thread)
55 {
56     pth_pqueue_t *q;
57
58     if (thread == NULL)
59         return pth_error(FALSE, EINVAL);
60
61     /* the current thread cannot be cancelled */
62     if (thread == pth_current)
63         return pth_error(FALSE, EINVAL);
64
65     /* the thread has to be at least still alive */
66     if (thread->state == PTH_STATE_DEAD)
67         return pth_error(FALSE, EPERM);
68
69     /* now mark the thread as cancelled */
70     thread->cancelreq = TRUE;
71
72     /* when cancellation is enabled in async mode we cancel the thread immediately */
73     if (   thread->cancelstate & PTH_CANCEL_ENABLE
74         && thread->cancelstate & PTH_CANCEL_ASYNCHRONOUS) {
75
76         /* remove thread from its queue */
77         switch (thread->state) {
78             case PTH_STATE_NEW:     q = &pth_NQ; break;
79             case PTH_STATE_READY:   q = &pth_RQ; break;
80             case PTH_STATE_WAITING: q = &pth_WQ; break;
81             default:                q = NULL;
82         }
83         if (q == NULL)
84             return pth_error(FALSE, ESRCH);
85         if (!pth_pqueue_contains(q, thread))
86             return pth_error(FALSE, ESRCH);
87         pth_pqueue_delete(q, thread);
88
89         /* execute cleanups */
90         pth_thread_cleanup(thread);
91
92         /* and now either kick it out or move it to dead queue */
93         if (!thread->joinable) {
94             pth_debug2("pth_cancel: kicking out cancelled thread \"%s\" immediately", thread->name);
95             pth_tcb_free(thread);
96         }
97         else {
98             pth_debug2("pth_cancel: moving cancelled thread \"%s\" to dead queue", thread->name);
99             thread->join_arg = PTH_CANCELED;
100             thread->state = PTH_STATE_DEAD;
101             pth_pqueue_insert(&pth_DQ, PTH_PRIO_STD, thread);
102         }
103     }
104     return TRUE;
105 }
106
107 /* abort a thread (the cruel way) */
108 int pth_abort(pth_t thread)
109 {
110     if (thread == NULL)
111         return pth_error(FALSE, EINVAL);
112
113     /* the current thread cannot be aborted */
114     if (thread == pth_current)
115         return pth_error(FALSE, EINVAL);
116
117     if (thread->state == PTH_STATE_DEAD && thread->joinable) {
118         /* if thread is already terminated, just join it */
119         if (!pth_join(thread, NULL))
120             return FALSE;
121     }
122     else {
123         /* else force it to be detached and cancel it asynchronously */
124         thread->joinable = FALSE;
125         thread->cancelstate = (PTH_CANCEL_ENABLE|PTH_CANCEL_ASYNCHRONOUS);
126         if (!pth_cancel(thread))
127             return FALSE;
128     }
129     return TRUE;
130 }
131