1 /* Copyright (C) 2003 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>
4 and Richard Henderson <rth@redhat.com>, 2003.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 #ifdef HAVE_FORCED_UNWIND
28 static _Unwind_Reason_Code
29 unwind_stop (int version
, _Unwind_Action actions
,
30 _Unwind_Exception_Class exc_class
,
31 struct _Unwind_Exception
*exc_obj
,
32 struct _Unwind_Context
*context
, void *stop_parameter
)
34 struct pthread_unwind_buf
*buf
= stop_parameter
;
36 /* Do longjmp if we're at "end of stack", aka "end of unwind data".
37 We assume there are only C frame without unwind data in between
38 here and the jmp_buf target. Otherwise simply note that the CFA
39 of a function is NOT within it's stack frame; it's the SP of the
41 if ((actions
& _UA_END_OF_STACK
)
42 || ! _JMPBUF_UNWINDS (buf
->cancel_jmp_buf
[0].jmp_buf,
43 _Unwind_GetCFA (context
)))
44 __libc_longjmp ((struct __jmp_buf_tag
*) buf
->cancel_jmp_buf
, 1);
46 return _URC_NO_REASON
;
51 unwind_cleanup (_Unwind_Reason_Code reason
, struct _Unwind_Exception
*exc
)
56 #endif /* have forced unwind */
60 __cleanup_fct_attribute
__attribute ((noreturn
))
61 __pthread_unwind (__pthread_unwind_buf_t
*buf
)
63 struct pthread_unwind_buf
*ibuf
= (struct pthread_unwind_buf
*) buf
;
64 struct pthread
*self
= THREAD_SELF
;
66 /* Handle the compatibility stuff first. Execute all handlers
67 registered with the old method. We don't execute them in order,
68 instead, they will run first. */
69 struct _pthread_cleanup_buffer
*oldp
= ibuf
->priv
.data
.cleanup
;
70 struct _pthread_cleanup_buffer
*curp
= THREAD_GETMEM (self
, cleanup
);
76 /* Pointer to the next element. */
77 struct _pthread_cleanup_buffer
*nextp
= curp
->__prev
;
79 /* Call the handler. */
80 curp
->__routine (curp
->__arg
);
87 /* Mark the current element as handled. */
88 THREAD_SETMEM (self
, cleanup
, curp
);
91 #ifdef HAVE_FORCED_UNWIND
92 /* This is not a catchable exception, so don't provide any details about
93 the exception type. We do need to initialize the field though. */
94 THREAD_SETMEM (self
, exc
.exception_class
, 0);
95 THREAD_SETMEM (self
, exc
.exception_cleanup
, unwind_cleanup
);
97 _Unwind_ForcedUnwind (&self
->exc
, unwind_stop
, ibuf
);
99 /* We simply jump to the registered setjmp buffer. */
100 __libc_longjmp ((struct __jmp_buf_tag
*) ibuf
->cancel_jmp_buf
, 1);
104 /* We better do not get here. */
110 __cleanup_fct_attribute
__attribute ((noreturn
))
111 __pthread_unwind_next (__pthread_unwind_buf_t
*buf
)
113 struct pthread_unwind_buf
*ibuf
= (struct pthread_unwind_buf
*) buf
;
115 __pthread_unwind (ibuf
->priv
.data
.prev
);