- struct thread_info *cur = getCurThread();
- if (cur == &MainThread)
- // Permit irqs to fire
- check_irqs32();
-
- // Switch to the next thread
- struct thread_info *next = cur->next;
- asm volatile(
- " pushl $1f\n" // store return pc
- " pushl %%ebp\n" // backup %ebp
- " movl %%esp, 4(%%eax)\n" // cur->stackpos = %esp
- " movl 4(%%ecx), %%esp\n" // %esp = next->stackpos
- " popl %%ebp\n" // restore %ebp
- " retl\n" // restore pc
- "1:\n"
- : "+a"(cur), "+c"(next)
- :
- : "ebx", "edx", "esi", "edi", "cc", "memory");
-}
-
-// Last thing called from a thread (called on "next" stack).
-static void
-__end_thread(struct thread_info *old)
-{
- struct thread_info *pos = &MainThread;
- while (pos->next != old)
- pos = pos->next;
- pos->next = old->next;
- free(old);
- dprintf(2, "=========== end thread %p\n", old);
-}
-
-void
-run_thread(void (*func)(void*), void *data)
-{
- ASSERT32();
- if (! CONFIG_THREADS)
- goto fail;
- struct thread_info *thread;
- thread = memalign_tmphigh(THREADSTACKSIZE, THREADSTACKSIZE);
- if (!thread)
- goto fail;
-
- thread->stackpos = (void*)thread + THREADSTACKSIZE;
- struct thread_info *cur = getCurThread();
- thread->next = cur->next;
- cur->next = thread;
-
- dprintf(2, "=========== start thread %p\n", thread);
- asm volatile(
- // Start thread
- " pushl $1f\n" // store return pc
- " pushl %%ebp\n" // backup %ebp
- " movl %%esp, 4(%%edx)\n" // cur->stackpos = %esp
- " movl 4(%%ebx), %%esp\n" // %esp = thread->stackpos
- " calll *%%ecx\n" // Call func
-
- // End thread
- " movl (%%ebx), %%ecx\n" // %ecx = thread->next
- " movl 4(%%ecx), %%esp\n" // %esp = next->stackpos
- " movl %%ebx, %%eax\n"
- " calll %4\n" // call __end_thread(thread)
- " popl %%ebp\n" // restore %ebp
- " retl\n" // restore pc
- "1:\n"
- : "+a"(data), "+c"(func), "+b"(thread), "+d"(cur)
- : "m"(*(u8*)__end_thread)
- : "esi", "edi", "cc", "memory");
- return;
-
-fail:
- func(data);
-}
-
-void
-wait_threads()
-{
- ASSERT32();
- if (! CONFIG_THREADS)
- return;
- while (MainThread.next != &MainThread)
- yield();