1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
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. */
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. */
15 /* Thread cancellation */
19 #include "internals.h"
23 int pthread_setcancelstate(int state
, int * oldstate
)
25 pthread_descr self
= thread_self();
26 if (state
< PTHREAD_CANCEL_ENABLE
|| state
> PTHREAD_CANCEL_DISABLE
)
28 if (oldstate
!= NULL
) *oldstate
= THREAD_GETMEM(self
, p_cancelstate
);
29 THREAD_SETMEM(self
, p_cancelstate
, state
);
30 if (THREAD_GETMEM(self
, p_canceled
) &&
31 THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
&&
32 THREAD_GETMEM(self
, p_canceltype
) == PTHREAD_CANCEL_ASYNCHRONOUS
)
33 pthread_exit(PTHREAD_CANCELED
);
37 int pthread_setcanceltype(int type
, int * oldtype
)
39 pthread_descr self
= thread_self();
40 if (type
< PTHREAD_CANCEL_DEFERRED
|| type
> PTHREAD_CANCEL_ASYNCHRONOUS
)
42 if (oldtype
!= NULL
) *oldtype
= THREAD_GETMEM(self
, p_canceltype
);
43 THREAD_SETMEM(self
, p_canceltype
, type
);
44 if (THREAD_GETMEM(self
, p_canceled
) &&
45 THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
&&
46 THREAD_GETMEM(self
, p_canceltype
) == PTHREAD_CANCEL_ASYNCHRONOUS
)
47 pthread_exit(PTHREAD_CANCELED
);
51 int pthread_cancel(pthread_t thread
)
53 pthread_handle handle
= thread_handle(thread
);
56 __pthread_lock(&handle
->h_lock
, NULL
);
57 if (invalid_handle(handle
, thread
)) {
58 __pthread_unlock(&handle
->h_lock
);
61 handle
->h_descr
->p_canceled
= 1;
62 pid
= handle
->h_descr
->p_pid
;
63 __pthread_unlock(&handle
->h_lock
);
64 kill(pid
, __pthread_sig_cancel
);
68 void pthread_testcancel(void)
70 pthread_descr self
= thread_self();
71 if (THREAD_GETMEM(self
, p_canceled
)
72 && THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
)
73 pthread_exit(PTHREAD_CANCELED
);
76 void _pthread_cleanup_push(struct _pthread_cleanup_buffer
* buffer
,
77 void (*routine
)(void *), void * arg
)
79 pthread_descr self
= thread_self();
80 buffer
->__routine
= routine
;
82 buffer
->__prev
= THREAD_GETMEM(self
, p_cleanup
);
83 THREAD_SETMEM(self
, p_cleanup
, buffer
);
86 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer
* buffer
,
89 pthread_descr self
= thread_self();
90 if (execute
) buffer
->__routine(buffer
->__arg
);
91 THREAD_SETMEM(self
, p_cleanup
, buffer
->__prev
);
94 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer
* buffer
,
95 void (*routine
)(void *), void * arg
)
97 pthread_descr self
= thread_self();
98 buffer
->__routine
= routine
;
100 buffer
->__canceltype
= THREAD_GETMEM(self
, p_canceltype
);
101 buffer
->__prev
= THREAD_GETMEM(self
, p_cleanup
);
102 THREAD_SETMEM(self
, p_canceltype
, PTHREAD_CANCEL_DEFERRED
);
103 THREAD_SETMEM(self
, p_cleanup
, buffer
);
106 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer
* buffer
,
109 pthread_descr self
= thread_self();
110 if (execute
) buffer
->__routine(buffer
->__arg
);
111 THREAD_SETMEM(self
, p_cleanup
, buffer
->__prev
);
112 THREAD_SETMEM(self
, p_canceltype
, buffer
->__canceltype
);
113 if (THREAD_GETMEM(self
, p_canceled
) &&
114 THREAD_GETMEM(self
, p_cancelstate
) == PTHREAD_CANCEL_ENABLE
&&
115 THREAD_GETMEM(self
, p_canceltype
) == PTHREAD_CANCEL_ASYNCHRONOUS
)
116 pthread_exit(PTHREAD_CANCELED
);
119 void __pthread_perform_cleanup(void)
121 pthread_descr self
= thread_self();
122 struct _pthread_cleanup_buffer
* c
;
123 for (c
= THREAD_GETMEM(self
, p_cleanup
); c
!= NULL
; c
= c
->__prev
)
124 c
->__routine(c
->__arg
);
128 /* We need a hook to force the cancelation wrappers to be linked in when
129 static libpthread is used. */
130 extern const int __pthread_provide_wrappers
;
131 static const int * const __pthread_require_wrappers
=
132 &__pthread_provide_wrappers
;