2 ** GNU Pth - The GNU Portable Threads
3 ** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
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/.
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.
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.
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>.
23 ** pth_cancel.c: Pth thread cancellation
25 /* ``Study it forever and you'll still wonder.
26 Fly it once and you'll know.''
30 /* set cancellation state */
31 void pth_cancel_state(int newstate, int *oldstate)
34 *oldstate = pth_current->cancelstate;
36 pth_current->cancelstate = newstate;
40 /* enter a cancellation point */
41 void pth_cancel_point(void)
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);
53 /* cancel a thread (the friendly way) */
54 int pth_cancel(pth_t thread)
59 return pth_error(FALSE, EINVAL);
61 /* the current thread cannot be cancelled */
62 if (thread == pth_current)
63 return pth_error(FALSE, EINVAL);
65 /* the thread has to be at least still alive */
66 if (thread->state == PTH_STATE_DEAD)
67 return pth_error(FALSE, EPERM);
69 /* now mark the thread as cancelled */
70 thread->cancelreq = TRUE;
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) {
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;
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);
89 /* execute cleanups */
90 pth_thread_cleanup(thread);
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);
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);
107 /* abort a thread (the cruel way) */
108 int pth_abort(pth_t thread)
111 return pth_error(FALSE, EINVAL);
113 /* the current thread cannot be aborted */
114 if (thread == pth_current)
115 return pth_error(FALSE, EINVAL);
117 if (thread->state == PTH_STATE_DEAD && thread->joinable) {
118 /* if thread is already terminated, just join it */
119 if (!pth_join(thread, NULL))
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))