static int _rthread_init(void) { pthread_t thread = &_initial_thread; extern int __isthreaded; thread->tid = getthrid(); thread->donesem.lock = _SPINLOCK_UNLOCKED; thread->flags |= THREAD_CANCEL_ENABLE|THREAD_CANCEL_DEFERRED; thread->flags_lock = _SPINLOCK_UNLOCKED; strlcpy(thread->name, "Main process", sizeof(thread->name)); LIST_INSERT_HEAD(&_thread_list, thread, threads); if (_rthread_open_kqueue()) return (errno); _rthread_debug_init(); _rthread_debug(1, "rthread init\n"); _threads_ready = 1; __isthreaded = 1; #if defined(__ELF__) && defined(PIC) /* * To avoid recursion problems in ld.so, we need to trigger the * functions once to fully bind them before registering them * for use. */ _rthread_dl_lock(0); _rthread_dl_lock(1); _rthread_bind_lock(0); _rthread_bind_lock(1); dlctl(NULL, DL_SETTHREADLCK, _rthread_dl_lock); dlctl(NULL, DL_SETBINDLCK, _rthread_bind_lock); #endif return (0); }
static void zend_jit_perf_jitdump_register(const char *name, void *start, size_t size) { if (jitdump_fd >= 0) { static uint64_t id = 1; zend_perf_jitdump_load_record rec; size_t len = strlen(name); uint32_t thread_id; #if defined(__linux__) thread_id = syscall(SYS_gettid); #elif defined(__FreeBSD__) long tid; thr_self(&tid); thread_id = (uint32_t)tid; #elif defined(__OpenBSD__) thread_id = getthrid(); #elif defined(__NetBSD__) thread_id = _lwp_self(); #endif memset(&rec, 0, sizeof(rec)); rec.hdr.event = ZEND_PERF_JITDUMP_RECORD_LOAD; rec.hdr.size = sizeof(rec) + len + 1 + size; rec.hdr.time_stamp = zend_perf_timestamp(); rec.process_id = getpid(); rec.thread_id = thread_id; rec.vma = (uint64_t)(uintptr_t)start; rec.code_address = (uint64_t)(uintptr_t)start; rec.code_size = (uint64_t)size; rec.code_id = id++; zend_quiet_write(jitdump_fd, &rec, sizeof(rec)); zend_quiet_write(jitdump_fd, name, len + 1); zend_quiet_write(jitdump_fd, start, size); } }
static inline void setup_static_tib(Elf_Phdr *phdr, int phnum) { struct tib *tib; char *base; int i; if (phdr != NULL) { for (i = 0; i < phnum; i++) { if (phdr[i].p_type != PT_TLS) continue; if (phdr[i].p_memsz == 0) break; if (phdr[i].p_memsz < phdr[i].p_filesz) break; /* invalid */ #if TLS_VARIANT == 1 _static_tls_size = phdr[i].p_memsz; #elif TLS_VARIANT == 2 /* * variant 2 places the data before the TIB * so we need to round up to the alignment */ _static_tls_size = ELF_ROUND(phdr[i].p_memsz, phdr[i].p_align); #endif if (phdr[i].p_vaddr != 0 && phdr[i].p_filesz != 0) { static_tls = (void *)phdr[i].p_vaddr; static_tls_fsize = phdr[i].p_filesz; } break; } } /* * We call getpagesize() here instead of using _pagesize because * there's no aux-vector in non-PIE static links, so _pagesize * might not be set yet. If so getpagesize() will get the value. */ base = mmap(NULL, ELF_ROUND(_static_tls_size + sizeof *tib, getpagesize()), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); # if TLS_VARIANT == 1 tib = (struct tib *)base; # elif TLS_VARIANT == 2 tib = (struct tib *)(base + _static_tls_size); # endif _static_tls_init(base); TIB_INIT(tib, NULL, NULL); tib->tib_tid = getthrid(); TCB_SET(TIB_TO_TCB(tib)); #if ! TCB_HAVE_MD_GET _libc_single_tcb = TIB_TO_TCB(tib); #endif }
static pthread_t _rthread_findself(void) { pthread_t me; pid_t tid = getthrid(); LIST_FOREACH(me, &_thread_list, threads) if (me->tid == tid) break; return (me); }
int pthread_join(pthread_t thread, void **retval) { int e; if (thread->tid == getthrid()) e = EDEADLK; else if (thread->flags & THREAD_DETACHED) e = EINVAL; else { _sem_wait(&thread->donesem, 0, 0); if (retval) *retval = thread->retval; e = 0; /* We should be the last having a ref to this thread, but * someone stupid or evil might haved detached it; * in that case the thread will cleanup itself */ if ((thread->flags & THREAD_DETACHED) == 0) _rthread_free(thread); } _rthread_reaper(); return (e); }