📄 thread.c
字号:
MONITOR monitor;#if INCLUDEDEBUGCODE const char *format = "Thread %lx enter %s monitor %lx (owner=%lx, depth=%lx)\n";#endif switch (OBJECT_MHC_TAG(object)) { case MHC_UNLOCKED: if (value == MHC_UNLOCKED) { /* Our hash code is still 0. We can just create a simple * lock, which has implicit depth of 1 and an implicit hash * code of 0. */ SET_OBJECT_SIMPLE_LOCK(object, thisThread);#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "simple", (long)object, 0L, 0L); }#endif /* INCLUDEDEBUGCODE */ return MonitorStatusOwn; } else if (allocateFastLock(thisThread, object, 1, value)) { /* We need a fast lock, since we already have a hash code. * If the above allocation succeeds, then we're done. */#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "fast", (long)object, (long)thisThread, (long)0); }#endif /* INCLUDEDEBUGCODE */ return MonitorStatusOwn; } /* We have to do it the hard way */ goto upgradeToRealMonitor; case MHC_SIMPLE_LOCK: if (OBJECT_MHC_SIMPLE_THREAD(object) == thisThread) { if (allocateFastLock(thisThread, object, 2, 0)) { /* We need to upgrade from a simple lock to a fast lock, * since the depth is now 2. Indicate that the hash code * is still implicitly 0. */#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "fast", (long)object, (long)thisThread, (long)1); }#endif /* INCLUDEDEBUGCODE */ return MonitorStatusOwn; } } /* Either some other thread owns the lock, or no more fast locks */ goto upgradeToRealMonitor; case MHC_EXTENDED_LOCK: if (OBJECT_MHC_EXTENDED_THREAD(object) == thisThread) { thisThread->extendedLock.depth++;#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "fast", (long)object, (long)thisThread, (long)thisThread->extendedLock.depth); }#endif /* INCLUDEDEBUGCODE */ return MonitorStatusOwn; } goto upgradeToRealMonitor; upgradeToRealMonitor: /* Calling upgradeToRealMonitor may cause GC */ monitor = upgradeToRealMonitor(object); thisThread = CurrentThread; /* in case of GC */ break; default: /* case MHC_MONITOR: */ monitor = OBJECT_MHC_MONITOR(object); break; }#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "slow", (long)object, monitor->owner, monitor->depth); }#endif /* INCLUDEDEBUGCODE */ /* If we reach this point, the monitor of the object is "monitor", * and thisThread contains the current thread */ if (monitor->owner == NULL) { /* The monitor is unowned. Make ourselves be the owner */ monitor->owner = thisThread; monitor->depth = 1; return MonitorStatusOwn; } else if (monitor->owner == thisThread) { /* We already own the monitor. Increase the entry count. */ monitor->depth++; return MonitorStatusOwn; } else { /* Add ourselves to the wait queue. Indicate that when we are * woken, the monitor's depth should be set to 1 */ thisThread->monitor_depth = 1; addMonitorWait(monitor, thisThread); suspendThread(); return MonitorStatusWaiting; }}/*========================================================================= * FUNCTION: monitorExit * TYPE: Monitor handler * OVERVIEW: Relinquish ownership of a monitor * INTERFACE: * parameters: object: Any Java object * returns: MonitorStatusOwnMonitor: still own the monitor * MonitorStatusReleaseMonitor: releasing the monitor * MonitorStatusError: some exception occurred *=======================================================================*/enum MonitorStatusTypemonitorExit(OBJECT object, char** exceptionName){ THREAD thisThread = CurrentThread;#if INCLUDEDEBUGCODE const char *format = "Thread %lx exit %s monitor %lx (owner=%lx, depth=%lx)\n";#endif *exceptionName = NULL; switch (OBJECT_MHC_TAG(object)) { case MHC_SIMPLE_LOCK: if (OBJECT_MHC_SIMPLE_THREAD(object) != thisThread) { break; } /* Releasing a simple lock is easy */#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "simple", (long)object, (long)thisThread, 1); }#endif /* INCLUDEDEBUGCODE */ SET_OBJECT_HASHCODE(object, 0); return MonitorStatusRelease; case MHC_EXTENDED_LOCK: if (OBJECT_MHC_EXTENDED_THREAD(object) != thisThread) { break; } else { int newDepth;#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "fast", (long)object, (long)thisThread, (long)thisThread->extendedLock.depth); }#endif /* INCLUDEDEBUGCODE */ newDepth = --thisThread->extendedLock.depth; if (newDepth == 0) { /* Release the fast lock. No one is waiting for it */ SET_OBJECT_HASHCODE(object, thisThread->extendedLock.hashCode); FREE_EXTENDED_LOCK(thisThread); return MonitorStatusRelease; } else { if (newDepth == 1 && thisThread->extendedLock.hashCode==0){ /* Simplify this to a simple lock */ FREE_EXTENDED_LOCK(thisThread); SET_OBJECT_SIMPLE_LOCK(object, thisThread); } return MonitorStatusOwn; } } case MHC_MONITOR: { MONITOR monitor = OBJECT_MHC_MONITOR(object); if (monitor->owner != thisThread) { break; }#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, format, (long)thisThread, "slow", (long)object, (long)monitor->owner, (long)monitor->depth); }#endif /* INCLUDEDEBUGCODE */ if (--monitor->depth == 0) { /* Let someone else have the monitor */ removeMonitorWait(monitor); /* Is this now a dead monitor */ if ( monitor->owner == NULL && monitor->monitor_waitq == NULL && monitor->condvar_waitq == NULL) { /* Remove the monitor from the object */ SET_OBJECT_HASHCODE(object, monitor->hashCode); /* Use the "owner" slot to keep a list * of available monitors */ monitor->owner = (THREAD)MonitorCache; MonitorCache = monitor; } return MonitorStatusRelease; } else { return MonitorStatusOwn; } } case MHC_UNLOCKED: break; } *exceptionName = IllegalMonitorStateException; return MonitorStatusError;}/*========================================================================= * FUNCTION: monitorWait() * TYPE: Monitor handler * OVERVIEW: Wait for notification on the object * INTERFACE: * parameters: object: Any Java object * returns: MonitorStatusWaiting: waiting on the condvar * MonitorStatusError: some exception occurred *=======================================================================*/enum MonitorStatusTypemonitorWait(OBJECT object, long64 delta){ /* For monitor wait, we always need a real monitor object. */ MONITOR monitor = upgradeToRealMonitor(object);#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, "Thread %lx waiting on monitor/condvar %lx\n", (long)CurrentThread, (long)object); }#endif /* INCLUDEDEBUGCODE */ if (monitor->owner != CurrentThread) { raiseException(IllegalMonitorStateException); return MonitorStatusError; } if (ll_zero_gt(delta)) { registerAlarm(CurrentThread, delta, monitorWaitAlarm); } addCondvarWait(monitor, CurrentThread); suspendThread(); return MonitorStatusWaiting;}/* Callback function if a thread's timer expires while waiting to be notified */static void monitorWaitAlarm(THREAD thread){ MONITOR monitor = thread->monitor; if (monitor != NULL) { if (removeFromQueue(&monitor->condvar_waitq, thread)) { addMonitorWait(monitor, thread); } else { fatalError(KVM_MSG_THREAD_NOT_ON_CONDVAR_QUEUE); } }}/*========================================================================= * FUNCTION: monitorNotify() * TYPE: Monitor handler * OVERVIEW: Notify one process * INTERFACE: * parameters: object: Any Java object * notifyAll: true if waking up all waiters. * returns: MonitorStatusOwnMonitor: normal * MonitorStatusError: some exception occurred *=======================================================================*/enum MonitorStatusTypemonitorNotify(OBJECT object, bool_t notifyAll){ long value = object->mhc.hashCode; void *address = (void *)(value & ~0x3); MONITOR monitor; switch (OBJECT_MHC_TAG(object)) { case MHC_SIMPLE_LOCK: case MHC_EXTENDED_LOCK: if (address != CurrentThread) { break; } /* We can't have any waiters, since this is a simple lock */ return MonitorStatusOwn; case MHC_MONITOR: /* Make sure current thread is the owner of the monitor */ monitor = OBJECT_MHC_MONITOR(object); if (monitor->owner != CurrentThread) { break; }#if INCLUDEDEBUGCODE if (tracemonitors) { fprintf(stdout, "Thread %lx %s monitor %lx\n", (long)CurrentThread, (notifyAll ? "notifying all in" : "notifying"), (long)object); }#endif /* INCLUDEDEBUGCODE */ removeCondvarWait(OBJECT_MHC_MONITOR(object), notifyAll); return MonitorStatusOwn; case MHC_UNLOCKED: break; } raiseException(IllegalMonitorStateException); return MonitorStatusError;}/*========================================================================= * Queue manipulation functions (internal to this file) *=======================================================================*//*========================================================================= * FUNCTION: addThreadToQueue() * TYPE: public instance-level operation * OVERVIEW: Add a thread to the indicated queue * INTERFACE: * parameters: queue: A pointer to the queue thisThread: thread to add to the queue where: AT_START or AT_END * returns: <nothing> * NOTE: There are no safety checks here, so please * do not suspend the same thread twice. *=======================================================================*/static voidaddThreadToQueue(THREAD *queue, THREAD thisThread, queueWhere where){ START_CRITICAL_SECTION if (*queue == NIL) { *queue = thisThread; thisThread->nextThread = thisThread; } else { /* Add thisThread after *queue, which always points * to the last element of the list */ thisThread->nextThread = (*queue)->nextThread; (*queue)->nextThread = thisThread; if (where == AT_START) { /* We are already the first element of the queue */ ; } else { /* make this thread be the last thread */ *queue = thisThread; } } END_CRITICAL_SECTION}/*========================================================================= * FUNCTION: removeQueueStart() * TYPE: private instance-level operation * OVERVIEW: Remove a thread by from start of the indicated queue * INTERFACE: * parameters: queue: A pointer to the queue * returns: A THREAD pointer or NIL *=======================================================================*/sta
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -