#include "bsdthread_register.h" #include "../base.h" #include "../errno.h" #include #include "../signal/sigexc.h" #include #include #include #include #include "../simple.h" int pthread_obj_size; bsdthread_entry_t pthread_entry_point; bsdwqthread_entry_t wqueue_entry_point; #define PTHREAD_FEATURE_DISPATCHFUNC 1 #define PTHREAD_FEATURE_QOS_MAINTENANCE 0x10 #define PTHREAD_FEATURE_QOS_DEFAULT 0x40000000 #define WORKQ_FEATURE_FINEPRIO 0x02 #define WORKQ_FEATURE_KEVENT 0x40 struct _pthread_registration_data { uint64_t version; uint64_t dispatch_queue_offset; uint64_t main_qos; uint32_t tsd_offset; uint32_t return_to_kernel_offset; uint32_t mach_thread_self_offset; } __attribute__ ((packed)); static struct _pthread_registration_data g_pth_regdata; long sys_bsdthread_register(void* thread_start, void* wqthread, int pthsize, const struct _pthread_registration_data* pth_regdata, unsigned long pth_regdata_len, unsigned long long dpq_offset) { pthread_obj_size = pthsize; pthread_entry_point = (bsdthread_entry_t) thread_start; wqueue_entry_point = (bsdwqthread_entry_t) wqthread; g_pth_regdata = *pth_regdata; uintptr_t pthread_handle = _pthread_getspecific_direct(_PTHREAD_TSD_SLOT_PTHREAD_SELF); uintptr_t dispatch_qaddr = pthread_handle + g_pth_regdata.tsd_offset + g_pth_regdata.dispatch_queue_offset; if (dserver_rpc_set_thread_handles(pthread_handle, dispatch_qaddr) < 0) { __simple_abort(); } return /* WORKQ_FEATURE_KEVENT | WORKQ_FEATURE_FINEPRIO | PTHREAD_FEATURE_QOS_MAINTENANCE | PTHREAD_FEATURE_DISPATCHFUNC | PTHREAD_FEATURE_QOS_DEFAULT */ 0; } void pthread_entry_point_wrapper(void* self, int thread_port, void* funptr, void* funarg, unsigned long stack_addr, unsigned int flags) { sigexc_thread_setup(); uintptr_t pthread_handle = (unsigned long) self; uintptr_t dispatch_qaddr = pthread_handle + g_pth_regdata.tsd_offset + g_pth_regdata.dispatch_queue_offset; if (dserver_rpc_set_thread_handles(pthread_handle, dispatch_qaddr) < 0) { __simple_abort(); } pthread_entry_point(self, thread_port, funptr, funarg, stack_addr, flags); } void wqueue_entry_point_wrapper(void* self, int thread_port, void* stackaddr, void* item, int reuse, int nevents) { sigexc_thread_setup(); wqueue_entry_point(self, thread_port, stackaddr, item, reuse, nevents); }