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
= self
->p_cancelstate
;
29 self
->p_cancelstate
= state
;
30 if (self
->p_canceled
&&
31 self
->p_cancelstate
== PTHREAD_CANCEL_ENABLE
&&
32 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
= self
->p_canceltype
;
43 self
->p_canceltype
= type
;
44 if (self
->p_canceled
&&
45 self
->p_cancelstate
== PTHREAD_CANCEL_ENABLE
&&
46 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
);
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 (self
->p_canceled
&& self
->p_cancelstate
== PTHREAD_CANCEL_ENABLE
)
72 pthread_exit(PTHREAD_CANCELED
);
75 void _pthread_cleanup_push(struct _pthread_cleanup_buffer
* buffer
,
76 void (*routine
)(void *), void * arg
)
78 pthread_descr self
= thread_self();
79 buffer
->routine
= routine
;
81 buffer
->prev
= self
->p_cleanup
;
82 self
->p_cleanup
= buffer
;
85 void _pthread_cleanup_pop(struct _pthread_cleanup_buffer
* buffer
,
88 pthread_descr self
= thread_self();
89 if (execute
) buffer
->routine(buffer
->arg
);
90 self
->p_cleanup
= buffer
->prev
;
93 void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer
* buffer
,
94 void (*routine
)(void *), void * arg
)
96 pthread_descr self
= thread_self();
97 buffer
->routine
= routine
;
99 buffer
->canceltype
= self
->p_canceltype
;
100 buffer
->prev
= self
->p_cleanup
;
101 self
->p_canceltype
= PTHREAD_CANCEL_DEFERRED
;
102 self
->p_cleanup
= buffer
;
105 void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer
* buffer
,
108 pthread_descr self
= thread_self();
109 if (execute
) buffer
->routine(buffer
->arg
);
110 self
->p_cleanup
= buffer
->prev
;
111 self
->p_canceltype
= buffer
->canceltype
;
112 if (self
->p_canceled
&&
113 self
->p_cancelstate
== PTHREAD_CANCEL_ENABLE
&&
114 self
->p_canceltype
== PTHREAD_CANCEL_ASYNCHRONOUS
)
115 pthread_exit(PTHREAD_CANCELED
);
118 void __pthread_perform_cleanup(void)
120 pthread_descr self
= thread_self();
121 struct _pthread_cleanup_buffer
* c
;
122 for (c
= self
->p_cleanup
; c
!= NULL
; c
= c
->prev
) c
->routine(c
->arg
);
126 /* We need a hook to force the cancelation wrappers to be linked in when
127 static libpthread is used. */
128 extern const int __pthread_provide_wrappers
;
129 static const int * const __pthread_require_wrappers
=
130 &__pthread_provide_wrappers
;