this repo has no description
1
fork

Configure Feed

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

Work on getting libdispatch working

+77 -40
+1 -1
src/kernel/emulation/linux/bsdthread/bsdthread_register.h
··· 3 3 typedef void (*bsdthread_entry_t)(void* /* self */, int /* thread_port */, void* /* funptr */, 4 4 void* /* funarg */, unsigned long /* stacksize */, unsigned int /* flags */); 5 5 typedef void (*bsdwqthread_entry_t)(void* /* self */, int /* thread_port */, void* /* stackaddr */, 6 - void* /* item */, int /* reuse */); 6 + void* /* item */, int /* reuse */, int /* nevents */); 7 7 8 8 extern int pthread_obj_size; 9 9 extern bsdthread_entry_t pthread_entry_point;
+33 -18
src/kernel/emulation/linux/bsdthread/workq_kernreturn.c
··· 55 55 long tv_nsec; 56 56 }; 57 57 58 - #define __PTK_DARLING_WQ_KEVENT_KEY 150 59 - 60 58 void* __attribute__((weak)) __attribute__((visibility("default"))) pthread_getspecific(unsigned long key) { return NULL; } 61 59 int __attribute__((weak)) __attribute__((visibility("default"))) pthread_setspecific(unsigned long key, const void* value) { return 1; } 60 + 61 + // This is horrible, but it may work 62 + static struct wq_kevent_data* wq_event_pending = NULL; 62 63 63 64 long sys_workq_kernreturn(int options, void* item, int affinity, int prio) 64 65 { ··· 73 74 struct kevent_qos_s* keventlist = item; 74 75 int nkevents = affinity; 75 76 76 - wq_event = (struct wq_kevent_data*) pthread_getspecific(__PTK_DARLING_WQ_KEVENT_KEY); 77 + // __simple_printf("kevent return, obj=%p, nkevents=%d\n", wq_event, nkevents); 77 78 78 - if (wq_event != NULL) 79 + if (wq_event_pending != NULL) 79 80 { 80 - pthread_setspecific(__PTK_DARLING_WQ_KEVENT_KEY, NULL); 81 - memmove(wq_event->events, keventlist, nkevents * sizeof(struct kevent_qos_s)); 82 - wq_event->nevents = nkevents; 81 + int* sem; 82 + if (nkevents > 0) 83 + memmove(wq_event_pending->events, keventlist, nkevents * sizeof(struct kevent_qos_s)); 84 + wq_event_pending->nevents = nkevents; 83 85 84 - sem_up(&wq_event->sem); 86 + sem = &wq_event_pending->sem; 87 + wq_event_pending = NULL; 88 + sem_up(sem); 85 89 } 90 + else 91 + __simple_printf("wq_event is NULL, something is going to get stuck forever\n"); 86 92 } 87 93 case WQOPS_THREAD_RETURN: 88 94 { ··· 129 135 } 130 136 wakeup: 131 137 132 - // __simple_printf("Thread %d woken up\n", my_id); 133 - 134 138 // reset stack and call entry point again with WQ_FLAG_THREAD_REUSE 135 139 thread_self = thread_self_trap(); 136 140 stack = __darling_thread_get_stack(); 137 141 142 + // __simple_printf("Thread %d woken up\n", thread_self); 143 + 144 + if (me.event) 145 + wq_event_pending = me.event; 138 146 #ifdef __x86_64__ 139 147 __asm__ __volatile__ ( 140 148 "movq %%rbx, %%r8\n" // 5th argument 149 + "movl %5, %%r9d\n" // 6th argument 141 150 "movq %0, %%rsp\n" 142 151 "movq %%rsp, %%rdx\n" // 3rd argument 143 152 "xorq %%rcx, %%rcx\n" // 4th argument 144 153 "subq $32, %%rsp\n" 145 154 "jmpq *%2\n" 146 155 :: "D" (stack), "S" (thread_self), "a" (wqueue_entry_point), 147 - "b" (me.prio | WQ_FLAG_THREAD_REUSE | WQ_FLAG_THREAD_NEWSPI) 156 + "b" (me.flags | WQ_FLAG_THREAD_REUSE), "c" (me.event ? me.event->events : NULL), 157 + "r" (me.event ? me.event->nevents : 0) 148 158 ); 149 159 #elif defined(__i386__) 150 - // Arguments are in eax, ebx, ecx, edx, edi 160 + // Arguments are in eax, ebx, ecx, edx, edi, esi 151 161 __asm__ __volatile__ ( 152 162 "movl %0, %%esp\n" 153 163 "movl %0, %%ecx\n" ··· 155 165 "subl $32, %%esp\n" 156 166 "jmpl *%2\n" 157 167 :: "a" (stack), "b" (thread_self), "S" (wqueue_entry_point), 158 - "D" (me.prio | WQ_FLAG_THREAD_REUSE | WQ_FLAG_THREAD_NEWSPI) 168 + "D" (me.flags | WQ_FLAG_THREAD_REUSE), "d" (me.event ? me.event->events : NULL), 169 + "S" (me.event ? me.event->nevents : 0) 159 170 ); 160 171 #else 161 172 # error Missing assembly! ··· 169 180 case WQOPS_QUEUE_REQTHREAD_FOR_KEVENT: 170 181 { 171 182 wq_event = (struct wq_kevent_data*) item; 172 - pthread_setspecific(__PTK_DARLING_WQ_KEVENT_KEY, wq_event); 183 + affinity = 1; 173 184 } 174 185 case WQOPS_QUEUE_REQTHREADS2: // with prop bucket 175 186 case WQOPS_QUEUE_REQTHREADS: ··· 201 212 202 213 // Resume an existing thread 203 214 // __simple_printf("Resuming thread %d\n", id); 204 - 205 - thread->prio = prio & WQ_FLAG_THREAD_PRIOMASK; 206 - thread->prio |= prio & WQ_FLAG_THREAD_OVERCOMMIT; 215 + 216 + //thread->prio = prio & WQ_FLAG_THREAD_PRIOMASK; 217 + //thread->prio |= prio & WQ_FLAG_THREAD_OVERCOMMIT; 218 + thread->flags = flags; 219 + thread->event = wq_event; 207 220 208 221 // Dequeue 209 222 list_remove(&workq_parked_head, thread); ··· 217 230 218 231 sem_up(&workq_parked_lock); 219 232 220 - // __simple_printf("Spawning a new thread\n"); 233 + // __simple_printf("Spawning a new thread, nevents=%d\n", (wq_event != NULL) ? wq_event->nevents : -1); 234 + wq_event_pending = wq_event; 235 + 221 236 ret = __darling_thread_create(512*1024, pthread_obj_size, wqueue_entry_point, 0, 222 237 (wq_event != NULL) ? wq_event->events : NULL, flags, 223 238 (wq_event != NULL) ? wq_event->nevents : 0,
+8 -7
src/kernel/emulation/linux/bsdthread/workq_kernreturn.h
··· 6 6 // Darling specific 7 7 #define WQOPS_QUEUE_REQTHREAD_FOR_KEVENT 0x100020 8 8 9 - struct parked_thread 10 - { 11 - struct parked_thread *prev, *next; 12 - int sem, prio; 13 - }; 14 - struct timespec; 15 - 16 9 struct wq_kevent_data 17 10 { 18 11 struct kevent_qos_s* events; 19 12 int nevents; 20 13 int sem; 21 14 }; 15 + 16 + struct parked_thread 17 + { 18 + struct parked_thread *prev, *next; 19 + int sem, flags; 20 + struct wq_kevent_data* event; 21 + }; 22 + struct timespec; 22 23 23 24 long sys_workq_kernreturn(int options, void* item, int affinity, int prio); 24 25
+20 -14
src/kernel/emulation/linux/kqueue/kevent_qos.c
··· 29 29 if ((kq == -1) != !!(flags & KEVENT_FLAG_WORKQ)) 30 30 return -EINVAL; 31 31 32 - if (kq != -1) 33 - { 34 - __simple_printf("Dunno how to handle kevent_qos with a valid kq number\n"); 35 - return -ENOTSUP; 36 - } 37 - 38 32 if (default_kq == -1) 39 33 { 40 34 default_kq = sys_kqueue(); ··· 51 45 } 52 46 if (eventlist != NULL && nevents > 0) 53 47 eventlist64 = (struct kevent64_s*) __builtin_alloca(nevents * sizeof(struct kevent64_s)); 48 + if (nevents == 0 && (flags & KEVENT_FLAG_WORKQ)) 49 + { 50 + eventlist = (struct kevent_qos_s*) __builtin_alloca(nevents * sizeof(struct kevent_qos_s)); 51 + nevents = 1; 52 + eventlist64 = (struct kevent64_s*) __builtin_alloca(nevents * sizeof(struct kevent64_s)); 53 + } 54 54 55 55 rv = kevent64(default_kq, changelist64, nchanges, eventlist64, nevents, flags, NULL); 56 56 ··· 62 62 kevent_64_to_qos(&eventlist64[i], &eventlist[i]); 63 63 } 64 64 65 - // Pass to workqueue and wait 66 - wq_kevent.sem = 0; 67 - wq_kevent.events = eventlist; 68 - wq_kevent.nevents = rv; 65 + if (flags & KEVENT_FLAG_WORKQ) 66 + { 67 + // Pass to workqueue and wait 68 + wq_kevent.sem = 0; 69 + wq_kevent.events = eventlist; 70 + wq_kevent.nevents = rv; 69 71 70 - sys_workq_kernreturn(WQOPS_QUEUE_REQTHREAD_FOR_KEVENT, &wq_kevent, 1, 0); 71 - sem_down(&wq_kevent.sem, -1); 72 + sys_workq_kernreturn(WQOPS_QUEUE_REQTHREAD_FOR_KEVENT, &wq_kevent, 1, 0); 73 + 74 + // __simple_printf("waiting for workq processing\n"); 75 + sem_down(&wq_kevent.sem, -1); 72 76 73 - rv = wq_kevent.nevents; 74 - memmove(eventlist, wq_kevent.events, rv * sizeof(struct kevent_qos_s)); 77 + rv = wq_kevent.nevents; 78 + memmove(eventlist, wq_kevent.events, rv * sizeof(struct kevent_qos_s)); 79 + // __simple_printf("workq done processing, returning %d to caller\n", rv); 80 + } 75 81 76 82 return rv; 77 83 }
+15
src/startup/threads.c
··· 24 24 #include <string.h> 25 25 #include <stdbool.h> 26 26 #include <stdlib.h> 27 + #include <signal.h> 28 + #include <unistd.h> 29 + #include <sys/syscall.h> 27 30 28 31 // The point of this file is build macOS threads on top of native libc's threads, 29 32 // otherwise it would not be possible to make native calls from these threads. ··· 162 165 int __darling_thread_terminate(void* stackaddr, 163 166 unsigned long freesize, unsigned long pthobj_size) 164 167 { 168 + if (getpid() == syscall(SYS_gettid)) 169 + { 170 + // dispatch_main() calls pthread_exit(NULL) on the main thread, 171 + // which turns the our process into a zombie. 172 + // Let's just hang around forever. 173 + sigset_t mask; 174 + memset(&mask, 0, sizeof(mask)); 175 + 176 + while (1) 177 + sigsuspend(&mask); 178 + } 179 + 165 180 struct reaper_item* item = (struct reaper_item*) malloc(sizeof(struct reaper_item)); 166 181 item->thread = pthread_self(); 167 182 item->stack = stackaddr;