📄 threads.c
字号:
currentThread = candidate; // Its just easier this way. init_sp_pv(); candidate->state = RUNNING; if (candidate == bootThread) { MethodRecord *mRec; ClassRecord *classRecord; classRecord = get_class_record (get_entry_class (gProgramNumber)); // Initialize top word with fake parameter for main(): set_top_ref (JNULL); // Push stack frame for main method: mRec= find_method (classRecord, main_4_1Ljava_3lang_3String_2_5V); dispatch_special (mRec, null); // Push another if necessary for the static initializer: dispatch_static_initializer (classRecord, pc); } else { set_top_ref (ptr2word (candidate)); dispatch_virtual ((Object *) candidate, run_4_5V, null); } // The following is needed because the current stack frame // was just created stackFrame = current_stackframe(); update_stack_frame (stackFrame); } break; case RUNNING: // Its running already case DEAD: // Dead threads should be handled earlier default: // ??? break; } // Do we now have a thread we want to run? // Note we may later decide not to if all non-daemon threads have died if (currentThread == null && candidate->state == RUNNING) { currentThread = candidate; // Move thread to end of queue *pThreadQ = candidate; } if (!candidate->daemon) { // May or may not be running but it could do at some point#if DEBUG_THREADSprintf ("Found a non-daemon thread %d: %d(%d)\n", (int) candidate, (int)candidate->threadId, (int) candidate->state);#endif nonDaemonRunnable = true; } #if DEBUG_THREADS printf ("switch_thread: done processing thread %d: %d\n", (int) candidate, (int) (candidate->state == RUNNING)); #endif // Always use the first running thread as the thread // Keep looping: cull dead threads, check there's at least one non-daemon thread previousThread = candidate; } while (candidate != anchorThread); } // end for #if DEBUG_THREADSprintf ("currentThread=%d, ndr=%d\n", (int) currentThread, (int)nonDaemonRunnable);#endif#if DEBUG_THREADS printf ("Leaving switch_thread()\n");#endif if (nonDaemonRunnable) { // There is at least one non-daemon thread left alive if (currentThread != null) { // If we found a running thread and there is at least one // non-daemon thread left somewhere in the queue... #if DEBUG_THREADS printf ("Current thread is %d: %d(%d)\n", (int) currentThread, (int)currentThread->threadId, (int) currentThread->state); printf ("getting current stack frame...\n"); #endif stackFrame = current_stackframe(); #if DEBUG_THREADS printf ("updating registers...\n"); #endif update_registers (stackFrame); #if DEBUG_THREADS printf ("done updating registers\n"); #endif if (currentThread->interruptState == INTERRUPT_GRANTED) throw_exception(interruptedException); } return true; } schedule_request(REQUEST_EXIT); currentThread = null; return false;}/* * Current thread owns object's monitor (we hope) and wishes to relinquish * it temporarily (by calling Object.wait()). */void monitor_wait(Object *obj, const FOURBYTES time){#if DEBUG_MONITOR printf("monitor_wait of %d, thread %d(%d)\n",(int)obj, (int)currentThread, currentThread->threadId);#endif if (currentThread->threadId != get_thread_id (obj)) { throw_exception(illegalMonitorStateException); return; } // Great. We own the monitor which means we can give it up, but // indicate that we are listening for notify's. currentThread->state = CONDVAR_WAITING; // Save monitor depth currentThread->monitorCount = get_monitor_count(obj); // Save the object who's monitor we will want back currentThread->waitingOn = ptr2word (obj); // Might be an alarm set too. if (time > 0) currentThread->sleepUntil = get_sys_time() + time; else currentThread->sleepUntil = 0; #if DEBUG_MONITOR printf("monitor_wait of %d, thread %d(%d) until %ld\n",(int)obj, (int)currentThread, currentThread->threadId, time);#endif // Indicate that the object's monitor is now free. set_thread_id (obj, NO_OWNER); set_monitor_count(obj, 0); // Gotta yield schedule_request( REQUEST_SWITCH_THREAD);}/* * Current thread owns object's monitor (we hope) and wishes to wake up * any other threads waiting on it. (by calling Object.notify()). */void monitor_notify(Object *obj, const boolean all){#if DEBUG_MONITOR printf("monitor_notify of %d, thread %d(%d)\n",(int)obj, (int)currentThread, currentThread->threadId);#endif if (currentThread->threadId != get_thread_id (obj)) { throw_exception(illegalMonitorStateException); return; } monitor_notify_unchecked(obj, all);}/* * wake up any objects waiting on the passed object. */void monitor_notify_unchecked(Object *obj, const boolean all){ short i; Thread *pThread; #if DEBUG_MONITOR printf("monitor_notify_unchecked of %d, thread %d(%d)\n",(int)obj, (int)currentThread, currentThread->threadId);#endif // Find a thread waiting on us and move to WAIT state. for (i=MAX_PRIORITY-1; i >= 0; i--) { pThread = threadQ[i]; if (!pThread) continue; do { // Remember threadQ[i] is the last thread on the queue pThread = word2ptr(pThread->nextThread); if (pThread->state == CONDVAR_WAITING && pThread->waitingOn == ptr2word (obj)) { // might have been interrupted while waiting if (pThread->interruptState != INTERRUPT_CLEARED) pThread->interruptState = INTERRUPT_GRANTED; pThread->state = MON_WAITING; if (!all) return; } } while (pThread != threadQ[i]); }}/** * currentThread enters obj's monitor: * * if monitor is in use, save object in thread and re-schedule * else grab monitor and increment its count. * * Note that this operation is atomic as far as the program is concerned. */void enter_monitor (Thread *pThread, Object* obj){#if DEBUG_MONITOR printf("enter_monitor of %d\n",(int)obj);#endif if (obj == JNULL) { throw_exception (nullPointerException); return; } if (get_monitor_count (obj) != NO_OWNER && pThread->threadId != get_thread_id (obj)) { // There is an owner, but its not us. // Make thread wait until the monitor is relinquished. pThread->state = MON_WAITING; pThread->waitingOn = ptr2word (obj); pThread->monitorCount = 1; // Gotta yield schedule_request (REQUEST_SWITCH_THREAD); return; } set_thread_id (obj, pThread->threadId); inc_monitor_count (obj);}/** * Decrement monitor count * Release monitor if count reaches zero */void exit_monitor (Thread *pThread, Object* obj){ byte newMonitorCount;#if DEBUG_MONITOR printf("exit_monitor of %d\n",(int)obj);#endif if (obj == JNULL) { // Exiting due to a NPE on monitor_enter [FIX THIS] return; } #ifdef VERIFY assert (get_thread_id(obj) == pThread->threadId, THREADS7); assert (get_monitor_count(obj) > 0, THREADS8); #endif newMonitorCount = get_monitor_count(obj)-1; if (newMonitorCount == 0) set_thread_id (obj, NO_OWNER); set_monitor_count (obj, newMonitorCount);}/** * Current thread waits for thread to die. * * throws InterruptedException */void join_thread(Thread *thread){}void dequeue_thread(Thread *thread){ // First take it out of its current queue byte cIndex = thread->priority-1; Thread **pThreadQ = &threadQ[cIndex]; // Find the previous thread at the old priority Thread *previous = *pThreadQ; #if DEBUG_THREADS printf("Previous thread %ld\n", ptr2word(previous)); #endif while (word2ptr(previous->nextThread) != thread) previous = word2ptr(previous->nextThread); #if DEBUG_THREADS printf("Previous thread %ld\n", ptr2word(previous)); #endif if (previous == thread) { #if DEBUG_THREADS printf("No more threads of priority %d\n", thread->priority); #endif *pThreadQ = null; } else { previous->nextThread = thread->nextThread; *pThreadQ = previous; } }void enqueue_thread(Thread *thread){ // Could insert it anywhere. Just insert it at the end. byte cIndex = thread->priority-1; Thread *previous = threadQ[cIndex]; threadQ[cIndex] = thread; if (previous == null) thread->nextThread = ptr2word(thread); else { Thread *pNext = word2ptr(previous->nextThread); thread->nextThread = ptr2word(pNext); previous->nextThread = ptr2word(thread); }}/** * Set the priority of the passed thread. Insert into new queue, remove * from old queue. Overload to remove from all queues if passed priority * is zero. * * Returns the 'previous' thread. */void set_thread_priority(Thread *thread, const FOURBYTES priority){ #if DEBUG_THREADS printf("Thread priority set to %ld was %d\n", priority, thread->priority); #endif if (thread->priority == priority) return; if (thread->state == NEW) { // Not fully initialized thread->priority = priority; return; } dequeue_thread(thread); thread->priority = priority; enqueue_thread(thread); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -