123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- #include <errno.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <string.h>
- #include "pthreadP.h"
- #include <hp-timing.h>
- #include <ldsodefs.h>
- #include <atomic.h>
- #include <libc-internal.h>
- #include <resolv.h>
- static int start_thread (void *arg);
- int __pthread_debug;
- static td_thr_events_t __nptl_threads_events;
- static struct pthread *__nptl_last_event;
- unsigned int __nptl_nthreads = 1;
- #include "allocatestack.c"
- #include "createthread.c"
- struct pthread *
- internal_function
- __find_in_stack_list (pd)
- struct pthread *pd;
- {
- list_t *entry;
- struct pthread *result = NULL;
- lll_lock (stack_cache_lock);
- list_for_each (entry, &stack_used)
- {
- struct pthread *curp;
- curp = list_entry (entry, struct pthread, list);
- if (curp == pd)
- {
- result = curp;
- break;
- }
- }
- if (result == NULL)
- list_for_each (entry, &__stack_user)
- {
- struct pthread *curp;
- curp = list_entry (entry, struct pthread, list);
- if (curp == pd)
- {
- result = curp;
- break;
- }
- }
- lll_unlock (stack_cache_lock);
- return result;
- }
- void
- attribute_hidden
- __nptl_deallocate_tsd (void)
- {
- struct pthread *self = THREAD_SELF;
-
- if (THREAD_GETMEM (self, specific_used))
- {
- size_t round;
- size_t cnt;
- round = 0;
- do
- {
- size_t idx;
-
- THREAD_SETMEM (self, specific_used, false);
- for (cnt = idx = 0; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt)
- {
- struct pthread_key_data *level2;
- level2 = THREAD_GETMEM_NC (self, specific, cnt);
- if (level2 != NULL)
- {
- size_t inner;
- for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE;
- ++inner, ++idx)
- {
- void *data = level2[inner].data;
- if (data != NULL)
- {
-
- level2[inner].data = NULL;
-
- if (level2[inner].seq
- == __pthread_keys[idx].seq
-
- && __pthread_keys[idx].destr != NULL)
-
- __pthread_keys[idx].destr (data);
- }
- }
- }
- else
- idx += PTHREAD_KEY_1STLEVEL_SIZE;
- }
- if (THREAD_GETMEM (self, specific_used) == 0)
-
- goto just_free;
- }
-
- while (__builtin_expect (++round < PTHREAD_DESTRUCTOR_ITERATIONS, 0));
-
- memset (&THREAD_SELF->specific_1stblock, '\0',
- sizeof (self->specific_1stblock));
- just_free:
-
- for (cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt)
- {
- struct pthread_key_data *level2;
- level2 = THREAD_GETMEM_NC (self, specific, cnt);
- if (level2 != NULL)
- {
-
- free (level2);
- THREAD_SETMEM_NC (self, specific, cnt, NULL);
- }
- }
- THREAD_SETMEM (self, specific_used, false);
- }
- }
- void
- internal_function
- __free_tcb (struct pthread *pd)
- {
-
- if (__builtin_expect (atomic_bit_test_set (&pd->cancelhandling,
- TERMINATED_BIT) == 0, 1))
- {
-
- if (DEBUGGING_P && __find_in_stack_list (pd) == NULL)
-
- abort ();
-
- __deallocate_stack (pd);
- }
- }
- static int
- start_thread (void *arg)
- {
- struct pthread *pd = (struct pthread *) arg;
- #if HP_TIMING_AVAIL
-
- hp_timing_t now;
- HP_TIMING_NOW (now);
- THREAD_SETMEM (pd, cpuclock_offset, now);
- #endif
-
- __resp = &pd->res;
-
- struct pthread_unwind_buf unwind_buf;
-
- unwind_buf.priv.data.prev = NULL;
- unwind_buf.priv.data.cleanup = NULL;
- int not_first_call;
- not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
- if (__builtin_expect (! not_first_call, 1))
- {
-
- THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
- if (__builtin_expect (pd->stopped_start, 0))
- {
- int oldtype = CANCEL_ASYNC ();
-
- lll_lock (pd->lock);
-
- lll_unlock (pd->lock);
- CANCEL_RESET (oldtype);
- }
-
- #ifdef CALL_THREAD_FCT
- THREAD_SETMEM (pd, result, CALL_THREAD_FCT (pd));
- #else
- THREAD_SETMEM (pd, result, pd->start_routine (pd->arg));
- #endif
- }
-
- __nptl_deallocate_tsd ();
-
- if (__builtin_expect (atomic_decrement_and_test (&__nptl_nthreads), 0))
-
- exit (0);
-
- if (__builtin_expect (pd->report_events, 0))
- {
-
- const int idx = __td_eventword (TD_DEATH);
- const uint32_t mask = __td_eventmask (TD_DEATH);
- if ((mask & (__nptl_threads_events.event_bits[idx]
- | pd->eventbuf.eventmask.event_bits[idx])) != 0)
- {
-
- if (pd->nextevent == NULL)
- {
- pd->eventbuf.eventnum = TD_DEATH;
- pd->eventbuf.eventdata = pd;
- do
- pd->nextevent = __nptl_last_event;
- while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event,
- pd, pd->nextevent));
- }
-
- __nptl_death_event ();
- }
- }
-
- atomic_bit_set (&pd->cancelhandling, EXITING_BIT);
-
- if (IS_DETACHED (pd))
-
- __free_tcb (pd);
-
- __exit_thread_inline (0);
-
- return 0;
- }
- static const struct pthread_attr default_attr =
- {
-
- .guardsize = 1,
- };
- int
- __pthread_create_2_1 (newthread, attr, start_routine, arg)
- pthread_t *newthread;
- const pthread_attr_t *attr;
- void *(*start_routine) (void *);
- void *arg;
- {
- STACK_VARIABLES;
- const struct pthread_attr *iattr = (struct pthread_attr *) attr;
- if (iattr == NULL)
-
- iattr = &default_attr;
- struct pthread *pd = 0;
- int err = ALLOCATE_STACK (iattr, &pd);
- if (__builtin_expect (err != 0, 0))
-
- return err;
-
- #ifdef TLS_TCB_AT_TP
-
- pd->header.self = pd;
-
- pd->header.tcb = pd;
- #endif
-
- pd->start_routine = start_routine;
- pd->arg = arg;
-
- struct pthread *self = THREAD_SELF;
- pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
- | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)));
-
- pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL;
-
- pd->eventbuf = self->eventbuf;
-
- pd->schedpolicy = self->schedpolicy;
- pd->schedparam = self->schedparam;
-
- #ifdef THREAD_COPY_STACK_GUARD
- THREAD_COPY_STACK_GUARD (pd);
- #endif
-
- if (attr != NULL
- && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
- && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0)
- {
- INTERNAL_SYSCALL_DECL (scerr);
-
- if (iattr->flags & ATTR_FLAG_POLICY_SET)
- pd->schedpolicy = iattr->schedpolicy;
- else if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0)
- {
- pd->schedpolicy = INTERNAL_SYSCALL (sched_getscheduler, scerr, 1, 0);
- pd->flags |= ATTR_FLAG_POLICY_SET;
- }
- if (iattr->flags & ATTR_FLAG_SCHED_SET)
- memcpy (&pd->schedparam, &iattr->schedparam,
- sizeof (struct sched_param));
- else if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0)
- {
- INTERNAL_SYSCALL (sched_getparam, scerr, 2, 0, &pd->schedparam);
- pd->flags |= ATTR_FLAG_SCHED_SET;
- }
-
- int minprio = INTERNAL_SYSCALL (sched_get_priority_min, scerr, 1,
- iattr->schedpolicy);
- int maxprio = INTERNAL_SYSCALL (sched_get_priority_max, scerr, 1,
- iattr->schedpolicy);
- if (pd->schedparam.sched_priority < minprio
- || pd->schedparam.sched_priority > maxprio)
- {
- err = EINVAL;
- goto errout;
- }
- }
-
- *newthread = (pthread_t) pd;
-
- bool is_detached = IS_DETACHED (pd);
-
- err = create_thread (pd, iattr, STACK_VARIABLES_ARGS);
- if (err != 0)
- {
-
- if (!is_detached)
- {
- errout:
- __deallocate_stack (pd);
- }
- return err;
- }
- return 0;
- }
- weak_alias(__pthread_create_2_1, pthread_create)
- #include "../nptl_db/db_info.c"
- PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_lock)
- PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_unlock)
- PTHREAD_STATIC_FN_REQUIRE (pthread_once)
- PTHREAD_STATIC_FN_REQUIRE (pthread_cancel)
- PTHREAD_STATIC_FN_REQUIRE (pthread_key_create)
- PTHREAD_STATIC_FN_REQUIRE (pthread_setspecific)
- PTHREAD_STATIC_FN_REQUIRE (pthread_getspecific)
- PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_init)
- PTHREAD_STATIC_FN_REQUIRE (_pthread_cleanup_push_defer)
- PTHREAD_STATIC_FN_REQUIRE (_pthread_cleanup_pop_restore)
|