📄 thread.c
字号:
thread->nextAlarmThread = q; } else { thread->nextAlarmThread = TimerQueue; TimerQueue = thread; }}/*========================================================================= * FUNCTION: checkTimerQueue() * TYPE: timer queue * OVERVIEW: Remove objects, as necessary, from the timer queue and * call their callback function. * INTERFACE: * parameters: A pointer to a ulong64. This value will be set to the time * at which the next clock event will occur. * returns: no value *=======================================================================*/voidcheckTimerQueue(ulong64 *nextTimerWakeup){#if NEED_LONG_ALIGNMENT Java8 tdub;#endif if (TimerQueue != NULL) { ulong64 now = CurrentTime_md(); do { ulong64 firstTime = GET_ULONG(TimerQueue->wakeupTime); if (ll_compare_le(firstTime, now)) { /* Remove this item from the queue, and resume it */ THREAD thread = TimerQueue; void (*wakeupCall)() = thread->wakeupCall;#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(thread, "Removing from timer queue"); }#endif TimerQueue = thread->nextAlarmThread; thread->nextAlarmThread = NULL; thread->wakeupCall = NULL; /* signal that not on queue */ wakeupCall(thread); } else { break; } } while (TimerQueue != NULL); } /* Now indicate when the next timer wakeup should happen */ if (TimerQueue == NULL) { ll_setZero(*nextTimerWakeup); } else { *nextTimerWakeup = GET_ULONG(TimerQueue->wakeupTime); }}/*========================================================================= * FUNCTION: removePendingAlarm(); * TYPE: timer queue * OVERVIEW: Remove thread from the timer queue. * INTERFACE: * parameters: The thread to remove from the timer queue. * returns: no value *=======================================================================*/static voidremovePendingAlarm(THREAD thread) { THREAD q, prev_q;#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(thread, "Purging from timer queue"); }#endif for (q = TimerQueue, prev_q = NULL; q != NULL; prev_q = q, q = q->nextAlarmThread) { if (q == thread) { if (prev_q) { prev_q->nextAlarmThread = q->nextAlarmThread; } else { TimerQueue = q->nextAlarmThread; } q->nextAlarmThread = NULL; q->wakeupCall = NULL; /* indicate not on queue anymore */ break; } }}/*========================================================================= * FUNCTION: inTimerQueue(); * TYPE: timer queue * OVERVIEW: Determine if a thread is in the timer queue. * INTERFACE: * parameters: The thread * returns: TRUE if the thread is in the timer queue. *=======================================================================*/bool_t inTimerQueue(THREAD thread) { return thread->wakeupCall != NULL;}/*========================================================================= * Monitor implementation *=======================================================================*/MONITOR MonitorCache;static char IllegalMonitorStateException[] = "java/lang/IllegalMonitorStateException";/*========================================================================= * Monitor operations *=======================================================================*//*========================================================================= * FUNCTION: addMonitorWait * TYPE: Monitor handler * OVERVIEW: Called to indicate a thread is waiting on a specific monitor * INTERFACE: * parameters: monitor: Monitor * thread: Thread waiting on the monitor *=======================================================================*/static voidaddMonitorWait(MONITOR monitor, THREAD thread) { /* Add to the wait queue */ addThreadToQueue(&monitor->monitor_waitq, thread, AT_END); thread->monitor = monitor; thread->state |= THREAD_MONITOR_WAIT;#if INCLUDEDEBUGCODE if (tracemonitors) { TraceMonitor(thread, monitor, &monitor->monitor_waitq, QUEUE_ADDED); }#endif /* If the wait queue has no owner, perhaps we should try to run this */ if (monitor->owner == NULL) { removeMonitorWait(monitor); }}/*========================================================================= * FUNCTION: removeMonitorWait * TYPE: Monitor handler * OVERVIEW: Called to indicate a new thread can take ownership of the * monitor * INTERFACE: * parameters: monitor: Monitor * thread: Thread waiting to be notified *=======================================================================*/static voidremoveMonitorWait(MONITOR monitor){ THREAD waiter = removeQueueStart(&monitor->monitor_waitq); if (waiter != NULL) { /* Set the monitor's ownership and restore the entry count */ monitor->owner = waiter; monitor->depth = waiter->monitor_depth; /* Zero this, just to be sure */ waiter->monitor = NULL; waiter->monitor_depth = 0;#if INCLUDEDEBUGCODE if (tracemonitors) { TraceMonitor(waiter, monitor, &monitor->monitor_waitq, QUEUE_REMOVED); }#endif resumeThread(waiter); } else { /* No one wants this monitor. Mark it as unused */ monitor->owner = NULL; monitor->depth = 0; }}/*========================================================================= * FUNCTION: addCondvarWait * TYPE: Monitor handler * OVERVIEW: Called to indicate a thread is waiting to be notified * INTERFACE: * parameters: monitor: Monitor * thread: Thread waiting to be notified *=======================================================================*/static voidaddCondvarWait(MONITOR monitor, THREAD thread) { if (monitor->owner != thread) { fatalVMError(KVM_MSG_BAD_CALL_TO_ADDCONDVARWAIT); } addThreadToQueue(&monitor->condvar_waitq, thread, AT_END); thread->monitor = monitor; thread->state |= THREAD_CONVAR_WAIT;#if INCLUDEDEBUGCODE if (tracemonitors) { TraceMonitor(thread, monitor, &monitor->condvar_waitq, QUEUE_ADDED); }#endif /* Save our entry count, so we can restore it when we regain control of * the monitor */ thread->monitor_depth = monitor->depth; /* We're relinquishing the monitor. Get the next guy off the queue */ removeMonitorWait(monitor);}/*========================================================================= * FUNCTION: removeCondvarWait * TYPE: Monitor handler * OVERVIEW: Called to notify one thread waiting to be notified * INTERFACE: * parameters: monitor: Monitor *=======================================================================*/static voidremoveCondvarWait(MONITOR monitor, bool_t notifyAll) { do { THREAD waiter = removeQueueStart(&monitor->condvar_waitq); if (waiter == NULL) { break; } /* This thread now has to wait to get ownership of the monitor */#if INCLUDEDEBUGCODE if (tracemonitors) { TraceMonitor(waiter, monitor, &monitor->condvar_waitq, FALSE); }#endif /* Just in case we were set to get an alarm */ removePendingAlarm(waiter); /* We can run as soon as we get the monitor again */ addMonitorWait(monitor, waiter); } /* Once through if !notifyAll. Until waiter == NULL, otherwise */ while (notifyAll);}static bool_tallocateFastLock(THREAD thread, OBJECT object, int depth, long hashCode) { if (IS_EXTENDED_LOCK_FREE(thread)) { /* thisLock->object = object; */ thread->extendedLock.depth = depth; thread->extendedLock.hashCode = hashCode; SET_OBJECT_EXTENDED_LOCK(object, thread); return TRUE; } else { return FALSE; }}voidclearObjectMonitor(OBJECT object) { long hashCode; switch (OBJECT_MHC_TAG(object)) { case MHC_UNLOCKED: /* Do nothing */ return; case MHC_SIMPLE_LOCK: hashCode = 0; break; case MHC_EXTENDED_LOCK: { THREAD thread = OBJECT_MHC_EXTENDED_THREAD(object); hashCode = thread->extendedLock.hashCode; FREE_EXTENDED_LOCK(thread); break; } default: hashCode = OBJECT_MHC_MONITOR(object)->hashCode; break; } SET_OBJECT_HASHCODE(object, hashCode);}static MONITORupgradeToRealMonitor(OBJECT object){ enum MHC_Tag_TypeCode tag = OBJECT_MHC_TAG(object); MONITOR monitor; if (tag == MHC_MONITOR) { /* We already have a monitor, so there is no need to do anything */ return OBJECT_MHC_MONITOR(object); } if (MonitorCache != NULL) { monitor = MonitorCache; MonitorCache = (MONITOR)monitor->owner; /* Make sure that the appropriate slots are zero. We know that * the queues are zero, since otherwise the monitor wouldn't have * been freed in the first placed */ monitor->owner = NULL; monitor->hashCode = 0; monitor->depth = 0; } else { START_TEMPORARY_ROOTS /* Create the monitor, while protecting the object from GC */ DECLARE_TEMPORARY_ROOT(OBJECT, tObject, object); monitor = (MONITOR)callocObject(SIZEOF_MONITOR, GCT_MONITOR); object = tObject; END_TEMPORARY_ROOTS }#if INCLUDEDEBUGCODE monitor->object = object;#endif switch(tag) { case MHC_UNLOCKED: monitor->hashCode = object->mhc.hashCode; break; case MHC_SIMPLE_LOCK: monitor->owner = OBJECT_MHC_SIMPLE_THREAD(object); monitor->depth = 1; break; case MHC_EXTENDED_LOCK: { THREAD thread = OBJECT_MHC_EXTENDED_THREAD(object); monitor->owner = thread; monitor->depth = thread->extendedLock.depth; monitor->hashCode = thread->extendedLock.hashCode; /* Free this fast lock, since it is no longer in use */ FREE_EXTENDED_LOCK(thread); break; default: /* Needed to keep compiler happy */ break; } } SET_OBJECT_MONITOR(object, monitor); return monitor;}long*monitorHashCodeAddress(OBJECT object) { switch (OBJECT_MHC_TAG(object)) { case MHC_SIMPLE_LOCK: { THREAD thisThread = OBJECT_MHC_SIMPLE_THREAD(object); if (allocateFastLock(thisThread, object, 1, 0)) { return &thisThread->extendedLock.hashCode; } else { MONITOR monitor = upgradeToRealMonitor(object); /* object may be trash, because of a GC, but doesn't matter */ return &monitor->hashCode; } } case MHC_EXTENDED_LOCK: { THREAD thread = OBJECT_MHC_EXTENDED_THREAD(object); return &thread->extendedLock.hashCode; } default: /* Keep compiler happy */ /* Do nothing */ return NULL; }}/*========================================================================= * FUNCTION: monitorEnter * TYPE: Monitor handler * OVERVIEW: Try to grab the monitor of an object * INTERFACE: * parameters: object: Any Java object * returns: MonitorStatusOwn: own the monitor * MonitorStatusWaiting: waiting for the monitor *=======================================================================*/enum MonitorStatusTypemonitorEnter(OBJECT object){ THREAD thisThread = CurrentThread; long value = object->mhc.hashCode;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -