📄 bjthread.c
字号:
*/void jthread_enable_stop(void){ jthread_t currentJThread = GET_JTHREAD(); if (NULL != currentJThread) { atomic_or(¤tJThread->stop_allowed, 1); if (currentJThread->stop_pending) { currentJThread->status = THREAD_DYING; onstop(); jthread_exit(); } }}/* * interrupt a thread */voidjthread_interrupt(jthread_t tid){ thread_info tinfo; DBG(JTHREAD, dprintf("interrupting thread %p, %s\n", tid, THREAD_NAME(tid));) if (THREAD_DYING != tid->status && THREAD_DEAD != tid->status) { get_thread_info(tid->native_thread, &tinfo); if (B_THREAD_SUSPENDED != tinfo.state && B_THREAD_RUNNING != tinfo.state) { /* * This thread is asleep, waiting on I/O or * blocked on a semaphore, so resume_thread won't * work without a preceding suspend_thread, and * since these amount to signalling the targeted * thread, we need to snooze a bit, as described * in the Be Book section on the "snooze" function. */ suspend_thread(tid->native_thread); snooze(1000); /* microseconds */ } /* * At this point, the targeted thread is either already * running, or is in a resumable state. */ resume_thread(tid->native_thread); }}/* * cleanup handler for a given thread. This handler is called when that * thread is killed (i.e., when it receives a STOP_SIGNAL). */static voiddeathcallback(int sig){ jthread_t currentJThread = GET_JTHREAD(); atomic_or(¤tJThread->stop_pending, 1); if (0 == atomic_or(¤tJThread->stop_allowed, 0)) { DBG(JTHREAD, dprintf("%s rejects the STOP request", THREAD_NAME(currentJThread));) return; } currentJThread->status = THREAD_DYING; onstop(); mark_thread_dead(); /* by returning, we proceed with the STOP and exit that thread */}/* * start function for each thread. * This function install the cleanup handler, sets jthread-specific * data and calls the actual work function. */int32start_me_up(void *arg){ jthread_t tid = (jthread_t)arg; thread_info tinfo; extern void initExceptions(void); DBG(JTHREAD, dprintf("start_me_up: setting up for %s\n", THREAD_NAME(tid));) acquire_sem(threadLock); /* GROSS HACK ALERT -- On R4, child threads don't inherit the * spawning thread's signal handlers! */ initExceptions(); /* from ../../exceptions.c */ /* END OF GROSS HACK */ signal(STOP_SIGNAL, deathcallback); tid->stop_allowed = 1; tid->stop_pending = 0; /* * Determine the top and bottom addrs of this thread's stack */ get_thread_info(tid->native_thread, &tinfo); tid->stack_top = tinfo.stack_end; tid->stack_bottom = tinfo.stack_base; SET_JTHREAD(tid); SET_COOKIE(tid->jlThread); tid->status = THREAD_RUNNING; release_sem(threadLock); DBG(JTHREAD, dprintf("start_me_up: calling t-func for %s\n", THREAD_NAME(tid));) tid->func(tid->jlThread); DBG(JTHREAD, dprintf("start_me_up: thread %s returned\n", THREAD_NAME(tid));) assert (tid->status != THREAD_DYING); mark_thread_dead(); /* by returning, we exit this thread */ return (0);}/* * create a new jthread */jthread_tjthread_create(unsigned int pri, void (*func)(void *), int daemon, void *jlThread, size_t threadStackSize){ thread_id ntid; jthread_t tid; /* * Note that we create the thread in a joinable state, which is the * default. Our finalizer will join the threads, allowing the * thread system to free its resources. */ tid = allocator(sizeof(*tid)); assert(tid != 0); acquire_sem(threadLock); tid->jlThread = jlThread; tid->func = func; tid->nextlive = liveThreads; liveThreads = tid; tid->status = THREAD_NEWBORN; ntid = spawn_thread(start_me_up, nameThread(jlThread), map_Java_priority(pri), tid); tid->native_thread = ntid; talive++; if ((tid->daemon = daemon) != 0) { tdaemon++; } release_sem(threadLock); /* Check if we can safely save the per-thread info for * this thread. Yes, I know the per-thread stuff is lame, * but let's get this working first, shall we? */ if (NULL == per_thread_info[ntid % MAX_THREADS].jtid) { DBG(JTHREAD, dprintf("created thread %s, daemon=%d\n", nameThread(jlThread), daemon);) resume_thread(ntid); return (tid); } else { DBG(JTHREAD, dprintf("can't create thread: " "per-thread info table too small\n");) kill_thread(ntid); /* stillborn */ deallocator(tid); return NULL; }}/*============================================================================ * * Functions that are part of the user interface * *//* * sleep for time milliseconds */ voidjthread_sleep(jlong time){ DBG(JTHREAD, dprintf("thread %s: sleeping for %g second(s)...", THREAD_NAME(GET_JTHREAD()), (double)time/1000.0);) /* snooze_until takes an arg in usecs */ snooze_until(system_time() + (time*1000L), B_SYSTEM_TIMEBASE); DBG(JTHREAD, dprintf("OK, I'm awake!\n");)}/* * Check whether a thread is alive. * * Note that threads executing their cleanup function are not (jthread-) alive. * (they're set to THREAD_DEAD) */intjthread_alive(jthread_t tid){ return tid && (tid->status == THREAD_NEWBORN || tid->status == THREAD_RUNNING);}/* * Change thread priority. */voidjthread_setpriority(jthread_t jtid, int prio){ set_thread_priority(jtid->native_thread, map_Java_priority(prio));}/* * Stop a thread in its tracks. */voidjthread_stop(jthread_t jtid){ /* can I cancel myself safely??? */ /* NB: jthread_stop should never be invoked on the current thread */ DBG(JTHREAD, dprintf("stopping %s...\n", THREAD_NAME(jtid));) send_signal(jtid->native_thread, STOP_SIGNAL);}static voidremove_thread(jthread_t tid){ jthread_t* ntid; int found = 0; DBG(JTHREAD, dprintf("Removing entry for thread %s\n", THREAD_NAME(tid));) acquire_sem(threadLock); talive--; if (tid->daemon) { tdaemon--; } /* Remove thread from live list so it can be garbage collected */ for (ntid = &liveThreads; *ntid != 0; ntid = &(*ntid)->nextlive) { if (tid == (*ntid)) { found = 1; (*ntid) = tid->nextlive; break; } } assert(found); release_sem(threadLock); /* If we only have daemons left, then we should exit. */ if (talive == tdaemon) { /* Make sure this section doesn't get executed * more than once. */ if (isShuttingDown) { return; } atomic_or(&isShuttingDown, 1); DBG(JTHREAD, dprintf("%s: all done, closing shop\n", THREAD_NAME(tid));) if (runOnExit != 0) { runOnExit(); } /* does that really make sense??? */ for (tid = liveThreads; tid != 0; tid = tid->nextlive) { if (destructor1) { (*destructor1)(tid->jlThread); } kill_thread(tid->native_thread); DBG(JTHREAD, dprintf("killed %s\n", THREAD_NAME(tid));) } /* Shut down this thread */ DBG(JTHREAD, dprintf("%s: Goodbye!\n", THREAD_NAME(GET_JTHREAD()));) exit_thread(0); } else { if (destructor1) { (*destructor1)(tid->jlThread); } /* This thread will now return to mark_thread_dead, and * then call exit_thread() from that function's caller. */ }}/* * mark the current thread as dead and remove it from the lists. */static voidmark_thread_dead(void){ jthread_t currentJThread = GET_JTHREAD(); assert (currentJThread->status != THREAD_DEAD); currentJThread->status = THREAD_DEAD; remove_thread(currentJThread);}/* * Have a thread exit. * Each thread exits only once. */voidjthread_exit(void){ jthread_t currentJThread = GET_JTHREAD(); DBG(JTHREAD, dprintf("jthread_exit called by %s\n", THREAD_NAME(currentJThread));) mark_thread_dead(); /* * If this is the main thread, wait for all other threads to finish. * At this point, the main jthread is no longer part of the * live list. */ if (the_main_thread == currentJThread->native_thread) { while (talive > tdaemon) { jthread_t tid = NULL; int32 rc; acquire_sem(threadLock); for (tid = liveThreads; tid != NULL; tid = tid->nextlive) { if (tid->daemon) break; } release_sem(threadLock); if (NULL != tid) { wait_for_thread(tid->native_thread, &rc); } } } /* * OK, now it's safe to exit */ DBG(JTHREAD, dprintf("%s: at the point of no return in jthread_exit\n", THREAD_NAME(currentJThread));) exit_thread(0); while (1) assert(!"This better not return.");}/* * Print info about a given jthread to stderr */void jthread_dumpthreadinfo(jthread_t tid){ dprintf("jthread %p native %ld status %s\n", tid, tid->native_thread, tid->status == THREAD_NEWBORN ? "NEWBORN" : tid->status == THREAD_RUNNING ? "RUNNING" : tid->status == THREAD_DYING ? "DYING" : tid->status == THREAD_DEAD ? "DEAD" : "???");}/* * dump info on all live threads */void/* ARGSUSED */dumpLiveThreads(int s){ jthread_t tid; for (tid = liveThreads; tid != NULL; tid = tid->nextlive) { jthread_dumpthreadinfo(tid); }}/* * have main thread wait for all threads to finish */void jthread_exit_when_done(void){ while (talive > 1) jthread_yield(); jthread_exit();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -