_Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *context) { if (__builtin_expect (libgcc_s_getcfa == NULL, 0)) pthread_cancel_init (); return libgcc_s_getcfa (context); }
_Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, void *stop_argument) { if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0)) pthread_cancel_init (); return libgcc_s_forcedunwind (exc, stop, stop_argument); }
_Unwind_Reason_Code __gcc_personality_v0 (_Unwind_State state, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) { if (__builtin_expect (libgcc_s_personality == NULL, 0)) pthread_cancel_init (); return libgcc_s_personality (state, ue_header, context); }
static int live_server_start(void *arg) { pthread_cancel_init(); if(pthread_create(&server_tid, NULL, liveserver_main, NULL) != 0) { ga_error("start live-server failed.\n"); return -1; } return 0; }
void _Unwind_Resume (struct _Unwind_Exception *exc) { if (__builtin_expect (libgcc_s_handle == NULL, 0)) pthread_cancel_init (); else atomic_read_barrier (); void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume; PTR_DEMANGLE (resume); resume (exc); }
_Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *context) { if (__builtin_expect (libgcc_s_handle == NULL, 0)) pthread_cancel_init (); else atomic_read_barrier (); _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa; PTR_DEMANGLE (getcfa); return getcfa (context); }
void _Unwind_Resume (struct _Unwind_Exception *exc) { if (__glibc_unlikely (libgcc_s_handle == NULL)) pthread_cancel_init (); else atomic_read_barrier (); void (*resume) (struct _Unwind_Exception *exc) = __libgcc_s_resume; PTR_DEMANGLE (resume); resume (exc); }
_Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, void *stop_argument) { if (__builtin_expect (libgcc_s_handle == NULL, 0)) pthread_cancel_init (); else atomic_read_barrier (); _Unwind_Reason_Code (*forcedunwind) (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *) = libgcc_s_forcedunwind; PTR_DEMANGLE (forcedunwind); return forcedunwind (exc, stop, stop_argument); }
_Unwind_Reason_Code __gcc_personality_v0 (int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, struct _Unwind_Exception *ue_header, struct _Unwind_Context *context) { if (__builtin_expect (libgcc_s_handle == NULL, 0)) pthread_cancel_init (); else atomic_read_barrier (); _Unwind_Reason_Code (*personality) (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, struct _Unwind_Context *) = libgcc_s_personality; PTR_DEMANGLE (personality); return personality (version, actions, exception_class, ue_header, context); }
int pthread_cancel (pthread_t th) { volatile struct pthread *pd = (volatile struct pthread *) th; /* Make sure the descriptor is valid. */ if (INVALID_TD_P (pd)) /* Not a valid thread handle. */ return ESRCH; #ifdef SHARED pthread_cancel_init (); #endif int result = 0; int oldval; int newval; do { again: oldval = pd->cancelhandling; newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; /* Avoid doing unnecessary work. The atomic operation can potentially be expensive if the bug has to be locked and remote cache lines have to be invalidated. */ if (oldval == newval) break; /* If the cancellation is handled asynchronously just send a signal. We avoid this if possible since it's more expensive. */ if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) { /* Mark the cancellation as "in progress". */ if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, oldval | CANCELING_BITMASK, oldval)) goto again; #ifdef SIGCANCEL /* The cancellation handler will take care of marking the thread as canceled. */ pid_t pid = getpid (); INTERNAL_SYSCALL_DECL (err); int val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, pd->tid, SIGCANCEL); if (INTERNAL_SYSCALL_ERROR_P (val, err)) result = INTERNAL_SYSCALL_ERRNO (val, err); #else /* It should be impossible to get here at all, since pthread_setcanceltype should never have allowed PTHREAD_CANCEL_ASYNCHRONOUS to be set. */ abort (); #endif break; } /* A single-threaded process should be able to kill itself, since there is nothing in the POSIX specification that says that it cannot. So we set multiple_threads to true so that cancellation points get executed. */ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); #ifndef TLS_MULTIPLE_THREADS_IN_TCB __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; #endif } /* Mark the thread as canceled. This has to be done atomically since other bits could be modified as well. */ while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval, oldval)); return result; }
int pthread_cancel ( pthread_t th) { volatile struct pthread *pd = (volatile struct pthread *) th; /* Make sure the descriptor is valid. */ if (INVALID_TD_P (pd)) /* Not a valid thread handle. */ return ESRCH; #ifdef SHARED pthread_cancel_init (); #endif int result = 0; int oldval; int newval; do { again: oldval = pd->cancelhandling; newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; /* Avoid doing unnecessary work. The atomic operation can potentially be expensive if the bug has to be locked and remote cache lines have to be invalidated. */ if (oldval == newval) break; /* If the cancellation is handled asynchronously just send a signal. We avoid this if possible since it's more expensive. */ if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) { /* Mark the cancellation as "in progress". */ if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, oldval | CANCELING_BITMASK, oldval)) goto again; /* The cancellation handler will take care of marking the thread as canceled. */ INTERNAL_SYSCALL_DECL (err); /* One comment: The PID field in the TCB can temporarily be changed (in fork). But this must not affect this code here. Since this function would have to be called while the thread is executing fork, it would have to happen in a signal handler. But this is no allowed, pthread_cancel is not guaranteed to be async-safe. */ int val; #if defined(__ASSUME_TGKILL) && __ASSUME_TGKILL val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); #else # ifdef __NR_tgkill val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), pd->tid, SIGCANCEL); if (INTERNAL_SYSCALL_ERROR_P (val, err) && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) # endif val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCANCEL); #endif if (INTERNAL_SYSCALL_ERROR_P (val, err)) result = INTERNAL_SYSCALL_ERRNO (val, err); break; } } /* Mark the thread as canceled. This has to be done atomically since other bits could be modified as well. */ while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval, oldval)); return result; }