parlib: Add uthread_sched_yield()
[akaros.git] / user / pthread / pthread.c
1 #include <ros/trapframe.h>
2 #include "pthread.h"
3 #include <parlib/vcore.h>
4 #include <parlib/mcs.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <parlib/assert.h>
8 #include <stdio.h>
9 #include <errno.h>
10 #include <parlib/parlib.h>
11 #include <ros/event.h>
12 #include <parlib/arch/atomic.h>
13 #include <parlib/arch/arch.h>
14 #include <sys/queue.h>
15 #include <sys/mman.h>
16 #include <parlib/event.h>
17 #include <parlib/ucq.h>
18 #include <parlib/signal.h>
19 #include <parlib/arch/trap.h>
20
21 struct pthread_queue ready_queue = TAILQ_HEAD_INITIALIZER(ready_queue);
22 struct pthread_queue active_queue = TAILQ_HEAD_INITIALIZER(active_queue);
23 struct mcs_pdr_lock queue_lock;
24 int threads_ready = 0;
25 int threads_active = 0;
26 atomic_t threads_total;
27 bool need_tls = TRUE;
28
29 /* Array of per-vcore structs to manage waiting on syscalls and handling
30  * overflow.  Init'd in pth_init(). */
31 struct sysc_mgmt *sysc_mgmt = 0;
32
33 /* Helper / local functions */
34 static int get_next_pid(void);
35 static inline void spin_to_sleep(unsigned int spins, unsigned int *spun);
36 static inline void pthread_exit_no_cleanup(void *ret);
37
38 /* Pthread 2LS operations */
39 static void pth_sched_entry(void);
40 static void pth_thread_runnable(struct uthread *uthread);
41 static void pth_thread_paused(struct uthread *uthread);
42 static void pth_thread_blockon_sysc(struct uthread *uthread, void *sysc);
43 static void pth_thread_has_blocked(struct uthread *uthread, uth_sync_t sync_obj,
44                                    int flags);
45 static void pth_thread_refl_fault(struct uthread *uth,
46                                   struct user_context *ctx);
47 static void pth_thread_exited(struct uthread *uth);
48 static struct uthread *pth_thread_create(void *(*func)(void *), void *arg);
49
50 /* Event Handlers */
51 static void pth_handle_syscall(struct event_msg *ev_msg, unsigned int ev_type,
52                                void *data);
53
54 struct schedule_ops pthread_sched_ops = {
55         .sched_entry = pth_sched_entry,
56         .thread_runnable = pth_thread_runnable,
57         .thread_paused = pth_thread_paused,
58         .thread_blockon_sysc = pth_thread_blockon_sysc,
59         .thread_has_blocked = pth_thread_has_blocked,
60         .thread_refl_fault = pth_thread_refl_fault,
61         .thread_exited = pth_thread_exited,
62         .thread_create = pth_thread_create,
63 };
64
65 /* Static helpers */
66 static void __pthread_free_stack(struct pthread_tcb *pt);
67 static int __pthread_allocate_stack(struct pthread_tcb *pt);
68 static void __pth_yield_cb(struct uthread *uthread, void *junk);
69
70 /* Called from vcore entry.  Options usually include restarting whoever was
71  * running there before or running a new thread.  Events are handled out of
72  * event.c (table of function pointers, stuff like that). */
73 static void __attribute__((noreturn)) pth_sched_entry(void)
74 {
75         uint32_t vcoreid = vcore_id();
76         if (current_uthread) {
77                 /* Prep the pthread to run any pending posix signal handlers registered
78          * via pthread_kill once it is restored. */
79                 uthread_prep_pending_signals(current_uthread);
80                 /* Run the thread itself */
81                 run_current_uthread();
82                 assert(0);
83         }
84         /* no one currently running, so lets get someone from the ready queue */
85         struct pthread_tcb *new_thread = NULL;
86         /* Try to get a thread.  If we get one, we'll break out and run it.  If not,
87          * we'll try to yield.  vcore_yield() might return, if we lost a race and
88          * had a new event come in, one that may make us able to get a new_thread */
89         do {
90                 handle_events(vcoreid);
91                 __check_preempt_pending(vcoreid);
92                 mcs_pdr_lock(&queue_lock);
93                 new_thread = TAILQ_FIRST(&ready_queue);
94                 if (new_thread) {
95                         TAILQ_REMOVE(&ready_queue, new_thread, tq_next);
96                         assert(new_thread->state == PTH_RUNNABLE);
97                         new_thread->state = PTH_RUNNING;
98                         TAILQ_INSERT_TAIL(&active_queue, new_thread, tq_next);
99                         threads_active++;
100                         threads_ready--;
101                         mcs_pdr_unlock(&queue_lock);
102                         /* If you see what looks like the same uthread running in multiple
103                          * places, your list might be jacked up.  Turn this on. */
104                         printd("[P] got uthread %08p on vc %d state %08p flags %08p\n",
105                                new_thread, vcoreid,
106                                ((struct uthread*)new_thread)->state,
107                                ((struct uthread*)new_thread)->flags);
108                         break;
109                 }
110                 mcs_pdr_unlock(&queue_lock);
111                 /* no new thread, try to yield */
112                 printd("[P] No threads, vcore %d is yielding\n", vcore_id());
113                 /* TODO: you can imagine having something smarter here, like spin for a
114                  * bit before yielding. */
115                 vcore_yield(FALSE);
116         } while (1);
117         /* Prep the pthread to run any pending posix signal handlers registered
118      * via pthread_kill once it is restored. */
119         uthread_prep_pending_signals((struct uthread*)new_thread);
120         /* Run the thread itself */
121         run_uthread((struct uthread*)new_thread);
122         assert(0);
123 }
124
125 /* Could move this, along with start_routine and arg, into the 2LSs */
126 static void __pthread_run(void)
127 {
128         struct pthread_tcb *me = pthread_self();
129         pthread_exit_no_cleanup(me->start_routine(me->arg));
130 }
131
132 /* GIANT WARNING: if you make any changes to this, also change the broadcast
133  * wakeups (cond var, barrier, etc) */
134 static void pth_thread_runnable(struct uthread *uthread)
135 {
136         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
137         /* At this point, the 2LS can see why the thread blocked and was woken up in
138          * the first place (coupling these things together).  On the yield path, the
139          * 2LS was involved and was able to set the state.  Now when we get the
140          * thread back, we can take a look. */
141         printd("pthread %08p runnable, state was %d\n", pthread, pthread->state);
142         switch (pthread->state) {
143                 case (PTH_CREATED):
144                 case (PTH_BLK_YIELDING):
145                 case (PTH_BLK_SYSC):
146                 case (PTH_BLK_PAUSED):
147                 case (PTH_BLK_MUTEX):
148                         /* can do whatever for each of these cases */
149                         break;
150                 default:
151                         panic("Odd state %d for pthread %08p\n", pthread->state, pthread);
152         }
153         pthread->state = PTH_RUNNABLE;
154         /* Insert the newly created thread into the ready queue of threads.
155          * It will be removed from this queue later when vcore_entry() comes up */
156         mcs_pdr_lock(&queue_lock);
157         /* Again, GIANT WARNING: if you change this, change batch wakeup code */
158         TAILQ_INSERT_TAIL(&ready_queue, pthread, tq_next);
159         threads_ready++;
160         mcs_pdr_unlock(&queue_lock);
161         /* Smarter schedulers should look at the num_vcores() and how much work is
162          * going on to make a decision about how many vcores to request. */
163         vcore_request_more(threads_ready);
164 }
165
166 /* For some reason not under its control, the uthread stopped running (compared
167  * to yield, which was caused by uthread/2LS code).
168  *
169  * The main case for this is if the vcore was preempted or if the vcore it was
170  * running on needed to stop.  You are given a uthread that looks like it took a
171  * notif, and had its context/silly state copied out to the uthread struct.
172  * (copyout_uthread).  Note that this will be called in the context (TLS) of the
173  * vcore that is losing the uthread.  If that vcore is running, it'll be in a
174  * preempt-event handling loop (not in your 2LS code).  If this is a big
175  * problem, I'll change it. */
176 static void pth_thread_paused(struct uthread *uthread)
177 {
178         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
179
180         __pthread_generic_yield(pthread);
181         /* communicate to pth_thread_runnable */
182         pthread->state = PTH_BLK_PAUSED;
183         /* At this point, you could do something clever, like put it at the front of
184          * the runqueue, see if it was holding a lock, do some accounting, or
185          * whatever. */
186         pth_thread_runnable(uthread);
187 }
188
189 /* Restarts a uthread hanging off a syscall.  For the simple pthread case, we
190  * just make it runnable and let the main scheduler code handle it. */
191 static void restart_thread(struct syscall *sysc)
192 {
193         struct uthread *ut_restartee = (struct uthread*)sysc->u_data;
194         /* uthread stuff here: */
195         assert(ut_restartee);
196         assert(((struct pthread_tcb*)ut_restartee)->state == PTH_BLK_SYSC);
197         assert(ut_restartee->sysc == sysc);     /* set in uthread.c */
198         ut_restartee->sysc = 0; /* so we don't 'reblock' on this later */
199         pth_thread_runnable(ut_restartee);
200 }
201
202 /* This handler is usually run in vcore context, though I can imagine it being
203  * called by a uthread in some other threading library. */
204 static void pth_handle_syscall(struct event_msg *ev_msg, unsigned int ev_type,
205                                void *data)
206 {
207         struct syscall *sysc;
208         assert(in_vcore_context());
209         /* if we just got a bit (not a msg), it should be because the process is
210          * still an SCP and hasn't started using the MCP ev_q yet (using the simple
211          * ev_q and glibc's blockon) or because the bit is still set from an old
212          * ev_q (blocking syscalls from before we could enter vcore ctx).  Either
213          * way, just return.  Note that if you screwed up the pth ev_q and made it
214          * NO_MSG, you'll never notice (we used to assert(ev_msg)). */
215         if (!ev_msg)
216                 return;
217         /* It's a bug if we don't have a msg (we're handling a syscall bit-event) */
218         assert(ev_msg);
219         /* Get the sysc from the message and just restart it */
220         sysc = ev_msg->ev_arg3;
221         assert(sysc);
222         restart_thread(sysc);
223 }
224
225 /* This will be called from vcore context, after the current thread has yielded
226  * and is trying to block on sysc.  Need to put it somewhere were we can wake it
227  * up when the sysc is done.  For now, we'll have the kernel send us an event
228  * when the syscall is done. */
229 static void pth_thread_blockon_sysc(struct uthread *uthread, void *syscall)
230 {
231         struct syscall *sysc = (struct syscall*)syscall;
232         int old_flags;
233         uint32_t vcoreid = vcore_id();
234         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
235
236         __pthread_generic_yield(pthread);
237         pthread->state = PTH_BLK_SYSC;
238         /* Set things up so we can wake this thread up later */
239         sysc->u_data = uthread;
240         /* Register our vcore's syscall ev_q to hear about this syscall. */
241         if (!register_evq(sysc, sysc_mgmt[vcoreid].ev_q)) {
242                 /* Lost the race with the call being done.  The kernel won't send the
243                  * event.  Just restart him. */
244                 restart_thread(sysc);
245         }
246         /* GIANT WARNING: do not touch the thread after this point. */
247 }
248
249 static void pth_thread_has_blocked(struct uthread *uthread, uth_sync_t sync_obj,
250                                    int flags)
251 {
252         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
253
254         __pthread_generic_yield(pthread);
255         /* Could imagine doing something with the flags.  For now, we just treat
256          * most externally blocked reasons as 'MUTEX'.  Whatever we do here, we are
257          * mostly communicating to our future selves in pth_thread_runnable(), which
258          * gets called by whoever triggered this callback */
259         switch (flags) {
260         case UTH_EXT_BLK_YIELD:
261                 pthread->state = PTH_BLK_YIELDING;
262                 break;
263         default:
264                 pthread->state = PTH_BLK_MUTEX;
265         };
266         if (sync_obj)
267                 __uth_default_sync_enqueue(uthread, sync_obj);
268 }
269
270 static void __signal_and_restart(struct uthread *uthread,
271                                  int signo, int code, void *addr)
272 {
273         uthread_prep_signal_from_fault(uthread, signo, code, addr);
274         pth_thread_runnable(uthread);
275 }
276
277 static void handle_div_by_zero(struct uthread *uthread, unsigned int err,
278                                unsigned long aux)
279 {
280         __signal_and_restart(uthread, SIGFPE, FPE_INTDIV, (void*)aux);
281 }
282
283 static void handle_gp_fault(struct uthread *uthread, unsigned int err,
284                             unsigned long aux)
285 {
286         __signal_and_restart(uthread, SIGSEGV, SEGV_ACCERR, (void*)aux);
287 }
288
289 static void handle_page_fault(struct uthread *uthread, unsigned int err,
290                               unsigned long aux)
291 {
292         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
293         if (!(err & PF_VMR_BACKED)) {
294                 __signal_and_restart(uthread, SIGSEGV, SEGV_MAPERR, (void*)aux);
295         } else {
296                 syscall_async(&uthread->local_sysc, SYS_populate_va, aux, 1);
297                 __block_uthread_on_async_sysc(uthread);
298         }
299 }
300
301 static void pth_thread_refl_hw_fault(struct uthread *uthread,
302                                      unsigned int trap_nr,
303                                      unsigned int err, unsigned long aux)
304 {
305         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
306
307         __pthread_generic_yield(pthread);
308         pthread->state = PTH_BLK_SYSC;
309
310         switch (trap_nr) {
311         case HW_TRAP_DIV_ZERO:
312                 handle_div_by_zero(uthread, err, aux);
313                 break;
314         case HW_TRAP_GP_FAULT:
315                 handle_gp_fault(uthread, err, aux);
316                 break;
317         case HW_TRAP_PAGE_FAULT:
318                 handle_page_fault(uthread, err, aux);
319                 break;
320         default:
321                 printf("Pthread has unhandled fault: %d, err: %d, aux: %p\n",
322                        trap_nr, err, aux);
323                 /* Note that uthread.c already copied out our ctx into the uth
324                  * struct */
325                 print_user_context(&uthread->u_ctx);
326                 printf("Turn on printx to spew unhandled, malignant trap info\n");
327                 exit(-1);
328         }
329 }
330
331 static void pth_thread_refl_fault(struct uthread *uth,
332                                   struct user_context *ctx)
333 {
334         switch (ctx->type) {
335         case ROS_HW_CTX:
336                 pth_thread_refl_hw_fault(uth, __arch_refl_get_nr(ctx),
337                                          __arch_refl_get_err(ctx),
338                                          __arch_refl_get_aux(ctx));
339                 break;
340         default:
341                 assert(0);
342         }
343 }
344
345 static void pth_thread_exited(struct uthread *uth)
346 {
347         struct pthread_tcb *pthread = (struct pthread_tcb*)uth;
348
349         __pthread_generic_yield(pthread);
350         /* Catch some bugs */
351         pthread->state = PTH_EXITING;
352         /* Destroy the pthread */
353         uthread_cleanup(uth);
354         /* Cleanup, mirroring pthread_create() */
355         __pthread_free_stack(pthread);
356         /* If we were the last pthread, we exit for the whole process.  Keep in mind
357          * that thread0 is counted in this, so this will only happen if that thread
358          * calls pthread_exit(). */
359         if ((atomic_fetch_and_add(&threads_total, -1) == 1))
360                 exit(0);
361 }
362
363 /* Careful, if someone used the pthread_need_tls() hack to turn off TLS, it will
364  * also be turned off for these threads. */
365 static struct uthread *pth_thread_create(void *(*func)(void *), void *arg)
366 {
367         struct pthread_tcb *pth;
368         int ret;
369
370         ret = pthread_create(&pth, NULL, func, arg);
371         return ret == 0 ? (struct uthread*)pth : NULL;
372 }
373
374 /* Akaros pthread extensions / hacks */
375
376 /* Careful using this - glibc and gcc are likely to use TLS without you knowing
377  * it. */
378 void pthread_need_tls(bool need)
379 {
380         need_tls = need;
381 }
382
383 /* Pthread interface stuff and helpers */
384
385 int pthread_attr_init(pthread_attr_t *a)
386 {
387         a->stackaddr = 0;
388         a->stacksize = PTHREAD_STACK_SIZE;
389         a->detachstate = PTHREAD_CREATE_JOINABLE;
390         /* priority and policy should be set by anyone changing inherit. */
391         a->sched_priority = 0;
392         a->sched_policy = 0;
393         a->sched_inherit = PTHREAD_INHERIT_SCHED;
394         return 0;
395 }
396
397 int pthread_attr_destroy(pthread_attr_t *a)
398 {
399         return 0;
400 }
401
402 static void __pthread_free_stack(struct pthread_tcb *pt)
403 {
404         int ret = munmap(pt->stacktop - pt->stacksize, pt->stacksize);
405         assert(!ret);
406 }
407
408 static int __pthread_allocate_stack(struct pthread_tcb *pt)
409 {
410         int force_a_page_fault;
411         assert(pt->stacksize);
412         void* stackbot = mmap(0, pt->stacksize,
413                               PROT_READ|PROT_WRITE|PROT_EXEC,
414                               MAP_ANONYMOUS, -1, 0);
415         if (stackbot == MAP_FAILED)
416                 return -1; // errno set by mmap
417         pt->stacktop = stackbot + pt->stacksize;
418         /* Want the top of the stack populated, but not the rest of the stack;
419          * that'll grow on demand (up to pt->stacksize) */
420         force_a_page_fault = ACCESS_ONCE(*(int*)(pt->stacktop - sizeof(int)));
421         return 0;
422 }
423
424 // Warning, this will reuse numbers eventually
425 static int get_next_pid(void)
426 {
427         static uint32_t next_pid = 0;
428         return next_pid++;
429 }
430
431 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
432 {
433         attr->stacksize = stacksize;
434         return 0;
435 }
436
437 int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
438 {
439         *stacksize = attr->stacksize;
440         return 0;
441 }
442
443 int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
444 {
445         attr->guardsize = guardsize;
446         return 0;
447 }
448
449 int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize)
450 {
451         *guardsize = attr->guardsize;
452         return 0;
453 }
454
455 int pthread_attr_getstack(const pthread_attr_t *__restrict __attr,
456                                                    void **__stackaddr, size_t *__stacksize)
457 {
458         *__stackaddr = __attr->stackaddr;
459         *__stacksize = __attr->stacksize;
460         return 0;
461 }
462
463 int pthread_getattr_np(pthread_t __th, pthread_attr_t *__attr)
464 {
465         struct uthread *uth = (struct uthread*)__th;
466
467         __attr->stackaddr = __th->stacktop - __th->stacksize;
468         __attr->stacksize = __th->stacksize;
469         if (atomic_read(&uth->join_ctl.state) == UTH_JOIN_DETACHED)
470                 __attr->detachstate = PTHREAD_CREATE_DETACHED;
471         else
472                 __attr->detachstate = PTHREAD_CREATE_JOINABLE;
473         return 0;
474 }
475
476 /* Do whatever init you want.  At some point call uthread_2ls_init() and pass it
477  * a uthread representing thread0 (int main()) */
478 void __attribute__((constructor)) pthread_lib_init(void)
479 {
480         uintptr_t mmap_block;
481         struct pthread_tcb *t;
482         int ret;
483
484         /* Only run once, but make sure that uthread_lib_init() has run already. */
485         parlib_init_once_racy(return);
486         uthread_lib_init();
487
488         mcs_pdr_init(&queue_lock);
489         /* Create a pthread_tcb for the main thread */
490         ret = posix_memalign((void**)&t, __alignof__(struct pthread_tcb),
491                              sizeof(struct pthread_tcb));
492         assert(!ret);
493         memset(t, 0, sizeof(struct pthread_tcb));       /* aggressively 0 for bugs */
494         t->id = get_next_pid();
495         t->stacksize = USTACK_NUM_PAGES * PGSIZE;
496         t->stacktop = (void*)USTACKTOP;
497         t->state = PTH_RUNNING;
498         /* implies that sigmasks are longs, which they are. */
499         assert(t->id == 0);
500         t->sched_policy = SCHED_FIFO;
501         t->sched_priority = 0;
502         SLIST_INIT(&t->cr_stack);
503         /* Put the new pthread (thread0) on the active queue */
504         mcs_pdr_lock(&queue_lock);
505         threads_active++;
506         TAILQ_INSERT_TAIL(&active_queue, t, tq_next);
507         mcs_pdr_unlock(&queue_lock);
508         /* Tell the kernel where and how we want to receive events.  This is just an
509          * example of what to do to have a notification turned on.  We're turning on
510          * USER_IPIs, posting events to vcore 0's vcpd, and telling the kernel to
511          * send to vcore 0.  Note sys_self_notify will ignore the vcoreid and
512          * private preference.  Also note that enable_kevent() is just an example,
513          * and you probably want to use parts of event.c to do what you want. */
514         enable_kevent(EV_USER_IPI, 0, EVENT_IPI | EVENT_VCORE_PRIVATE);
515         /* Set up the per-vcore structs to track outstanding syscalls */
516         sysc_mgmt = malloc(sizeof(struct sysc_mgmt) * max_vcores());
517         assert(sysc_mgmt);
518 #if 1   /* Independent ev_mboxes per vcore */
519         /* Get a block of pages for our per-vcore (but non-VCPD) ev_qs */
520         mmap_block = (uintptr_t)mmap(0, PGSIZE * 2 * max_vcores(),
521                                      PROT_WRITE | PROT_READ,
522                                      MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
523         assert(mmap_block);
524         /* Could be smarter and do this on demand (in case we don't actually want
525          * max_vcores()). */
526         for (int i = 0; i < max_vcores(); i++) {
527                 /* Each vcore needs to point to a non-VCPD ev_q */
528                 sysc_mgmt[i].ev_q = get_eventq_raw();
529                 sysc_mgmt[i].ev_q->ev_flags = EVENT_IPI | EVENT_INDIR |
530                                               EVENT_SPAM_INDIR | EVENT_WAKEUP;
531                 sysc_mgmt[i].ev_q->ev_vcore = i;
532                 sysc_mgmt[i].ev_q->ev_mbox->type = EV_MBOX_UCQ;
533                 ucq_init_raw(&sysc_mgmt[i].ev_q->ev_mbox->ucq,
534                              mmap_block + (2 * i    ) * PGSIZE, 
535                              mmap_block + (2 * i + 1) * PGSIZE); 
536         }
537         /* Technically, we should munmap and free what we've alloc'd, but the
538          * kernel will clean it up for us when we exit. */
539 #endif 
540 #if 0   /* One global ev_mbox, separate ev_q per vcore */
541         struct event_mbox *sysc_mbox = malloc(sizeof(struct event_mbox));
542         uintptr_t two_pages = (uintptr_t)mmap(0, PGSIZE * 2, PROT_WRITE | PROT_READ,
543                                               MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
544         printd("Global ucq: %08p\n", &sysc_mbox->ev_msgs);
545         assert(sysc_mbox);
546         assert(two_pages);
547         memset(sysc_mbox, 0, sizeof(struct event_mbox));
548         sysc_mbox->type = EV_MBOX_UCQ;
549         ucq_init_raw(&sysc_mbox->ucq, two_pages, two_pages + PGSIZE);
550         for (int i = 0; i < max_vcores(); i++) {
551                 sysc_mgmt[i].ev_q = get_eventq_slim();
552                 sysc_mgmt[i].ev_q->ev_flags = EVENT_IPI | EVENT_INDIR |
553                                               EVENT_SPAM_INDIR | EVENT_WAKEUP;
554                 sysc_mgmt[i].ev_q->ev_vcore = i;
555                 sysc_mgmt[i].ev_q->ev_mbox = sysc_mbox;
556         }
557 #endif
558         /* Sched ops is set by 2ls_init */
559         uthread_2ls_init((struct uthread*)t, &pthread_sched_ops, pth_handle_syscall,
560                          NULL);
561         atomic_init(&threads_total, 1);                 /* one for thread0 */
562 }
563
564 /* Make sure our scheduler runs inside an MCP rather than an SCP. */
565 void pthread_mcp_init()
566 {
567         /* Prevent this from happening more than once. */
568         parlib_init_once_racy(return);
569
570         uthread_mcp_init();
571         /* From here forward we are an MCP running on vcore 0. Could consider doing
572          * other pthread specific initialization based on knowing we are an mcp
573          * after this point. */
574 }
575
576 int __pthread_create(pthread_t *thread, const pthread_attr_t *attr,
577                      void *(*start_routine)(void *), void *arg)
578 {
579         struct uth_thread_attr uth_attr = {0};
580         struct pthread_tcb *parent;
581         struct pthread_tcb *pthread;
582         int ret;
583
584         /* For now, unconditionally become an mcp when creating a pthread (if not
585          * one already). This may change in the future once we support 2LSs in an
586          * SCP. */
587         pthread_mcp_init();
588
589         parent = (struct pthread_tcb*)current_uthread;
590         ret = posix_memalign((void**)&pthread, __alignof__(struct pthread_tcb),
591                              sizeof(struct pthread_tcb));
592         assert(!ret);
593         memset(pthread, 0, sizeof(struct pthread_tcb)); /* aggressively 0 for bugs*/
594         pthread->stacksize = PTHREAD_STACK_SIZE;        /* default */
595         pthread->state = PTH_CREATED;
596         pthread->id = get_next_pid();
597         /* Might override these later, based on attr && EXPLICIT_SCHED */
598         pthread->sched_policy = parent->sched_policy;
599         pthread->sched_priority = parent->sched_priority;
600         SLIST_INIT(&pthread->cr_stack);
601         /* Respect the attributes */
602         if (attr) {
603                 if (attr->stacksize)                                    /* don't set a 0 stacksize */
604                         pthread->stacksize = attr->stacksize;
605                 if (attr->detachstate == PTHREAD_CREATE_DETACHED)
606                         uth_attr.detached = TRUE;
607                 if (attr->sched_inherit == PTHREAD_EXPLICIT_SCHED) {
608                         pthread->sched_policy = attr->sched_policy;
609                         pthread->sched_priority = attr->sched_priority;
610                 }
611         }
612         /* allocate a stack */
613         if (__pthread_allocate_stack(pthread))
614                 printf("We're fucked\n");
615         /* Set the u_tf to start up in __pthread_run, which will call the real
616          * start_routine and pass it the arg.  Note those aren't set until later in
617          * pthread_create(). */
618         init_user_ctx(&pthread->uthread.u_ctx, (uintptr_t)&__pthread_run,
619                       (uintptr_t)(pthread->stacktop));
620         pthread->start_routine = start_routine;
621         pthread->arg = arg;
622         /* Initialize the uthread */
623         if (need_tls)
624                 uth_attr.want_tls = TRUE;
625         uthread_init((struct uthread*)pthread, &uth_attr);
626         *thread = pthread;
627         atomic_inc(&threads_total);
628         return 0;
629 }
630
631 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
632                    void *(*start_routine)(void *), void *arg)
633 {
634         if (!__pthread_create(thread, attr, start_routine, arg))
635                 pth_thread_runnable((struct uthread*)*thread);
636         return 0;
637 }
638
639 /* Helper that all pthread-controlled yield paths call.  Just does some
640  * accounting.  This is another example of how the much-loathed (and loved)
641  * active queue is keeping us honest.  Need to export for sem and friends. */
642 void __pthread_generic_yield(struct pthread_tcb *pthread)
643 {
644         mcs_pdr_lock(&queue_lock);
645         threads_active--;
646         TAILQ_REMOVE(&active_queue, pthread, tq_next);
647         mcs_pdr_unlock(&queue_lock);
648 }
649
650 int pthread_join(struct pthread_tcb *join_target, void **retval)
651 {
652         uthread_join((struct uthread*)join_target, retval);
653         return 0;
654 }
655
656 static inline void pthread_exit_no_cleanup(void *ret)
657 {
658         struct pthread_tcb *pthread = pthread_self();
659
660         while (SLIST_FIRST(&pthread->cr_stack))
661                 pthread_cleanup_pop(FALSE);
662         destroy_dtls();
663         uth_2ls_thread_exit(ret);
664 }
665
666 void pthread_exit(void *ret)
667 {
668         struct pthread_tcb *pthread = pthread_self();
669         while (SLIST_FIRST(&pthread->cr_stack))
670                 pthread_cleanup_pop(TRUE);
671         pthread_exit_no_cleanup(ret);
672 }
673
674 /* Cooperative yielding of the processor, to allow other threads to run */
675 int pthread_yield(void)
676 {
677         uthread_sched_yield();
678         return 0;
679 }
680
681 int pthread_cancel(pthread_t __th)
682 {
683         fprintf(stderr, "Unsupported %s!", __FUNCTION__);
684         abort();
685         return -1;
686 }
687
688 void pthread_cleanup_push(void (*routine)(void *), void *arg)
689 {
690         struct pthread_tcb *p = pthread_self();
691         struct pthread_cleanup_routine *r = malloc(sizeof(*r));
692         r->routine = routine;
693         r->arg = arg;
694         SLIST_INSERT_HEAD(&p->cr_stack, r, cr_next);
695 }
696
697 void pthread_cleanup_pop(int execute)
698 {
699         struct pthread_tcb *p = pthread_self();
700         struct pthread_cleanup_routine *r = SLIST_FIRST(&p->cr_stack);
701         if (r) {
702                 SLIST_REMOVE_HEAD(&p->cr_stack, cr_next);
703                 if (execute)
704                         r->routine(r->arg);
705                 free(r);
706         }
707 }
708
709 int pthread_mutexattr_init(pthread_mutexattr_t* attr)
710 {
711   attr->type = PTHREAD_MUTEX_DEFAULT;
712   return 0;
713 }
714
715 int pthread_mutexattr_destroy(pthread_mutexattr_t* attr)
716 {
717   return 0;
718 }
719
720 int pthread_attr_setdetachstate(pthread_attr_t *__attr, int __detachstate)
721 {
722         __attr->detachstate = __detachstate;
723         return 0;
724 }
725
726 int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr, int* type)
727 {
728   *type = attr ? attr->type : PTHREAD_MUTEX_DEFAULT;
729   return 0;
730 }
731
732 int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type)
733 {
734   if(type != PTHREAD_MUTEX_NORMAL)
735     return EINVAL;
736   attr->type = type;
737   return 0;
738 }
739
740 int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t* attr)
741 {
742   m->attr = attr;
743   atomic_init(&m->lock, 0);
744   return 0;
745 }
746
747 /* Helper for spinning sync, returns TRUE if it is okay to keep spinning.
748  *
749  * Alternatives include:
750  *              old_count <= num_vcores() (barrier code, pass in old_count as *state, 
751  *                                         but this only works if every awake pthread
752  *                                         will belong to the barrier).
753  *              just spin for a bit       (use *state to track spins)
754  *              FALSE                     (always is safe)
755  *              etc...
756  * 'threads_ready' isn't too great since sometimes it'll be non-zero when it is
757  * about to become 0.  We really want "I have no threads waiting to run that
758  * aren't going to run on their on unless this core yields instead of spins". */
759 /* TODO: consider making this a 2LS op */
760 static inline bool safe_to_spin(unsigned int *state)
761 {
762         return !threads_ready;
763 }
764
765 /* Set *spun to 0 when calling this the first time.  It will yield after 'spins'
766  * calls.  Use this for adaptive mutexes and such. */
767 static inline void spin_to_sleep(unsigned int spins, unsigned int *spun)
768 {
769         if ((*spun)++ == spins) {
770                 pthread_yield();
771                 *spun = 0;
772         }
773 }
774
775 int pthread_mutex_lock(pthread_mutex_t* m)
776 {
777         unsigned int spinner = 0;
778         while(pthread_mutex_trylock(m))
779                 while(*(volatile size_t*)&m->lock) {
780                         cpu_relax();
781                         spin_to_sleep(PTHREAD_MUTEX_SPINS, &spinner);
782                 }
783         /* normally we'd need a wmb() and a wrmb() after locking, but the
784          * atomic_swap handles the CPU mb(), so just a cmb() is necessary. */
785         cmb();
786         return 0;
787 }
788
789 int pthread_mutex_trylock(pthread_mutex_t* m)
790 {
791   return atomic_swap(&m->lock, 1) == 0 ? 0 : EBUSY;
792 }
793
794 int pthread_mutex_unlock(pthread_mutex_t* m)
795 {
796   /* keep reads and writes inside the protected region */
797   rwmb();
798   wmb();
799   atomic_set(&m->lock, 0);
800   return 0;
801 }
802
803 int pthread_mutex_destroy(pthread_mutex_t* m)
804 {
805   return 0;
806 }
807
808 int pthread_cond_init(pthread_cond_t *c, const pthread_condattr_t *a)
809 {
810         SLIST_INIT(&c->waiters);
811         spin_pdr_init(&c->spdr_lock);
812         if (a) {
813                 c->attr_pshared = a->pshared;
814                 c->attr_clock = a->clock;
815         } else {
816                 c->attr_pshared = PTHREAD_PROCESS_PRIVATE;
817                 c->attr_clock = 0;
818         }
819         return 0;
820 }
821
822 int pthread_cond_destroy(pthread_cond_t *c)
823 {
824         return 0;
825 }
826
827 static void swap_slists(struct pthread_list *a, struct pthread_list *b)
828 {
829         struct pthread_list temp;
830         temp = *a;
831         *a = *b;
832         *b = temp;
833 }
834
835 static void wake_slist(struct pthread_list *to_wake)
836 {
837         unsigned int nr_woken = 0;      /* assuming less than 4 bil threads */
838         struct pthread_tcb *pthread_i, *pth_temp;
839         /* Amortize the lock grabbing over all restartees */
840         mcs_pdr_lock(&queue_lock);
841         /* Do the work of pth_thread_runnable().  We're in uth context here, but I
842          * think it's okay.  When we need to (when locking) we drop into VC ctx, as
843          * far as the kernel and other cores are concerned. */
844         SLIST_FOREACH_SAFE(pthread_i, to_wake, sl_next, pth_temp) {
845                 pthread_i->state = PTH_RUNNABLE;
846                 nr_woken++;
847                 TAILQ_INSERT_TAIL(&ready_queue, pthread_i, tq_next);
848         }
849         threads_ready += nr_woken;
850         mcs_pdr_unlock(&queue_lock);
851         vcore_request_more(threads_ready);
852 }
853
854 int pthread_cond_broadcast(pthread_cond_t *c)
855 {
856         struct pthread_list restartees = SLIST_HEAD_INITIALIZER(restartees);
857         spin_pdr_lock(&c->spdr_lock);
858         swap_slists(&restartees, &c->waiters);
859         spin_pdr_unlock(&c->spdr_lock);
860         wake_slist(&restartees);
861         return 0;
862 }
863
864 /* spec says this needs to work regardless of whether or not it holds the mutex
865  * already. */
866 int pthread_cond_signal(pthread_cond_t *c)
867 {
868         struct pthread_tcb *pthread;
869         spin_pdr_lock(&c->spdr_lock);
870         pthread = SLIST_FIRST(&c->waiters);
871         if (!pthread) {
872                 spin_pdr_unlock(&c->spdr_lock);
873                 return 0;
874         }
875         SLIST_REMOVE_HEAD(&c->waiters, sl_next);
876         spin_pdr_unlock(&c->spdr_lock);
877         pth_thread_runnable((struct uthread*)pthread);
878         return 0;
879 }
880
881 /* Communicate btw cond_wait and its callback */
882 struct cond_junk {
883         pthread_cond_t                          *c;
884         pthread_mutex_t                         *m;
885 };
886
887 /* Callback/bottom half of cond wait.  For those writing these pth callbacks,
888  * the minimum is call generic, set state (communicate with runnable), then do
889  * something that causes it to be runnable in the future (or right now). */
890 static void __pth_wait_cb(struct uthread *uthread, void *junk)
891 {
892         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
893         pthread_cond_t *c = ((struct cond_junk*)junk)->c;
894         pthread_mutex_t *m = ((struct cond_junk*)junk)->m;
895         /* this removes us from the active list; we can reuse next below */
896         __pthread_generic_yield(pthread);
897         pthread->state = PTH_BLK_MUTEX;
898         spin_pdr_lock(&c->spdr_lock);
899         SLIST_INSERT_HEAD(&c->waiters, pthread, sl_next);
900         spin_pdr_unlock(&c->spdr_lock);
901         pthread_mutex_unlock(m);
902 }
903
904 int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
905 {
906         struct cond_junk local_junk;
907         local_junk.c = c;
908         local_junk.m = m;
909         uthread_yield(TRUE, __pth_wait_cb, &local_junk);
910         pthread_mutex_lock(m);
911         return 0;
912 }
913
914 int pthread_condattr_init(pthread_condattr_t *a)
915 {
916         a->pshared = PTHREAD_PROCESS_PRIVATE;
917         a->clock = 0;
918         return 0;
919 }
920
921 int pthread_condattr_destroy(pthread_condattr_t *a)
922 {
923         return 0;
924 }
925
926 int pthread_condattr_getpshared(pthread_condattr_t *a, int *s)
927 {
928         *s = a->pshared;
929         return 0;
930 }
931
932 int pthread_condattr_setpshared(pthread_condattr_t *a, int s)
933 {
934         a->pshared = s;
935         if (s == PTHREAD_PROCESS_SHARED) {
936                 printf("Warning: we don't do shared pthread condvars btw diff MCPs\n");
937                 return -1;
938         }
939         return 0;
940 }
941
942 int pthread_condattr_getclock(const pthread_condattr_t *attr,
943                               clockid_t *clock_id)
944 {
945         *clock_id = attr->clock;
946         return 0;
947 }
948
949 int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id)
950 {
951         printf("Warning: we don't do pthread condvar clock stuff\n");
952         attr->clock = clock_id;
953         return 0;
954 }
955
956 pthread_t pthread_self()
957 {
958   return (struct pthread_tcb*)current_uthread;
959 }
960
961 int pthread_equal(pthread_t t1, pthread_t t2)
962 {
963   return t1 == t2;
964 }
965
966 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
967 {
968         /* pthread_once's init routine doesn't take an argument, like parlibs.  This
969          * means the func will be run with an argument passed to it, but it'll be
970          * ignored. */
971         parlib_run_once(once_control, (void (*)(void *))init_routine, NULL);
972         /* The return for pthread_once isn't an error from the function, it's just
973          * an overall error.  Note pthread's init_routine() has no return value. */
974         return 0;
975 }
976
977 int pthread_barrier_init(pthread_barrier_t *b,
978                          const pthread_barrierattr_t *a, int count)
979 {
980         b->total_threads = count;
981         b->sense = 0;
982         atomic_set(&b->count, count);
983         spin_pdr_init(&b->lock);
984         SLIST_INIT(&b->waiters);
985         b->nr_waiters = 0;
986         return 0;
987 }
988
989 struct barrier_junk {
990         pthread_barrier_t                               *b;
991         int                                                             ls;
992 };
993
994 /* Callback/bottom half of barrier. */
995 static void __pth_barrier_cb(struct uthread *uthread, void *junk)
996 {
997         struct pthread_tcb *pthread = (struct pthread_tcb*)uthread;
998         pthread_barrier_t *b = ((struct barrier_junk*)junk)->b;
999         int ls = ((struct barrier_junk*)junk)->ls;
1000         /* Removes from active list, we can reuse.  must also restart */
1001         __pthread_generic_yield(pthread);
1002         /* TODO: if we used a trylock, we could bail as soon as we see sense */
1003         spin_pdr_lock(&b->lock);
1004         /* If sense is ls (our free value), we lost the race and shouldn't sleep */
1005         if (b->sense == ls) {
1006                 /* TODO: i'd like to fast-path the wakeup, skipping pth_runnable */
1007                 pthread->state = PTH_BLK_YIELDING;      /* not sure which state for this */
1008                 spin_pdr_unlock(&b->lock);
1009                 pth_thread_runnable(uthread);
1010                 return;
1011         }
1012         /* otherwise, we sleep */
1013         pthread->state = PTH_BLK_MUTEX; /* TODO: consider ignoring this */
1014         SLIST_INSERT_HEAD(&b->waiters, pthread, sl_next);
1015         b->nr_waiters++;
1016         spin_pdr_unlock(&b->lock);
1017 }
1018
1019 /* We assume that the same threads participating in the barrier this time will
1020  * also participate next time.  Imagine a thread stopped right after its fetch
1021  * and add - we know it is coming through eventually.  We finish and change the
1022  * sense, which should allow the delayed thread to eventually break through.
1023  * But if another n threads come in first, we'll set the sense back to the old
1024  * value, thereby catching the delayed thread til the next barrier. 
1025  *
1026  * A note on preemption: if any thread gets preempted and it is never dealt
1027  * with, eventually we deadlock, with all threads waiting on the last one to
1028  * enter (and any stragglers from one run will be the last in the next run).
1029  * One way or another, we need to handle preemptions.  The current 2LS requests
1030  * an IPI for a preempt, so we'll be fine.  Any other strategies will need to
1031  * consider how barriers work.  Any time we sleep, we'll be okay (since that
1032  * frees up our core to handle preemptions/run other threads. */
1033 int pthread_barrier_wait(pthread_barrier_t *b)
1034 {
1035         unsigned int spin_state = 0;
1036         int ls = !b->sense;     /* when b->sense is the value we read, then we're free*/
1037         struct pthread_list restartees = SLIST_HEAD_INITIALIZER(restartees);
1038         struct pthread_tcb *pthread_i;
1039         struct barrier_junk local_junk;
1040         
1041         long old_count = atomic_fetch_and_add(&b->count, -1);
1042
1043         if (old_count == 1) {
1044                 printd("Thread %d is last to hit the barrier, resetting...\n",
1045                        pthread_self()->id);
1046                 /* TODO: we might want to grab the lock right away, so a few short
1047                  * circuit faster? */
1048                 atomic_set(&b->count, b->total_threads);
1049                 /* we still need to maintain ordering btw count and sense, in case
1050                  * another thread doesn't sleep (if we wrote sense first, they could
1051                  * break out, race around, and muck with count before it is time) */
1052                 /* wmb(); handled by the spin lock */
1053                 spin_pdr_lock(&b->lock);
1054                 /* Sense is only protected in addition to decisions to sleep */
1055                 b->sense = ls;  /* set to free everyone */
1056                 /* All access to nr_waiters is protected by the lock */
1057                 if (!b->nr_waiters) {
1058                         spin_pdr_unlock(&b->lock);
1059                         return PTHREAD_BARRIER_SERIAL_THREAD;
1060                 }
1061                 swap_slists(&restartees, &b->waiters);
1062                 b->nr_waiters = 0;
1063                 spin_pdr_unlock(&b->lock);
1064                 wake_slist(&restartees);
1065                 return PTHREAD_BARRIER_SERIAL_THREAD;
1066         } else {
1067                 /* Spin if there are no other threads to run.  No sense sleeping */
1068                 do {
1069                         if (b->sense == ls)
1070                                 return 0;
1071                         cpu_relax();
1072                 } while (safe_to_spin(&spin_state));
1073
1074                 /* Try to sleep, when we wake/return, we're free to go */
1075                 local_junk.b = b;
1076                 local_junk.ls = ls;
1077                 uthread_yield(TRUE, __pth_barrier_cb, &local_junk);
1078                 // assert(b->sense == ls);
1079                 return 0;
1080         }
1081 }
1082
1083 int pthread_barrier_destroy(pthread_barrier_t *b)
1084 {
1085         assert(SLIST_EMPTY(&b->waiters));
1086         assert(!b->nr_waiters);
1087         /* Free any locks (if we end up using an MCS) */
1088         return 0;
1089 }
1090
1091 int pthread_detach(pthread_t thread)
1092 {
1093         uthread_detach((struct uthread*)thread);
1094         return 0;
1095 }
1096
1097 int pthread_kill(pthread_t thread, int signo)
1098 {
1099         return uthread_signal(&thread->uthread, signo);
1100 }
1101
1102 int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
1103 {
1104         int ret = sigprocmask(how, set, oset);
1105
1106         /* Ensures any pending signals we just unmasked get processed. */
1107         if (set && ret == 0)
1108                 pthread_yield();
1109         return ret;
1110 }
1111
1112 int pthread_sigqueue(pthread_t *thread, int sig, const union sigval value)
1113 {
1114         printf("pthread_sigqueue is not yet implemented!");
1115         return -1;
1116 }
1117
1118 int pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
1119 {
1120         *key = dtls_key_create(destructor);
1121         assert(key);
1122         return 0;
1123 }
1124
1125 int pthread_key_delete(pthread_key_t key)
1126 {
1127         dtls_key_delete(key);
1128         return 0;
1129 }
1130
1131 void *pthread_getspecific(pthread_key_t key)
1132 {
1133         return get_dtls(key);
1134 }
1135
1136 int pthread_setspecific(pthread_key_t key, const void *value)
1137 {
1138         set_dtls(key, (void*)value);
1139         return 0;
1140 }
1141
1142
1143 /* Scheduling Stuff */
1144
1145 static bool policy_is_supported(int policy)
1146 {
1147         /* As our scheduler changes, we can add more policies here */
1148         switch (policy) {
1149                 case SCHED_FIFO:
1150                         return TRUE;
1151                 default:
1152                         return FALSE;
1153         }
1154 }
1155
1156 int pthread_attr_setschedparam(pthread_attr_t *attr,
1157                                const struct sched_param *param)
1158 {
1159         /* The set of acceptable priorities are based on the scheduling policy.
1160          * We'll just accept any old number, since we might not know the policy
1161          * yet.  I didn't see anything in the man pages saying attr had to have a
1162          * policy set before setting priority. */
1163         attr->sched_priority = param->sched_priority;
1164         return 0;
1165 }
1166
1167 int pthread_attr_getschedparam(pthread_attr_t *attr,
1168                                struct sched_param *param)
1169 {
1170         param->sched_priority = attr->sched_priority;
1171         return 0;
1172 }
1173
1174 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
1175 {
1176         if (!policy_is_supported(policy))
1177                 return -EINVAL;
1178         attr->sched_policy = policy;
1179         return 0;
1180 }
1181
1182 int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy)
1183 {
1184         *policy = attr->sched_policy;
1185         return 0;
1186 }
1187
1188 /* We only support SCOPE_PROCESS, so we don't even use the attr. */
1189 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
1190 {
1191         if (scope != PTHREAD_SCOPE_PROCESS)
1192                 return -ENOTSUP;
1193         return 0;
1194 }
1195
1196 int pthread_attr_getscope(pthread_attr_t *attr, int *scope)
1197 {
1198         *scope = PTHREAD_SCOPE_PROCESS;
1199         return 0;
1200 }
1201
1202 /* Inheritance refers to policy, priority, scope */
1203 int pthread_attr_setinheritsched(pthread_attr_t *attr,
1204                                  int inheritsched)
1205 {
1206         switch (inheritsched) {
1207                 case PTHREAD_INHERIT_SCHED:
1208                 case PTHREAD_EXPLICIT_SCHED:
1209                         break;
1210                 default:
1211                         return -EINVAL;
1212         }
1213         attr->sched_inherit = inheritsched;
1214         return 0;
1215 }
1216
1217 int pthread_attr_getinheritsched(const pthread_attr_t *attr,
1218                                  int *inheritsched)
1219 {
1220         *inheritsched = attr->sched_inherit;
1221         return 0;
1222 }
1223
1224 int pthread_setschedparam(pthread_t thread, int policy,
1225                            const struct sched_param *param)
1226 {
1227         if (!policy_is_supported(policy))
1228                 return -EINVAL;
1229         thread->sched_policy = policy;
1230         /* We actually could check if the priority falls in the range of the
1231          * specified policy here, since we have both policy and priority. */
1232         thread->sched_priority = param->sched_priority;
1233         return 0;
1234 }
1235
1236 int pthread_getschedparam(pthread_t thread, int *policy,
1237                            struct sched_param *param)
1238 {
1239         *policy = thread->sched_policy;
1240         param->sched_priority = thread->sched_priority;
1241         return 0;
1242 }
1243
1244
1245 /* Unsupported Stuff */
1246
1247 int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
1248                                         const struct timespec *__restrict
1249                                         __abstime)
1250 {
1251         fprintf(stderr, "Unsupported %s!", __FUNCTION__);
1252         abort();
1253         return -1;
1254 }
1255
1256 int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
1257                                    pthread_mutex_t *__restrict __mutex,
1258                                    const struct timespec *__restrict __abstime)
1259 {
1260         fprintf(stderr, "Unsupported %s!", __FUNCTION__);
1261         abort();
1262         return -1;
1263 }