/** * Switch the active activity if there are other activities * waiting to run. * * @param activity The current active activity. */ void ActivityManager::relinquish(Activity *activity) { // if we have waiting activities, then let one of them // in next. if (hasWaiters()) { addWaitingActivity(activity, true); } }
/** * Add a waiting activity to the waiting queue. * * @param waitingAct The activity to queue up. * @param release If true, the kernel lock should be released on completion. */ void ActivityManager::addWaitingActivity(RexxActivity *waitingAct, bool release ) { ResourceSection lock("ActivityManager::addWaitingActivity", 0); // need the control block locks addWaitingActivityCount += 1; // nobody waiting yet? If the release flag is true, we already have the // kernel lock, but nobody is waiting. In theory, this can't really // happen, but we can return immediately if that is true. if (waitingActivities.empty()) { // we're done if we already have the lock and the queue is empty. if (release) { return; } // add to the end waitingActivities.push_back(waitingAct); // this will ensure this happens before the lock is released sentinel = false; // we should end up getting the lock immediately, but you never know. lock.release(); // release the lock now } else { // add to the end waitingActivities.push_back(waitingAct); // this will ensure this happens before the lock is released sentinel = false; // we're going to wait until posted, so make sure the run semaphore is cleared waitingAct->clearWait(); sentinel = true; lock.release(); // release the lock now sentinel = false; // if we are the current kernel semaphore owner, time to release this // so other waiters can if (release) { unlockKernel(); } SysActivity::yield(); // yield the thread waitingAct->waitForDispatch(); // wait for this thread to get dispatched again } sentinel = true; lockKernel(); // get the kernel lock now // belt and braces. it is possible the dispatcher was // reentered on the same thread, in which case we have an // earlier stack frame waiting on the same semaphore. Clear it so it // get get reposted later. waitingAct->clearWait(); sentinel = false; lock.reacquire(); // get the resource lock back sentinel = false; // another memory barrier // We only get dispatched if we end up at the front of the queue again, // so just pop the front element. waitingActivities.pop_front(); sentinel = true; // if there's something else in the queue, then post the run semaphore of // the head element so that it wakes up next and starts waiting on the // run semaphore if (hasWaiters()) { waitingActivities.front()->postDispatch(); } // the setting of the sentinel variables acts as a memory barrier to // ensure that the assignment of currentActivitiy occurs precisely at this point. sentinel = false; currentActivity = waitingAct; /* set new current activity */ sentinel = true; /* and new active settings */ Numerics::setCurrentSettings(waitingAct->getNumericSettings()); }
bool gps_hasWaiters() { return hasWaiters(&wait_gps); }