@@ -413,6 +413,7 @@ libc {
_thread_db_pthread_eventbuf;
_thread_db_pthread_eventbuf_eventmask;
_thread_db_pthread_eventbuf_eventmask_event_bits;
+ _thread_db_pthread_joinstate;
_thread_db_pthread_key_data_data;
_thread_db_pthread_key_data_level2_data;
_thread_db_pthread_key_data_seq;
@@ -119,7 +119,7 @@ get_cached_stack (size_t *sizep, void **memp)
*memp = result->stackblock;
/* Cancellation handling is back to the default. */
- result->cancelhandling = 0;
+ result->cancel_requested = 0;
result->cancelstate = PTHREAD_CANCEL_ENABLE;
result->canceltype = PTHREAD_CANCEL_DEFERRED;
result->cleanup = NULL;
@@ -34,15 +34,9 @@ __pthread_enable_asynccancel (void)
int oldval = THREAD_GETMEM (self, canceltype);
THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
- int ch = THREAD_GETMEM (self, cancelhandling);
-
if (self->cancelstate == PTHREAD_CANCEL_ENABLE
- && (ch & CANCELED_BITMASK)
- && !(ch & EXITING_BITMASK)
- && !(ch & TERMINATED_BITMASK))
- {
- __do_cancel ();
- }
+ && self->cancel_requested == 1)
+ __do_cancel ();
return oldval;
}
@@ -285,17 +285,8 @@ struct pthread
struct pthread_unwind_buf *cleanup_jmp_buf;
#define HAVE_CLEANUP_JMP_BUF
- /* Flags determining processing of cancellation. */
- int cancelhandling;
- /* Bit set if canceled. */
-#define CANCELED_BIT 3
-#define CANCELED_BITMASK (0x01 << CANCELED_BIT)
- /* Bit set if thread is exiting. */
-#define EXITING_BIT 4
-#define EXITING_BITMASK (0x01 << EXITING_BIT)
- /* Bit set if thread terminated and TCB is freed. */
-#define TERMINATED_BIT 5
-#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT)
+ /* Flag to determine whether the thread is signaled to be cancelled. */
+ int cancel_requested;
/* Flags. Including those copied from the thread attribute. */
int flags;
@@ -23,22 +23,18 @@
void
__nptl_free_tcb (struct pthread *pd)
{
- /* The thread is exiting now. */
- if (atomic_bit_test_set (&pd->cancelhandling, TERMINATED_BIT) == 0)
- {
- /* Free TPP data. */
- if (pd->tpp != NULL)
- {
- struct priority_protection_data *tpp = pd->tpp;
+ /* Free TPP data. */
+ if (pd->tpp != NULL)
+ {
+ struct priority_protection_data *tpp = pd->tpp;
- pd->tpp = NULL;
- free (tpp);
- }
+ pd->tpp = NULL;
+ free (tpp);
+ }
- /* Queue the stack memory block for reuse and exit the process. The
- kernel will signal via writing to the address returned by
- QUEUE-STACK when the stack is available. */
- __nptl_deallocate_stack (pd);
- }
+ /* Queue the stack memory block for reuse and exit the process. The kernel
+ will signal via writing to the address of pthread 'joinstate' member
+ (due CLONE_CHILD_CLEARTID) when the child exits. */
+ __nptl_deallocate_stack (pd);
}
libc_hidden_def (__nptl_free_tcb)
@@ -42,11 +42,8 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
struct pthread *self = THREAD_SELF;
- int ch = atomic_load_relaxed (&self->cancelhandling);
- /* Cancelation not enabled, not cancelled, or already exitting. */
if (self->cancelstate == PTHREAD_CANCEL_DISABLE
- || (ch & CANCELED_BITMASK) == 0
- || (ch & EXITING_BITMASK) != 0)
+ || atomic_load_relaxed (&self->joinstate) == THREAD_STATE_EXITING)
return;
/* Set the return value. */
@@ -93,8 +90,9 @@ __pthread_cancel (pthread_t th)
}
#endif
- int oldch = atomic_fetch_or_acquire (&pd->cancelhandling, CANCELED_BITMASK);
- if ((oldch & CANCELED_BITMASK) != 0)
+ /* If already cancelled just return (cancellation will be acted upon in next
+ cancellation entrypoint). */
+ if (atomic_exchange_relaxed (&pd->cancel_requested, 1) == 1)
return 0;
if (pd == THREAD_SELF)
@@ -478,12 +478,6 @@ start_thread (void *arg)
}
}
- /* The thread is exiting now. Don't set this bit until after we've hit
- the event-reporting breakpoint, so that td_thr_get_info on us while at
- the breakpoint reports TD_THR_RUN state rather than TD_THR_ZOMBIE. */
- atomic_bit_set (&pd->cancelhandling, EXITING_BIT);
-
-
/* CONCURRENCY NOTES:
Concurrent pthread_detach() will either set state to
@@ -569,8 +563,8 @@ start_thread (void *arg)
do
/* XXX This differs from the typical futex_wait_simple pattern in that
the futex_wait condition (setxid_futex) is different from the
- condition used in the surrounding loop (cancelhandling). We need
- to check and document why this is correct. */
+ condition used in the surrounding loop. We need to check and
+ document why this is correct. */
futex_wait_simple (&pd->setxid_futex, 0, FUTEX_PRIVATE);
while (atomic_load_relaxed (&pd->setxid_flag) == 1);
@@ -33,14 +33,10 @@ check_for_deadlock (struct pthread *pd)
{
struct pthread *self = THREAD_SELF;
return ((pd == self
- || (atomic_load_acquire (&self->joinstate) == THREAD_STATE_DETACHED
- && (pd->cancelhandling
- & (CANCELED_BITMASK | EXITING_BITMASK
- | TERMINATED_BITMASK)) == 0))
+ || (atomic_load_acquire (&self->joinstate)
+ == THREAD_STATE_DETACHED))
&& !(self->cancelstate == PTHREAD_CANCEL_ENABLE
- && (pd->cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK
- | TERMINATED_BITMASK))
- == CANCELED_BITMASK));
+ && atomic_load_relaxed (&self->cancel_requested) == 1));
}
int
@@ -23,14 +23,8 @@ void
___pthread_testcancel (void)
{
struct pthread *self = THREAD_SELF;
- int cancelhandling = THREAD_GETMEM (self, cancelhandling);
- if (self->cancelstate == PTHREAD_CANCEL_ENABLE
- && (cancelhandling & CANCELED_BITMASK)
- && !(cancelhandling & EXITING_BITMASK)
- && !(cancelhandling & TERMINATED_BITMASK))
- {
- __do_cancel ();
- }
+ if (self->cancelstate == PTHREAD_CANCEL_ENABLE && self->cancel_requested == 1)
+ __do_cancel ();
}
versioned_symbol (libc, ___pthread_testcancel, pthread_testcancel, GLIBC_2_34);
libc_hidden_ver (___pthread_testcancel, __pthread_testcancel)
@@ -53,7 +53,7 @@ DB_STRUCT_FIELD (pthread, list)
DB_STRUCT_FIELD (pthread, report_events)
DB_STRUCT_FIELD (pthread, tid)
DB_STRUCT_FIELD (pthread, start_routine)
-DB_STRUCT_FIELD (pthread, cancelhandling)
+DB_STRUCT_FIELD (pthread, joinstate)
DB_STRUCT_FIELD (pthread, schedpolicy)
DB_STRUCT_FIELD (pthread, schedparam_sched_priority)
DB_STRUCT_FIELD (pthread, specific)
@@ -27,7 +27,7 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
{
td_err_e err;
void *copy;
- psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events;
+ psaddr_t tls, schedpolicy, schedprio, joinstate, tid, report_events;
LOG ("td_thr_get_info");
@@ -36,7 +36,7 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
/* Special case for the main thread before initialization. */
copy = NULL;
tls = 0;
- cancelhandling = 0;
+ joinstate = 0;
schedpolicy = SCHED_OTHER;
schedprio = 0;
tid = 0;
@@ -75,8 +75,8 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0);
if (err != TD_OK)
return err;
- err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread,
- cancelhandling, 0);
+ err = DB_GET_FIELD_LOCAL (joinstate, th->th_ta_p, copy, pthread,
+ joinstate, 0);
if (err != TD_OK)
return err;
err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread,
@@ -95,13 +95,11 @@ td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop)
? 0 : (uintptr_t) schedprio);
infop->ti_type = TD_THR_USER;
- if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0)
- /* XXX For now there is no way to get more information. */
+ int js = (int) (uintptr_t) joinstate;
+ if (js == THREAD_STATE_JOINABLE || js == THREAD_STATE_DETACHED)
infop->ti_state = TD_THR_ACTIVE;
- else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
- infop->ti_state = TD_THR_ZOMBIE;
else
- infop->ti_state = TD_THR_UNKNOWN;
+ infop->ti_state = TD_THR_ZOMBIE;
/* Initialization which are the same in both cases. */
infop->ti_ta_p = th->th_ta_p;
@@ -22,7 +22,7 @@
td_err_e
td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset)
{
- psaddr_t cancelhandling, tid;
+ psaddr_t joinstate, tid;
td_err_e err;
LOG ("td_thr_getfpregs");
@@ -33,13 +33,14 @@ td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset)
regset) != PS_OK ? TD_ERR : TD_OK;
/* We have to get the state and the PID for this thread. */
- err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
- cancelhandling, 0);
+ err = DB_GET_FIELD (joinstate, th->th_ta_p, th->th_unique, pthread,
+ joinstate, 0);
if (err != TD_OK)
return err;
/* If the thread already terminated we return all zeroes. */
- if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK)
+ int js = (int) (uintptr_t) joinstate;
+ if (js == THREAD_STATE_EXITING || js == THREAD_STATE_EXITED)
memset (regset, '\0', sizeof (*regset));
/* Otherwise get the register content through the callback. */
else
@@ -22,7 +22,7 @@
td_err_e
td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset)
{
- psaddr_t cancelhandling, tid;
+ psaddr_t joinstate, tid;
td_err_e err;
LOG ("td_thr_getgregs");
@@ -33,13 +33,14 @@ td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset)
regset) != PS_OK ? TD_ERR : TD_OK;
/* We have to get the state and the PID for this thread. */
- err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
- cancelhandling, 0);
+ err = DB_GET_FIELD (joinstate, th->th_ta_p, th->th_unique, pthread,
+ joinstate, 0);
if (err != TD_OK)
return err;
/* If the thread already terminated we return all zeroes. */
- if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK)
+ int js = (int) (uintptr_t) joinstate;
+ if (js == THREAD_STATE_EXITING || js == THREAD_STATE_EXITED)
memset (regset, '\0', sizeof (*regset));
/* Otherwise get the register content through the callback. */
else
@@ -22,7 +22,7 @@
td_err_e
td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs)
{
- psaddr_t cancelhandling, tid;
+ psaddr_t joinstate, tid;
td_err_e err;
LOG ("td_thr_setfpregs");
@@ -33,13 +33,14 @@ td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs)
fpregs) != PS_OK ? TD_ERR : TD_OK;
/* We have to get the state and the PID for this thread. */
- err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
- cancelhandling, 0);
+ err = DB_GET_FIELD (joinstate, th->th_ta_p, th->th_unique, pthread,
+ joinstate, 0);
if (err != TD_OK)
return err;
/* Only set the registers if the thread hasn't yet terminated. */
- if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
+ int js = (int) (uintptr_t) joinstate;
+ if (js != THREAD_STATE_EXITING || js != THREAD_STATE_EXITED)
{
err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
if (err != TD_OK)
@@ -22,7 +22,7 @@
td_err_e
td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs)
{
- psaddr_t cancelhandling, tid;
+ psaddr_t joinstate, tid;
td_err_e err;
LOG ("td_thr_setgregs");
@@ -33,13 +33,14 @@ td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs)
gregs) != PS_OK ? TD_ERR : TD_OK;
/* We have to get the state and the PID for this thread. */
- err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
- cancelhandling, 0);
+ err = DB_GET_FIELD (joinstate, th->th_ta_p, th->th_unique, pthread,
+ joinstate, 0);
if (err != TD_OK)
return err;
/* Only set the registers if the thread hasn't yet terminated. */
- if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0)
+ int js = (int) (uintptr_t) joinstate;
+ if (js != THREAD_STATE_EXITING || js != THREAD_STATE_EXITED)
{
err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0);
if (err != TD_OK)
@@ -3,7 +3,6 @@
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
-CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
TLS_PRE_TCB_SIZE sizeof (struct pthread)
@@ -4,7 +4,6 @@
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
-CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo)
@@ -271,9 +271,6 @@ __exit_thread (void *value)
{
struct pthread *self = THREAD_SELF;
- /* Make sure we get no more cancellations. */
- THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
-
THREAD_SETMEM (self, result, value);
/* It is required by POSIX XSH 2.9.5 Thread Cancellation under the heading
@@ -4,7 +4,6 @@
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
-CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
TLS_PRE_TCB_SIZE sizeof (struct pthread)
@@ -4,7 +4,6 @@
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
-CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
CLEANUP offsetof (struct pthread, cleanup)
CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev)
@@ -13,6 +12,3 @@ MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads)
POINTER_GUARD offsetof (tcbhead_t, pointer_guard)
FEATURE_1_OFFSET offsetof (tcbhead_t, feature_1)
SSP_BASE_OFFSET offsetof (tcbhead_t, ssp_base)
-
-TCB_CANCELED_BITMASK CANCELED_BITMASK