this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Provide RPC callbacks for thread creation

MLDR's copy of the RPC wrappers only uses the main socket created by MLDR on process startup. Therefore, when we were checking in calling those wrappers in the elfcalls thread code, we were using the main thread's socket rather than the new thread's socket.

Instead of that, we now have libsystem_kernel provide some RPC wrapper callbacks which the elfcalls code stores. Then, when it calls them, it'll use libsystem_kernel's copy of the RPC wrapper code, which automatically uses the current thread's socket.

+43 -21
+10 -5
src/kernel/emulation/linux/bsdthread/bsdthread_create.c
··· 13 13 #include "../machdep/tls.h" 14 14 #include "../mach/mach_traps.h" 15 15 16 + #include <darlingserver/rpc.h> 17 + 16 18 extern void *memset(void *s, int c, size_t n); 17 19 18 20 #define PTHREAD_START_CUSTOM 0x01000000 ··· 28 30 29 31 // http://www.tldp.org/FAQ/Threads-FAQ/clone.c 30 32 33 + static const struct darling_thread_create_callbacks callbacks = { 34 + .thread_self_trap = &thread_self_trap_impl, 35 + .thread_set_tsd_base = &sys_thread_set_tsd_base, 36 + .dserver_rpc_checkin = &dserver_rpc_checkin, 37 + .dserver_rpc_checkout = &dserver_rpc_checkout, 38 + .kprintf = &__simple_kprintf, 39 + }; 40 + 31 41 long sys_bsdthread_create(void* thread_start, void* arg, 32 42 void* stack, void* pthread, uint32_t flags) 33 43 { ··· 47 57 ret = darling_thread_create((void**) stack, pthread_entry_point_wrapper, thread_start, 48 58 arg, stacksize, flags); 49 59 #else 50 - struct darling_thread_create_callbacks callbacks = { 51 - .thread_self_trap = &thread_self_trap_impl, 52 - .thread_set_tsd_base = &sys_thread_set_tsd_base, 53 - }; 54 - 55 60 return __darling_thread_create(((uintptr_t)stack), pthread_obj_size, 56 61 pthread_entry_point_wrapper, thread_start, arg, (uintptr_t) stack, flags, 57 62 &callbacks, pthread);
+10 -5
src/kernel/emulation/linux/bsdthread/workq_kernreturn.c
··· 21 21 // much easier to include than libpthread's `internal.h` 22 22 #include "../../../../startup/mldr/elfcalls/dthreads.h" 23 23 24 + #include <darlingserver/rpc.h> 25 + 24 26 #define WQ_MAX_THREADS 64 25 27 26 28 #define WQOPS_QUEUE_ADD 1 ··· 88 90 89 91 // This is horrible, but it may work 90 92 static struct wq_kevent_data* wq_event_pending = NULL; 93 + 94 + static const struct darling_thread_create_callbacks callbacks = { 95 + .thread_self_trap = &thread_self_trap_impl, 96 + .thread_set_tsd_base = &sys_thread_set_tsd_base, 97 + .dserver_rpc_checkin = &dserver_rpc_checkin, 98 + .dserver_rpc_checkout = &dserver_rpc_checkout, 99 + .kprintf = &__simple_kprintf, 100 + }; 91 101 92 102 static int extract_wq_flags(int priority) { 93 103 int flags = 0; ··· 282 292 283 293 // __simple_printf("Spawning a new thread, nevents=%d\n", (wq_event != NULL) ? wq_event->nevents : -1); 284 294 wq_event_pending = wq_event; 285 - 286 - struct darling_thread_create_callbacks callbacks = { 287 - .thread_self_trap = &thread_self_trap_impl, 288 - .thread_set_tsd_base = &sys_thread_set_tsd_base, 289 - }; 290 295 291 296 __darling_thread_create(512*1024, pthread_obj_size, wqueue_entry_point_wrapper, 0, 292 297 (wq_event != NULL) ? wq_event->events : NULL, flags,
+5 -1
src/startup/mldr/elfcalls/elfcalls.h
··· 2 2 #define _ELFCALLS_H_ 3 3 4 4 #include <stdint.h> 5 + #include <stdbool.h> 5 6 6 7 struct darling_thread_create_callbacks { 7 8 int (*thread_self_trap)(void); 8 9 void (*thread_set_tsd_base)(void*, int); 10 + int (*dserver_rpc_checkin)(bool is_fork); 11 + int (*dserver_rpc_checkout)(int exec_listener_pipe, bool executing_macho); 12 + void (*kprintf)(const char* format, ...); 9 13 }; 10 14 11 - typedef struct darling_thread_create_callbacks* darling_thread_create_callbacks_t; 15 + typedef const struct darling_thread_create_callbacks* darling_thread_create_callbacks_t; 12 16 13 17 struct elf_calls 14 18 {
+18 -10
src/startup/mldr/elfcalls/threads.c
··· 43 43 static __thread jmp_buf t_jmpbuf; 44 44 static __thread void* t_freeaddr; 45 45 static __thread size_t t_freesize; 46 + static __thread darling_thread_create_callbacks_t t_callbacks = NULL; 46 47 47 48 typedef void (*thread_ep)(void**, int, ...); 48 49 struct arg_struct ··· 233 234 // the socket is ready; assign it now 234 235 dthread->tsd[DTHREAD_TSD_SLOT_DSERVER_RPC_FD] = (void*)(intptr_t)new_rpc_fd; 235 236 236 - // checkin with darlingserver on this new thread 237 - if (dserver_rpc_checkin(false) < 0) { 238 - // we can't do ANYTHING if darlingserver doesn't acknowledge us successfully 239 - abort(); 240 - } 237 + t_callbacks = args.callbacks; 241 238 242 239 // libpthread now expects the kernel to set the TSD 243 240 // so, since we're pretending to be the kernel handling threads... 244 - args.callbacks->thread_set_tsd_base(&dthread->tsd[0], 0); 241 + t_callbacks->thread_set_tsd_base(&dthread->tsd[0], 0); 245 242 *flags |= args.is_workqueue ? DWQ_FLAG_THREAD_TSD_BASE_SET : DTHREAD_START_TSD_BASE_SET; 246 243 247 - int thread_self_port = args.callbacks->thread_self_trap(); 244 + // now that we've set the TSD, darlingserver RPC can now use our per-thread socket; 245 + // let's check-in with darlingserver on this new thread 246 + if (t_callbacks->dserver_rpc_checkin(false) < 0) { 247 + // we can't do ANYTHING if darlingserver doesn't acknowledge us successfully 248 + abort(); 249 + } 250 + 251 + int thread_self_port = t_callbacks->thread_self_trap(); 248 252 dthread->tsd[DTHREAD_TSD_SLOT_MACH_THREAD_SELF] = (void*)(intptr_t)thread_self_port; 249 253 args.port = thread_self_port; 250 254 ··· 305 309 int __darling_thread_terminate(void* stackaddr, 306 310 unsigned long freesize, unsigned long pthobj_size) 307 311 { 308 - if (dserver_rpc_checkout(-1, false) < 0) { 309 - // failing to checkout is not fatal. 312 + if ((t_callbacks ? t_callbacks->dserver_rpc_checkout : dserver_rpc_checkout)(-1, false) < 0) { 313 + // failing to check-out is not fatal. 310 314 // it's not ideal, but it's not fatal. 311 315 #define CHECKOUT_FAILURE_MESSAGE "Failed to checkout" 312 - dserver_rpc_kprintf(CHECKOUT_FAILURE_MESSAGE, sizeof(CHECKOUT_FAILURE_MESSAGE) - 1); 316 + if (t_callbacks) { 317 + t_callbacks->kprintf(CHECKOUT_FAILURE_MESSAGE); 318 + } else { 319 + dserver_rpc_kprintf(CHECKOUT_FAILURE_MESSAGE, sizeof(CHECKOUT_FAILURE_MESSAGE) - 1); 320 + } 313 321 } 314 322 315 323 if (getpid() == syscall(SYS_gettid))