/** * We're leaving the current thread. So we need to deactivate * this. */ void InterpreterInstance::exitCurrentThread() { // find the current activity and deactivate it, and // release the kernel lock. RexxActivity *activity = findActivity(); activity->exitCurrentThread(); }
RexxActivity *ActivityManager::findActivity() /******************************************************************************/ /* Function: Locate the activity associated with a thread */ /******************************************************************************/ { return findActivity(SysActivity::queryThreadID()); }
/** * Attach a thread to an interpreter instance. * * @return The attached activity. */ RexxActivity *InterpreterInstance::attachThread() { // first check for an existing activity RexxActivity *activity = findActivity(); // do we have this? we can just return it if (activity != OREF_NULL) { // make sure we mark this as attached...we might be nested and don't want to // clean this up until we complete activity->nestAttach(); return activity; } // we need to get a new activity set up for this particular thread activity = ActivityManager::attachThread(); // resource lock must come AFTER we attach the thread, otherwise // we can create a deadlock situation when we attempt to get the kernel // lock ResourceSection lock("InterpreterInstance::attachThread", 0); // add this to the activity lists allActivities->append((RexxObject *)activity); // associate the thread with this instance activity->setupAttachedActivity(this); return activity; }
/** * Attach an activity to an interpreter instance * * @param instance The interpreter instance involved. * * @return Either an existing activity, or a new activity created for * this thread. */ RexxActivity *ActivityManager::attachThread() { // it's possible we already have an activity active for this thread. That // most likely occurs in nested RexxStart() calls. RexxActivity *oldActivity = findActivity(); // we have an activity created for this thread already. The interpreter instance // should already have handled the case of an attach for an already attached thread. // so we're going to have a new activity to create, and potentially an existing one to // suspend // we need to lock the kernel to have access to the memory manager to // create this activity. lockKernel(); RexxActivity *activityObject = createCurrentActivity(); // Do we have a nested interpreter call occurring on the same thread? We need to // mark the old activity as suspended, and chain this to the new activity. if (oldActivity != OREF_NULL) { oldActivity->setSuspended(true); // this pushes this down the stack. activityObject->setNestedActivity(oldActivity); } unlockKernel(); /* release kernel semaphore */ // now we need to have this activity become the kernel owner. activityObject->requestAccess(); // this will help ensure that the code after the request access call // is only executed after access acquired. sentinel = true; // belt-and-braces. Make sure the current activity is explicitly set to // this activity before leaving. currentActivity = activityObject; return activityObject; }
/** * Flip on external trace for a thread. * * @param thread_id The target thread id. * @param on_or_off The trace setting. * * @return true if this worked, false otherwise. */ bool ActivityManager::setActivityTrace(thread_id_t thread_id, bool on_or_off ) { ResourceSection lock; // locate the activity associated with this thread_id. If not found, return // a failure. Activity *activity = findActivity(thread_id); if (activity != OREF_NULL) { return activity->setTrace(on_or_off); } return false; // this was a failure }
/** * Raise a halt condition on an activity. * * @param thread_id The target thread identifier. * @param description * The description of the halt. * * @return Returns the halt result. Returns false if a halt * condition is already pending or the target activity * is not found. */ bool ActivityManager::haltActivity(thread_id_t thread_id, RexxString * description ) { ResourceSection lock; // locate the activity associated with this thread_id. If not found, return // a failure. Activity *activity = findActivity(thread_id); if (activity != OREF_NULL) { return activity->halt(description); } return false; // this was a failure }
/** * Get an already existing activity for the current thread and * give it kernel access before returning. This will fail if * the thread has not been properly attached. * * @return The activity for this thread. */ RexxActivity *ActivityManager::getActivity() { // it's possible we already have an activity active for this thread. That // most likely occurs in nested RexxStart() calls. RexxActivity *activityObject = findActivity(); if (activityObject == OREF_NULL) /* Nope, 1st time through here. */ { // this is an error....not sure how to handle this. return OREF_NULL; } // go acquire the kernel lock and take care of nesting activityObject->enterCurrentThread(); return activityObject; // Return the activity for thread }
/** * Get an already existing activity for the current thread and * give it kernel access before returning. This will fail if * the thread has not been properly attached. * * @return The activity for this thread. */ Activity *ActivityManager::getActivity() { // it's possible we already have an activity active for this thread. That // most likely occurs in nested RexxStart() calls. Activity *activityObject = findActivity(); // we generally should have something. Somehow we have an improperly // attached thread. Just return a failure indicator. if (activityObject == OREF_NULL) { return OREF_NULL; } // go acquire the kernel lock and take care of nesting activityObject->enterCurrentThread(); return activityObject; // Return the activity for thread }
bool ActivityManager::setActivityTrace( thread_id_t thread_id, /* target thread id */ bool on_or_off ) /* trace on/off flag */ /******************************************************************************/ /* Function: Flip on a bit in a target activities top activation */ /******************************************************************************/ { ResourceSection lock("ActivityManager::setActivityTrace", 0); // locate the activity associated with this thread_id. If not found, return // a failure. RexxActivity *activity = findActivity(thread_id); if (activity != OREF_NULL) { return activity->setTrace(on_or_off); } return false; // this was a failure }
bool ActivityManager::haltActivity( thread_id_t thread_id, /* target thread id */ RexxString * description ) /* description to use */ /******************************************************************************/ /* Function: Flip on a bit in a target activities top activation */ /******************************************************************************/ { ResourceSection lock("ActivityManager::haltActivity", 0); // locate the activity associated with this thread_id. If not found, return // a failure. RexxActivity *activity = findActivity(thread_id); if (activity != OREF_NULL) { return activity->halt(description); } return false; // this was a failure }
/** * Get a root activity for a new interpreter instance. * * @return The newly created activity. */ Activity *ActivityManager::getRootActivity() { // it's possible we already have an activity active for this thread. That // most likely occurs in nested RexxStart() calls. Get that activity first, // and if we have one, we'll need to push this down. Activity *oldActivity = findActivity(); // we need to lock the kernel to have access to the memory manager to // create this activity. lockKernel(); // get a new activity object Activity *activityObject = createCurrentActivity(); unlockKernel(); // mark this as the root activity for an interpreter instance. Some operations // are only permitted from the root threads. activityObject->setInterpreterRoot(); // Do we have a nested interpreter call occurring on the same thread? We need to // mark the old activity as suspended, and chain this to the new activity. if (oldActivity != OREF_NULL) { oldActivity->setSuspended(true); // this pushes this down the stack. activityObject->setNestedActivity(oldActivity); } // now we need to have this activity become the kernel owner. activityObject->requestAccess(); // this will help ensure that the code after the request access call // is only executed after access acquired. sentinel = true; activityObject->activate(); // let the activity know it's in use, potentially nested // belt-and-braces. Make sure the current activity is explicitly set to // this activity before leaving. currentActivity = activityObject; return activityObject; }
/** * Attempt to shutdown the interpreter instance. This can only be done * from the root activity. * * @return true if shutdown has been initiated, false otherwise. */ bool InterpreterInstance::terminate() { // if our current activity is not the root one, we can't do that RexxActivity *current = findActivity(); // we also can't be doing active work on the root thread if (current != rootActivity || rootActivity->isActive()) { return false; } terminated = false; // turn on the global termination in process flag terminating = true; { ResourceSection lock("InterpreterInstance::terminate", 0); // remove the current activity from the list so we don't clean everything // up. We need to allActivities->removeItem((RexxObject *)current); // go remove all of the activities that are not doing work for this instance removeInactiveActivities(); // no activities left? We can leave now terminated = allActivities->items() == 0; // we need to restore the rootActivity to the list for potentially running uninits allActivities->append((RexxObject *)current); } // if there are active threads still running, we need to wait until // they all finish if (!terminated) { terminationSem.wait("InterpreterInstance::terminate", 0); } // if everything has terminated, then make sure we run the uninits before shutting down. // This activity is currently the current activity. We're going to run the // uninits on this one, so reactivate it until we're done running enterOnCurrentThread(); // release any global references we've been holding. globalReferences->empty(); // before we update of the data structures, make sure we process any // pending uninit activity. memoryObject.verboseMessage("Calling runUninits through collectAndUninit from InterpreterInstance::terminate\n"); memoryObject.collectAndUninit(Interpreter::lastInstance()); // do system specific termination of an instance sysInstance.terminate(); // ok, deactivate this again...this will return the activity because the terminating // flag is on. exitCurrentThread(); terminationSem.close(); // make sure the root activity is removed by the ActivityManager; ActivityManager::returnRootActivity(current); // tell the main interpreter controller we're gone. Interpreter::terminateInterpreterInstance(this); return true; }
/** * Find an activity for the current thread that's associated * with this activity. * * @return The target activity. */ RexxActivity *InterpreterInstance::findActivity() { return findActivity(SysActivity::queryThreadID()); }
/** * Detach a thread from this interpreter instance. * * @return true if this worked ok. */ bool InterpreterInstance::detachThread() { // first check for an existing activity return detachThread(findActivity()); }
/** * Locate the activity associated with the current thread * * @return The Activity for this thread, if it exists. */ Activity *ActivityManager::findActivity() { return findActivity(SysActivity::queryThreadID()); }