void MM_MasterGCThread::masterThreadEntryPoint() { OMR_VMThread *omrVMThread = NULL; Assert_MM_true(NULL != _collectorControlMutex); Assert_MM_true(NULL == _masterGCThread); /* Attach the thread as a system daemon thread */ /* You need a VM thread so that the stack walker can work */ omrVMThread = MM_EnvironmentBase::attachVMThread(_extensions->getOmrVM(), "Dedicated GC Master", MM_EnvironmentBase::ATTACH_GC_MASTER_THREAD); if (NULL == omrVMThread) { /* we failed to attach so notify the creating thread that we should fail to start up */ omrthread_monitor_enter(_collectorControlMutex); _masterThreadState = STATE_ERROR; omrthread_monitor_notify(_collectorControlMutex); omrthread_exit(_collectorControlMutex); } else { /* thread attached successfully */ MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread); /* attachVMThread could allocate an execute a barrier (since it that point, this thread acted as a mutator thread. * Flush GC chaches (like barrier buffers) before turning into the master thread */ env->flushGCCaches(); env->setThreadType(GC_MASTER_THREAD); /* Begin running the thread */ omrthread_monitor_enter(_collectorControlMutex); _collector->preMasterGCThreadInitialize(env); _masterThreadState = STATE_WAITING; _masterGCThread = omrthread_self(); omrthread_monitor_notify(_collectorControlMutex); do { if (STATE_GC_REQUESTED == _masterThreadState) { if (_runAsImplicit) { handleConcurrent(env); } else { handleSTW(env); } } if (STATE_WAITING == _masterThreadState) { if (_runAsImplicit || !handleConcurrent(env)) { omrthread_monitor_wait(_collectorControlMutex); } } } while (STATE_TERMINATION_REQUESTED != _masterThreadState); /* notify the other side that we are active so that they can continue running */ _masterThreadState = STATE_TERMINATED; _masterGCThread = NULL; omrthread_monitor_notify(_collectorControlMutex); MM_EnvironmentBase::detachVMThread(_extensions->getOmrVM(), omrVMThread, MM_EnvironmentBase::ATTACH_GC_MASTER_THREAD); omrthread_exit(_collectorControlMutex); } }
/** * This method is called to push the concurrent thread to run the next function */ void triggerNextStepWithStatus(SupportThreadInfo *info, BOOLEAN done) { omrthread_monitor_enter(info->synchronization); info->done = done; omrthread_monitor_notify(info->synchronization); omrthread_monitor_wait_interruptable(info->synchronization, MILLI_TIMEOUT, NANO_TIMEOUT); omrthread_monitor_exit(info->synchronization); }
/** * Send a event and optionally event data to the waiting thread. * * @param info The pointer to SigMaskTestInfo object * @param event The event * @param value The pointer to event data * @param size The size of the event data */ static void sendEvent(SigMaskTestInfo *info, SignalEvent event, void *value, size_t size) { omrthread_monitor_enter(info->monitor); info->bulletinBoard.event = event; if ((NULL != value) && (size > 0)) { memcpy(&info->bulletinBoard.data, value, size); } omrthread_monitor_notify(info->monitor); omrthread_monitor_exit(info->monitor); }
intptr_t sem_post_zos(j9sem_t s) { zos_sem_t *zs = (zos_sem_t *) s; omrthread_monitor_enter(zs->monitor); zs->count++; omrthread_monitor_notify(zs->monitor); omrthread_monitor_exit(zs->monitor); return 0; }
void MM_MasterGCThread::shutdown() { Assert_MM_true(NULL != _collectorControlMutex); if ((STATE_ERROR != _masterThreadState) && (STATE_DISABLED != _masterThreadState)) { /* tell the background thread to shut down and then wait for it to exit */ omrthread_monitor_enter(_collectorControlMutex); while(STATE_TERMINATED != _masterThreadState) { _masterThreadState = STATE_TERMINATION_REQUESTED; omrthread_monitor_notify(_collectorControlMutex); omrthread_monitor_wait(_collectorControlMutex); } omrthread_monitor_exit(_collectorControlMutex); /* don't NULL _collector as RAS could still trigger a collection after we've started shutting down */ } }
void MM_MasterGCThread::handleSTW(MM_EnvironmentBase *env) { Assert_MM_true(NULL != _incomingCycleState); env->_cycleState = _incomingCycleState; /* this thread effectively inherits exclusive access from the mutator thread -- set its state to indicate this */ env->assumeExclusiveVMAccess(1); _collector->masterThreadGarbageCollect(env, _allocDesc); uintptr_t exclusiveCount = env->relinquishExclusiveVMAccess(); Assert_MM_true(1 == exclusiveCount); env->_cycleState = NULL; _incomingCycleState = NULL; _masterThreadState = STATE_WAITING; omrthread_monitor_notify(_collectorControlMutex); }
/** * This method is called to run the set of steps that will be run on a thread * @param info SupportThreadInfo structure that contains the information for the steps and other parameters * that are used */ static intptr_t J9THREAD_PROC runRequest(SupportThreadInfo *info) { intptr_t result = 0; uintptr_t i = 0; omrthread_monitor_enter(info->synchronization); omrthread_monitor_exit(info->synchronization); for (i = 0; i < info->numberFunctions; i++) { result = info->functionsToRun[i]((void *)info); omrthread_monitor_enter(info->synchronization); omrthread_monitor_notify(info->synchronization); if (info->done == TRUE) { omrthread_monitor_exit(info->synchronization); break; } omrthread_monitor_wait_interruptable(info->synchronization, STEP_MILLI_TIMEOUT, STEP_NANO_TIMEOUT); omrthread_monitor_exit(info->synchronization); } return result; }
void CMonitor::Notify(void) { omrthread_monitor_notify(m_monitor); }
bool MM_MasterGCThread::garbageCollect(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription) { Assert_MM_mustHaveExclusiveVMAccess(env->getOmrVMThread()); bool didAttemptCollect = false; if (NULL != _collector) { /* the collector has started up so try to run */ /* once the master thread has stored itself in the _masterGCThread, it should never need to collect - this would hang */ Assert_MM_true(omrthread_self() != _masterGCThread); if (_runAsImplicit || (NULL == _masterGCThread)) { /* We might not have _masterGCThread in the startup phase or late in the shutdown phase. * For example, there may be a native out-of-memory during startup or RAS may * trigger a GC after we've shutdown the master thread. */ Assert_MM_true(0 == env->getSlaveID()); _collector->preMasterGCThreadInitialize(env); _collector->masterThreadGarbageCollect(env, allocDescription); if (_runAsImplicit && _collector->isConcurrentWorkAvailable(env)) { omrthread_monitor_enter(_collectorControlMutex); if (STATE_WAITING == _masterThreadState) { _masterThreadState = STATE_GC_REQUESTED; omrthread_monitor_notify(_collectorControlMutex); } omrthread_monitor_exit(_collectorControlMutex); } } else { /* this is the general case, when the master thread is running internally */ omrthread_monitor_enter(_collectorControlMutex); /* The variable assignments below are safe because we hold Xaccess. Otherwise, it is possible (based on the wait/notify mechanism here) * that another thread could come in under this mutex and stomp on the "parameters" while another thread is waiting. */ _allocDesc = allocDescription; _incomingCycleState = env->_cycleState; MasterGCThreadState previousState = _masterThreadState; _masterThreadState = STATE_GC_REQUESTED; if (STATE_WAITING == previousState) { omrthread_monitor_notify(_collectorControlMutex); } else if (STATE_RUNNING_CONCURRENT == previousState) { _collector->forceConcurrentFinish(); } else { Assert_MM_unreachable(); } /* The master thread will claim exclusive VM access. Artificially give it up in this thread so that tools like -Xcheck:vm continue to work. */ uintptr_t savedExclusiveCount = env->relinquishExclusiveVMAccess(); while (STATE_GC_REQUESTED == _masterThreadState) { omrthread_monitor_wait(_collectorControlMutex); } env->assumeExclusiveVMAccess(savedExclusiveCount); Assert_MM_true(NULL == _incomingCycleState); omrthread_monitor_exit(_collectorControlMutex); } didAttemptCollect = true; } return didAttemptCollect; }