+static void pth_thread_exited(struct uthread *uth)
+{
+ struct pthread_tcb *pthread = (struct pthread_tcb*)uth;
+
+ __pthread_generic_yield(pthread);
+ /* Catch some bugs */
+ pthread->state = PTH_EXITING;
+ /* Destroy the pthread */
+ uthread_cleanup(uth);
+ /* Cleanup, mirroring pthread_create() */
+ __pthread_free_stack(pthread);
+ /* If we were the last pthread, we exit for the whole process. Keep in
+ * mind that thread0 is counted in this, so this will only happen if
+ * that thread calls pthread_exit(). */
+ if ((atomic_fetch_and_add(&threads_total, -1) == 1))
+ exit(0);
+}
+
+/* Careful, if someone used the pthread_need_tls() hack to turn off TLS, it will
+ * also be turned off for these threads. */
+static struct uthread *pth_thread_create(void *(*func)(void *), void *arg)
+{
+ struct pthread_tcb *pth;
+ int ret;
+
+ ret = pthread_create(&pth, NULL, func, arg);
+ return ret == 0 ? (struct uthread*)pth : NULL;
+}
+
+/* Careful, that fake_uctx takes up a lot of stack space. We could call
+ * pthread_kill too. Note the VMM 2LS has similar code. */
+static void pth_got_posix_signal(int sig_nr, struct siginfo *info)
+{
+ struct user_context fake_uctx;
+
+ /* If we happen to have a current uthread, we can use that - perhaps
+ * that's what the user wants. If not, we'll build a fake one
+ * representing our current call stack. */
+ if (current_uthread) {
+ trigger_posix_signal(sig_nr, info, get_cur_uth_ctx());
+ } else {
+ init_user_ctx(&fake_uctx, (uintptr_t)pth_got_posix_signal,
+ get_stack_pointer());
+ trigger_posix_signal(sig_nr, info, &fake_uctx);
+ }
+}
+
+static void pth_thread_bulk_runnable(uth_sync_t *wakees)
+{
+ struct uthread *uth_i;
+ struct pthread_tcb *pth_i;
+
+ /* Amortize the lock grabbing over all restartees */
+ mcs_pdr_lock(&queue_lock);
+ while ((uth_i = __uth_sync_get_next(wakees))) {
+ pth_i = (struct pthread_tcb*)uth_i;
+ pth_i->state = PTH_RUNNABLE;
+ TAILQ_INSERT_TAIL(&ready_queue, pth_i, tq_next);
+ threads_ready++;
+ }
+ mcs_pdr_unlock(&queue_lock);
+ vcore_request_more(threads_ready);
+}
+