📄 pjthread.c
字号:
pthread_setspecific(cookie_key, jlThread); /* XXX what to do with mainThreadStackSize?? */ jthread_setpriority(jtid, prio); return (jtid);}/* * set a function to be run when all non-daemon threads have exited */voidjthread_atexit(void (*f)(void)){ runOnExit = f;}/* * disallow cancellation */void jthread_disable_stop(void){ jthread_t tid = GET_JTHREAD(); /* XXX is called exactly once before initial thread context is created. */ if (tid != NULL) tid->flags |= THREAD_FLAG_DONTSTOP;}/* * reallow cancellation and stop if cancellation pending */void jthread_enable_stop(void){ jthread_t tid = GET_JTHREAD(); /* XXX is called exactly once before initial thread context is created. */ if (tid != NULL) { tid->flags &= ~THREAD_FLAG_DONTSTOP; if (tid->status == THREAD_DYING) { tid->status = THREAD_RUNNING; onstop(); jthread_exit(); } }}/* * interrupt a thread */voidjthread_interrupt(jthread_t tid){ if (tid->native_thread != pthread_self()) pthread_kill(tid->native_thread, SIG_INT);}/* * start function for each thread. * This function install the cleanup handler, sets jthread-specific * data and calls the actual work function. */void *start_me_up(void *arg){ jthread_t tid = (jthread_t)arg;DBG(JTHREAD, dprintf("starting thread %p\n", tid); ) pthread_mutex_lock(&threadLock); SET_JTHREAD(tid); SET_COOKIE(tid->jlThread); tid->status = THREAD_RUNNING; pthread_mutex_unlock(&threadLock);DBG(JTHREAD, dprintf("calling thread %p, %d\n", tid, tid->native_thread); ) tid->func(tid->jlThread); assert(!"firstStartThread has returned");#if 0DBG(JTHREAD, dprintf("thread %d returned, calling jthread_exit\n", tid->native_thread); ) /* drop onstop handler if that thread is exiting by itself */ assert (tid->status != THREAD_DYING); mark_thread_dead(); /* by returning, we exit this thread */#endif return 0;}/* * create a new jthread */jthread_tjthread_create(unsigned int pri, void (*func)(void *), int daemon, void *jlThread, size_t threadStackSize){ int err; pthread_t new; jthread_t tid; pthread_attr_t attr;#ifdef CPU_INHERIT extern struct JNINativeInterface Kaffe_JNINativeInterface; JNIEnv env = &Kaffe_JNINativeInterface; pthread_t scheduler = cpui_thread_scheduler(&env, jlThread);#endif pthread_attr_init(&attr); /* XXX use setschedparam here */ pthread_attr_setstacksize(&attr, threadStackSize); oskit_pthread_attr_setprio(&attr, pri); /* * Note that we create the thread in a joinable state, which is the * default. Our finalizer will join the threads, allowing the * pthread system to free its resources. */#ifdef CPU_INHERIT pthread_attr_setscheduler(&attr, (pthread_t) scheduler); pthread_attr_setopaque(&attr, pri);#endif tid = allocator(sizeof (*tid)); assert(tid != 0); /* XXX */ pthread_mutex_lock(&threadLock); tid->jlThread = jlThread; tid->func = func; tid->nextlive = liveThreads; liveThreads = tid; tid->status = THREAD_NEWBORN; err = pthread_create(&new, &attr, start_me_up, tid); tid->native_thread = new; talive++; if ((tid->daemon = daemon) != 0) { tdaemon++; } pthread_mutex_unlock(&threadLock);DBG(JTHREAD, dprintf("created thread %d, daemon=%d\n", new, daemon); )#ifdef CPU_INHERITDBG(JTHREAD, dprintf("scheduler=%d, pri=%d\n", scheduler, pri); )#endif return (tid);}/*============================================================================ * * Functions that are part of the user interface * *//* * sleep for time milliseconds */ voidjthread_sleep(jlong time){ /* pthread_sleep is an oskit extension */ oskit_pthread_sleep((oskit_s64_t)time);}/* * 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){ /* XXX use setschedparam here */ oskit_pthread_setprio(jtid->native_thread, 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 */ pthread_kill(jtid->native_thread, SIG_STOP);}static voidremove_thread(jthread_t tid){ jthread_t* ntid; int found = 0; pthread_mutex_lock(&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); pthread_mutex_unlock(&threadLock); /* If we only have daemons left, then we should exit. */ if (talive == tdaemon && !tid->daemon) {DBG(JTHREAD, dprintf("all done, closing shop\n"); ) if (runOnExit != 0) { runOnExit(); } /* does that really make sense??? */ for (tid = liveThreads; tid != 0; tid = tid->nextlive) { if (destructor1) { (*destructor1)(tid->jlThread); } jthread_stop(tid); } /* Am I suppose to close things down nicely ?? */ KAFFEVM_EXIT(0); } else { if (destructor1) { (*destructor1)(tid->jlThread); } }}/* * mark the current thread as dead and remove it from the lists. */static voidmark_thread_dead(void){ jthread_t currentJThread = GET_JTHREAD(); assert(currentJThread); assert(currentJThread->status != THREAD_DEAD); currentJThread->status = THREAD_DEAD; remove_thread(currentJThread);}/* * Have a thread exit. * Each thread exits only once. */voidjthread_exit(void){DBG(JTHREAD, dprintf("jthread_exit called by %d\n", GET_JTHREAD()->native_thread); ) mark_thread_dead(); /* XXX disconnect the native thread object */ GET_JTHREAD()->native_thread = -1; pthread_detach(pthread_self()); pthread_exit(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, (long) tid->native_thread, tid->status == THREAD_NEWBORN ? "NEWBORN" : tid->status == THREAD_RUNNING ? "RUNNING" : tid->status == THREAD_DYING ? "DYING" : tid->status == THREAD_DEAD ? "DEAD" : tid->status == THREAD_CONTINUE? "CONTINUE": tid->status == THREAD_STOPPED ? "STOPPED" : "???");}/* * 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();}/*============================================================================ * * locking subsystem * */void jmutex_initialise(jmutex *lock){ if (0 != pthread_mutex_init(lock, (const pthread_mutexattr_t *)0)) { assert(!!!"Could not initialise mutex"); /* XXX */ }}voidjmutex_lock(jmutex *lock){ pthread_mutex_lock(lock);}voidjmutex_unlock(jmutex *lock){ pthread_mutex_unlock(lock);}voidjmutex_destroy(jmutex *lock){ pthread_mutex_destroy(lock);}voidjcondvar_initialise(jcondvar *cv){ if (0 != pthread_cond_init(cv, (const pthread_condattr_t *)0)) { assert(!!!"Could not initialise condvar"); /* XXX */ }}jbooljcondvar_wait(jcondvar *cv, jmutex *lock, jlong timeout){ struct oskit_timespec abstime; struct timeval now; if (timeout == (jlong)0) { pthread_cond_wait(cv, lock); return true; } /* Need to convert timeout to an abstime. Very dumb! */ gettimeofday(&now, 0); TIMEVAL_TO_TIMESPEC(&now, &abstime); abstime.tv_sec += timeout / 1000; abstime.tv_nsec += (timeout % 1000) * 1000000; if (abstime.tv_nsec > 1000000000) { abstime.tv_sec += 1; abstime.tv_nsec -= 1000000000; } pthread_cond_timedwait(cv, lock, &abstime); return true; /* XXX what should I be returning?? */}voidjcondvar_signal(jcondvar *cv, jmutex *lock){ pthread_cond_signal(cv);}voidjcondvar_destroy(jcondvar *cv){ pthread_cond_destroy(cv);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -