ActivityManager.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 
39 #include "RexxCore.h"
40 #include "RexxActivity.hpp"
41 #include "RexxActivation.hpp"
42 #include "DirectoryClass.hpp"
43 #include "ActivityManager.hpp"
44 #include "Interpreter.hpp"
45 #include "ProtectedObject.hpp"
46 #include "InterpreterInstance.hpp"
47 #include "RexxNativeActivation.hpp"
48 #include "SysActivity.hpp"
49 
50 // The currently active activity.
52 
53 // this is a volatile variable used to ensure instruction ordering
54 volatile bool ActivityManager::sentinel = false;
55 
56 // available activities we can reuse
58 
59 // table of all activities
61 
62 std::deque<RexxActivity *>ActivityManager::waitingActivities; // queue of waiting activities
63 
64 // process shutting down flag
66 
67 // number of active interpreter instances in this process
69 
70 // global lock for the interpreter
71 SysMutex ActivityManager::kernelSemaphore("ActivityManager::kernelSemaphore");
72 
73 // the termination complete semaphore
74 SysSemaphore ActivityManager::terminationSem("ActivityManager::terminationSem");
75 
76 /**
77  * Initialize the activity manager when the interpreter starts up.
78  */
80 {
84 }
85 
86 void ActivityManager::live(size_t liveMark)
87 /******************************************************************************/
88 /* NOTE: we do not mark the UninitTables. MEMORY will request the table */
89 /* and mark it for us. This is so that it can determine if there are */
90 /* any objects that a "dead" and need uninit run. Activity will run the */
91 /* UNINIT, but we let Garbage Collection, handle detection/etc. */
92 /* NOTE: we also do not mark the subClasses table. This will be managed */
93 /* by memory so that we can reclaim classes once all of the instances have */
94 /* also been reclaimed. */
95 /******************************************************************************/
96 {
99 }
100 
102 /******************************************************************************/
103 /* NOTE: we do not mark the UninitTables. MEMORY will request the table */
104 /* and mark it for us. This is so that it can determine if there are */
105 /* any objects that a "dead" and need uninit run. Activity will run the */
106 /* UNINIT, but we let Garbage Collection, handle detection/etc. */
107 /* The subClasses table is only marked during a save image, so that the */
108 /* classes will still have the proper subclass definitions. */
109 /******************************************************************************/
110 {
111  if (!memoryObject.savingImage())
112  {
115  }
116 }
117 
118 
120 
122 {
124 }
125 
126 /**
127  * Add a waiting activity to the waiting queue.
128  *
129  * @param waitingAct The activity to queue up.
130  * @param release If true, the kernel lock should be released on completion.
131  */
132 void ActivityManager::addWaitingActivity(RexxActivity *waitingAct, bool release )
133 {
134  ResourceSection lock("ActivityManager::addWaitingActivity", 0); // need the control block locks
136 
137  // nobody waiting yet? If the release flag is true, we already have the
138  // kernel lock, but nobody is waiting. In theory, this can't really
139  // happen, but we can return immediately if that is true.
140  if (waitingActivities.empty())
141  {
142  // we're done if we already have the lock and the queue is empty.
143  if (release)
144  {
145  return;
146  }
147  // add to the end
148  waitingActivities.push_back(waitingAct);
149  // this will ensure this happens before the lock is released
150  sentinel = false;
151  // we should end up getting the lock immediately, but you never know.
152  lock.release(); // release the lock now
153  }
154  else
155  {
156  // add to the end
157  waitingActivities.push_back(waitingAct);
158  // this will ensure this happens before the lock is released
159  sentinel = false;
160  // we're going to wait until posted, so make sure the run semaphore is cleared
161  waitingAct->clearWait();
162  sentinel = true;
163  lock.release(); // release the lock now
164  sentinel = false;
165  // if we are the current kernel semaphore owner, time to release this
166  // so other waiters can
167  if (release)
168  {
169  unlockKernel();
170  }
171  SysActivity::yield(); // yield the thread
172  waitingAct->waitForDispatch(); // wait for this thread to get dispatched again
173  }
174 
175  sentinel = true;
176  lockKernel(); // get the kernel lock now
177  // belt and braces. it is possible the dispatcher was
178  // reentered on the same thread, in which case we have an
179  // earlier stack frame waiting on the same semaphore. Clear it so it
180  // get get reposted later.
181  waitingAct->clearWait();
182  sentinel = false;
183  lock.reacquire(); // get the resource lock back
184  sentinel = false; // another memory barrier
185 
186  // We only get dispatched if we end up at the front of the queue again,
187  // so just pop the front element.
188  waitingActivities.pop_front();
189  sentinel = true;
190  // if there's something else in the queue, then post the run semaphore of
191  // the head element so that it wakes up next and starts waiting on the
192  // run semaphore
193  if (hasWaiters())
194  {
195  waitingActivities.front()->postDispatch();
196  }
197  // the setting of the sentinel variables acts as a memory barrier to
198  // ensure that the assignment of currentActivitiy occurs precisely at this point.
199  sentinel = false;
200  currentActivity = waitingAct; /* set new current activity */
201  sentinel = true;
202  /* and new active settings */
204 }
205 
206 
207 /**
208  * Terminate an interpreter instance. This starts process
209  * shutdown if the last instance goes away.
210  */
212 {
213  //TODO: more stuff should be moved into here.
215 }
216 
217 /**
218  * Terminate an interpreter instance. This starts process
219  * shutdown if the last instance goes away.
220  */
222 {
223  ResourceSection lock("ActivityManager::terminateInterpreter", 0);
224  interpreterInstances--; /* reduce the active count */
225  if (interpreterInstances == 0) /* down to nothing? */
226  {
227  /* force termination */
228  shutdown();
229  }
230 }
231 
232 
233 /**
234  * Shutdown the activity manager and initiate interpreter termination.
235  */
237 {
238  processTerminating = true;
239  /* Make sure we wake up server */
240  /* Make sure all free Activities */
241  /* get the terminate message */
242  /* done after uninit calls. incas */
243  /* uninits needed some. */
245 }
246 
247 
248 /**
249  * Create a new activation for a toplevel activation using a
250  * routine (vs. a method invocation).
251  *
252  * @param activity The activity we're running on.
253  * @param routine The routine object we're calling.
254  * @param code The code object associated with the method.
255  * @param calltype The type of call being made.
256  * @param environment
257  * The initial address environment.
258  * @param context The context of the invocation.
259  *
260  * @return The newly created activation.
261  */
262 RexxActivation *ActivityManager::newActivation(RexxActivity *activity, RexxActivation *parent, RoutineClass *routine, RexxCode *code, RexxString *calltype, RexxString *environment, int context)
263 {
264  // in heavily multithreaded environments, the activation cache is a source for race conditions
265  // that can lead to crashes. Just unconditionally create a new actvation
266  return new RexxActivation(activity, parent, routine, code, calltype, environment, context);
267 }
268 
269 
270 /**
271  * Create a new activation for an internal level call
272  * (internal call or interpreted execution).
273  *
274  * @param activity The activity we're running on.
275  * @param parent The parent activation. OREF_NULL is used if this is a top-level
276  * call.
277  * @param code The code object associated with the method.
278  * @param context The context of the invocation.
279  *
280  * @return The newly created activation.
281  */
283 {
284  // in heavily multithreaded environments, the activation cache is a source for race conditions
285  // that can lead to crashes. Just unconditionally create a new actvation
286  return new RexxActivation(activity, parent, code, context);
287 }
288 
289 
290 /**
291  * Create a new activation for a method invocation (vs. a
292  * program or routine call)
293  *
294  * @param activity The activity we're running on.
295  * @param method The method object being invoked.
296  * @param code The code object associated with the method.
297  *
298  * @return The newly created activation.
299  */
301 {
302  // in heavily multithreaded environments, the activation cache is a source for race conditions
303  // that can lead to crashes. Just unconditionally create a new actvation
304  return new RexxActivation(activity, parent, method, code);
305 }
306 
307 
308 /**
309  * Create a new activation for a a native external call stack
310  *
311  * @param activity The activity we're running on.
312  * @param parent The parent activation.
313  *
314  * @return The newly created activation.
315  */
317 {
318  // in heavily multithreaded environments, the activation cache is a source for race conditions
319  // that can lead to crashes. Just unconditionally create a new actvation
320  return new RexxNativeActivation(activity, parent);
321 }
322 
323 
324 /**
325  * Create a new activation for a a native external call stack
326  *
327  * @param activity The activity we're running on.
328  *
329  * @return The newly created activation.
330  */
332 {
333  // in heavily multithreaded environments, the activation cache is a source for race conditions
334  // that can lead to crashes. Just unconditionally create a new actvation
335  return new RexxNativeActivation(activity);
336 }
337 
338 
339 /**
340  * Obtain a new activity for running on a separate thread.
341  *
342  * @return The created (or pooled) activity object.
343  */
345 {
346  ResourceSection lock("ActivityManager::createNewActivity", 0); // lock the control information
347  /* try to get one from the free table*/
349  if (activity == OREF_NULL)
350  {
351  lock.release(); // release lock while creating new activity
352  /* Create a new activity object */
353  activity = new RexxActivity(true);
354  lock.reacquire(); // need this back again
355  /* Add this activity to the table of */
356  /* in use activities and the global */
357  /* table */
358  allActivities->append((RexxObject *)activity);
359  }
360  else
361  {
362  /* We are able to reuse an activity, */
363  /* so just re-initialize it. */
364  activity->reset();
365  }
366  return activity; /* return the activity */
367 }
368 
369 
370 /**
371  * Create an activity object for the current thread.
372  *
373  * @return
374  */
376 {
377  // create an activity object without creating a new thread
378  RexxActivity *activity = new RexxActivity(false);
379  ResourceSection lock("ActivityManager::createCurrentActivity", 0); // lock the control information
380  /* Add this activity to the table of */
381  /* in use activities and the global */
382  /* table */
383  allActivities->append((RexxObject *)activity);
384  return activity; /* return the activity */
385 }
386 
387 
388 /**
389  * Clone off an activity from an existing activity. Used for
390  * message start() are early reply operations.
391  *
392  * @param parent The currently running activity. The activity-specific settings are
393  * inherited from the parent.
394  *
395  * @return A new activity.
396  */
398 {
399  // create a new activity with the same priority as the parent
400  RexxActivity *activity = createNewActivity();
401  // copy any needed settings from the parent
402  activity->inheritSettings(parent);
403  return activity;
404 }
405 
406 
408 /******************************************************************************/
409 /* Function: see if there are any Uninit messages need to be send before */
410 /* the process goes away. */
411 /******************************************************************************/
412 {
414  while (activity != OREF_NULL)
415  {
416  // terminate this thread
417  activity->terminatePoolActivity();
419  }
420 }
421 
422 
423 /**
424  * Return an activity to the available pool. If we're in the
425  * process of shutting down, or have too many pool activities,
426  * we'll return false to tell the activity to completely
427  * shut things down.
428  *
429  * @param activity The activity we're adding back to the available pool.
430  *
431  * @return true if this was pooled, false if the thread should not wait for
432  * more work.
433  */
435 {
436  // are we shutting down or have too many threads in the pool?
438  {
439  // have the activity clean up its resources.
440  activity->cleanupActivityResources();
441 
442  // remove this from the activity list
443  allActivities->removeItem((RexxObject *)activity);
444  return false;
445  }
446  else
447  {
448  // just add this to the available list
449  availableActivities->append((RexxObject *)activity);
450  return true; // this was successfully pooled
451  }
452 }
453 
454 
456  thread_id_t thread_id, /* target thread id */
457  RexxString * description ) /* description to use */
458 /******************************************************************************/
459 /* Function: Flip on a bit in a target activities top activation */
460 /******************************************************************************/
461 {
462  ResourceSection lock("ActivityManager::haltActivity", 0);
463  // locate the activity associated with this thread_id. If not found, return
464  // a failure.
465  RexxActivity *activity = findActivity(thread_id);
466  if (activity != OREF_NULL)
467  {
468  return activity->halt(description);
469  }
470  return false; // this was a failure
471 }
472 
473 
475  thread_id_t thread_id, /* target thread id */
476  bool on_or_off ) /* trace on/off flag */
477 /******************************************************************************/
478 /* Function: Flip on a bit in a target activities top activation */
479 /******************************************************************************/
480 {
481  ResourceSection lock("ActivityManager::setActivityTrace", 0);
482  // locate the activity associated with this thread_id. If not found, return
483  // a failure.
484  RexxActivity *activity = findActivity(thread_id);
485  if (activity != OREF_NULL)
486  {
487  return activity->setTrace(on_or_off);
488  }
489  return false; // this was a failure
490 }
491 
492 
494 /******************************************************************************/
495 /* Function: Signal an activation to yield control */
496 /******************************************************************************/
497 {
498  ResourceSection lock("ActivityManager::yieldCurrentActivity", 0);
499 
501  if (activity != OREF_NULL)
502  {
503  activity->yield();
504  }
505 }
506 
507 
509 {
510  return SysActivity::yieldCounter();
511 }
512 
513 
515 /******************************************************************************/
516 /* Function: Locate the activity associated with a thread */
517 /******************************************************************************/
518 {
519  // this is a critical section
520  ResourceSection lock("ActivityManager::findActivity", 0);
521 
522  // NB: New activities are pushed on to the end, so it's prudent to search
523  // from the list end toward the front of the list. Also, this ensures we
524  // will find the toplevel activity nested on a given thread first.
525  for (size_t listIndex = allActivities->lastIndex();
526  listIndex != LIST_END;
527  listIndex = allActivities->previousIndex(listIndex) )
528  {
529  RexxActivity *activity = (RexxActivity *)allActivities->getValue(listIndex);
530  // this should never happen, but we never return suspended threads
531  if (activity->isThread(threadId) && !activity->isSuspended())
532  {
533  return activity;
534  }
535  }
536  return OREF_NULL;
537 }
538 
539 
541 /******************************************************************************/
542 /* Function: Locate the activity associated with a thread */
543 /******************************************************************************/
544 {
546 }
547 
548 
549 void ActivityManager::exit(int retcode)
550 /******************************************************************************/
551 /* Function: Really shut down--this exits the process */
552 /******************************************************************************/
553 {
554  ::exit(retcode);
555 }
556 
558 /******************************************************************************/
559 /* Function: Request access to the kernel */
560 /******************************************************************************/
561 {
562  kernelSemaphore.request("ActivityManager::lockKernel", 0); /* just request the semaphore */
563 }
564 
566 /******************************************************************************/
567 /* Function: Release the kernel access */
568 /******************************************************************************/
569 {
570  // the use of the sentinel variables will ensure that the assignment of
571  // current activity occurs BEFORE the kernel semaphore is released.
572  sentinel = false;
573  currentActivity = OREF_NULL; /* no current activation */
574  sentinel = true;
575  kernelSemaphore.release("ActivityManager::unlockKernel", 0); /* release the kernel semaphore */
576 }
577 
578 /**
579  * Create the global kernel lock for the ActivityManager.
580  */
582 {
584  // this needs to be created and set
587 }
588 
589 /**
590  * Create the global kernel lock for the ActivityManager.
591  */
593 {
596 }
597 
598 
599 /**
600  * Try a fast request for the kernel. This requires A) there
601  * be no waiting activities and B) that it be possible to request
602  * the semaphore without waiting.
603  *
604  * @return true if the semaphore was obtained, false if the kernel is
605  * not locked by this activity.
606  */
608 {
609  // don't give this up if we have activities in the
610  // dispatch queue
611  if (waitingActivities.empty())
612  {
613  return kernelSemaphore.requestImmediate("ActivityManager::lockKernelImmediate", 0);
614  }
615  return false;
616 }
617 
618 
619 /**
620  * Return an activity to the activity pool.
621  *
622  * @param activityObject
623  * The released activity.
624  */
626 /******************************************************************************/
627 /* Function: Return access to an activity previously obtained from */
628 /* getActivity(). This will handle activity nesting and also */
629 /* release the kernel semaphore. */
630 /******************************************************************************/
631 {
632  // START OF CRITICAL SECTION
633  {
634  ResourceSection lock("ActivityManager::returnActivity", 0);
635  // and also remove from the global list
636  allActivities->removeItem((RexxObject *)activityObject);
637  // if we ended up pushing an old activity down when we attached this
638  // thread, then we need to restore the old thread to active state.
639  RexxActivity *oldActivity = activityObject->getNestedActivity();
640  if (oldActivity != OREF_NULL)
641  {
642  oldActivity->setSuspended(false);
643  }
644  // cleanup any system resources this activity might own
645  activityObject->cleanupActivityResources();
646  }
647 }
648 
649 
650 /**
651  * Return an activity to the activity pool.
652  *
653  * @param activityObject
654  * The released activity.
655  */
657 {
658  // START OF CRITICAL SECTION
659  {
660  ResourceSection lock("ActivityManager::activityEnded", 0); // this is a critical section
661  // and also remove from the global list
662  allActivities->removeItem((RexxObject *)activityObject);
663  // cleanup any system resources this activity might own
664  activityObject->cleanupActivityResources();
665  /* Are we terminating? */
666  if (processTerminating && allActivities->items() == 0)
667  {
668  // notify any waiters that we're clear
669  postTermination();
670  }
671  }
672 }
673 
674 
675 /**
676  * Get a root activity for a new interpreter instance.
677  *
678  * @return The newly created activity.
679  */
681 {
682  // it's possible we already have an activity active for this thread. That
683  // most likely occurs in nested RexxStart() calls. Get that activity first,
684  // and if we have one, we'll need to push this down.
685  RexxActivity *oldActivity = findActivity();
686 
687  // we need to lock the kernel to have access to the memory manager to
688  // create this activity.
689  lockKernel();
690  /* Get a new activity object. */
691  RexxActivity *activityObject = createCurrentActivity();
692  unlockKernel(); /* release kernel semaphore */
693  // mark this as the root activity for an interpreter instance. Some operations
694  // are only permitted from the root threads.
695  activityObject->setInterpreterRoot();
696 
697  // Do we have a nested interpreter call occurring on the same thread? We need to
698  // mark the old activity as suspended, and chain this to the new activity.
699  if (oldActivity != OREF_NULL)
700  {
701  oldActivity->setSuspended(true);
702  // this pushes this down the stack.
703  activityObject->setNestedActivity(oldActivity);
704  }
705 
706  // now we need to have this activity become the kernel owner.
707  activityObject->requestAccess();
708  // this will help ensure that the code after the request access call
709  // is only executed after access acquired.
710  sentinel = true;
711 
712  activityObject->activate(); // let the activity know it's in use, potentially nested
713  // belt-and-braces. Make sure the current activity is explicitly set to
714  // this activity before leaving.
715  currentActivity = activityObject;
716  return activityObject;
717 }
718 
719 
720 /**
721  * return a root activity when an interpreter instance
722  * terminates.
723  */
725 {
726  // detach this from the instance. This will also reactivate
727  // and nested activity that's been pushed down.
728  activity->detachInstance();
729  // make sure we release any system resources used by this activity, such as the semaphores
730  activity->cleanupActivityResources();
731 
732  ResourceSection lock("ActivityManager::returnRootActivity", 0); // need the control block locks
733  // remove this from the activity list so it will never get
734  // picked up again.
735  allActivities->removeItem((RexxObject *)activity);
736 }
737 
738 
739 /**
740  * Attach an activity to an interpreter instance
741  *
742  * @param instance The interpreter instance involved.
743  *
744  * @return Either an existing activity, or a new activity created for
745  * this thread.
746  */
748 {
749  // it's possible we already have an activity active for this thread. That
750  // most likely occurs in nested RexxStart() calls.
751  RexxActivity *oldActivity = findActivity();
752  // we have an activity created for this thread already. The interpreter instance
753  // should already have handled the case of an attach for an already attached thread.
754  // so we're going to have a new activity to create, and potentially an existing one to
755  // suspend
756  // we need to lock the kernel to have access to the memory manager to
757  // create this activity.
758  lockKernel();
759  RexxActivity *activityObject = createCurrentActivity();
760  // Do we have a nested interpreter call occurring on the same thread? We need to
761  // mark the old activity as suspended, and chain this to the new activity.
762  if (oldActivity != OREF_NULL)
763  {
764  oldActivity->setSuspended(true);
765  // this pushes this down the stack.
766  activityObject->setNestedActivity(oldActivity);
767  }
768 
769  unlockKernel(); /* release kernel semaphore */
770 
771  // now we need to have this activity become the kernel owner.
772  activityObject->requestAccess();
773  // this will help ensure that the code after the request access call
774  // is only executed after access acquired.
775  sentinel = true;
776  // belt-and-braces. Make sure the current activity is explicitly set to
777  // this activity before leaving.
778  currentActivity = activityObject;
779  return activityObject;
780 }
781 
782 
783 /**
784  * Get an already existing activity for the current thread and
785  * give it kernel access before returning. This will fail if
786  * the thread has not been properly attached.
787  *
788  * @return The activity for this thread.
789  */
791 {
792  // it's possible we already have an activity active for this thread. That
793  // most likely occurs in nested RexxStart() calls.
794  RexxActivity *activityObject = findActivity();
795  if (activityObject == OREF_NULL) /* Nope, 1st time through here. */
796  {
797  // this is an error....not sure how to handle this.
798  return OREF_NULL;
799  }
800  // go acquire the kernel lock and take care of nesting
801  activityObject->enterCurrentThread();
802  return activityObject; // Return the activity for thread
803 }
804 
805 
806 wholenumber_t relinquishCount = 0; // Monitoring
807 
809 {
810  return relinquishCount;
811 }
812 
813 /**
814  * Switch the active activity if there are other activities
815  * waiting to run.
816  *
817  * @param activity The current active activity.
818  */
820 {
821  relinquishCount += 1;
822  // if we have waiting activities, then let one of them
823  // in next.
824  if (hasWaiters())
825  {
826  addWaitingActivity(activity, true);
827  }
828 }
829 
830 
831 /**
832  * Retrieve a variable from the current local environment
833  * object.
834  *
835  * @param name The name of the environment variable.
836  *
837  * @return The object stored in .local at the requested name.
838  */
840 {
841  if (currentActivity == OREF_NULL)
842  {
843  return TheNilObject;
844  }
845  return currentActivity->getLocalEnvironment(name);
846 }
847 
848 
849 /**
850  * Retrieve the current .local directory instance.
851  *
852  * @return The .local directory for the current activity.
853  */
855 {
856  if (currentActivity == OREF_NULL)
857  {
858  return OREF_NULL;
859  }
860  return currentActivity->getLocal();
861 }
862 
863 
864 /**
865  * Enter a native context block. This will locate the appropriate
866  * activity for this callback and acquire kernel access on that
867  * activity. If this thread has never been used, then a new
868  * interpreter instance will be created and the thread attached
869  * to that instance.
870  */
872 {
873  // default to no instance
876  // if not reentering on an existing thread, we create a new instance
877  // temporarily to service this request. Many functions will
878  // not make sense called this way.
879  if (activity == OREF_NULL)
880  {
881  // Get an instance. This also gives the root activity of the instance
882  // the kernel lock.
885 
886  }
888 }
889 
890 
891 /**
892  * Release the kernal access and cleanup when the context block
893  * goes out of scope.
894  */
896 {
898  if (instance != OREF_NULL)
899  {
900  // terminate the instance
901  instance->terminate();
902  }
903 }
904 
905 
906 /**
907  * Protect an object that associated with the current native
908  * context. This creates a local reference that will lock
909  * the object into memory until the native activation is
910  * popped off the stack.
911  *
912  * @param o The object to protect (can be null).
913  *
914  * @return The protected object.
915  */
917 {
918  self->createLocalReference(o);
919  return o;
920 }
921 
wholenumber_t relinquishCount
wholenumber_t addWaitingActivityCount
#define LIST_END
Definition: ListClass.hpp:60
RexxList * new_list()
Definition: ListClass.hpp:147
#define OREF_NULL
Definition: RexxCore.h:60
#define TheNilObject
Definition: RexxCore.h:181
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
static bool processTerminating
static SysSemaphore terminationSem
static void yieldCurrentActivity()
static RexxActivity * createNewActivity()
static RexxList * allActivities
static bool setActivityTrace(thread_id_t thread_id, bool on_or_off)
static RexxNativeActivation * newNativeActivation(RexxActivity *activity, RexxActivation *parent)
static wholenumber_t addWaitingActivityCounter()
static RexxActivation * newActivation(RexxActivity *activity, RexxActivation *parent, RoutineClass *routine, RexxCode *code, RexxString *calltype, RexxString *environment, int context)
static void clearActivityPool()
static bool poolActivity(RexxActivity *activity)
static void createInterpreter()
static void postTermination()
static void relinquish(RexxActivity *activity)
static wholenumber_t yieldCounter()
static size_t interpreterInstances
static bool lockKernelImmediate()
static RexxList * availableActivities
static void init()
static std::deque< RexxActivity * > waitingActivities
static RexxDirectory * getLocal()
static void returnActivity(RexxActivity *)
static bool hasWaiters()
static void lockKernel()
static void unlockKernel()
static void shutdown()
static void live(size_t)
static void activityEnded(RexxActivity *)
static void addWaitingActivity(RexxActivity *a, bool release)
static void terminateInterpreter()
static void createLocks()
static bool haltActivity(thread_id_t thread_id, RexxString *description)
static RexxActivity * createCurrentActivity()
static RexxObject * getLocalEnvironment(RexxString *name)
static RexxActivity * attachThread()
static void exit(int retcode)
static void liveGeneral(int reason)
static SysMutex kernelSemaphore
static void closeLocks()
static RexxActivity *volatile currentActivity
static void returnRootActivity(RexxActivity *activity)
static RexxActivity * getRootActivity()
static RexxActivity * getActivity()
static volatile bool sentinel
static wholenumber_t relinquishCounter()
static RexxActivity * findActivity()
static InterpreterInstance * createInterpreterInstance()
Definition: Interpreter.hpp:95
RexxActivity * getRootActivity()
RexxActivity * activity
InterpreterInstance * instance
RexxObject * protect(RexxObject *o)
static void setCurrentSettings(NumericSettings *s)
Definition: Numerics.hpp:112
void requestAccess()
void enterCurrentThread()
bool halt(RexxString *)
bool isThread(thread_id_t id)
void inheritSettings(RexxActivity *parent)
void setInterpreterRoot()
RexxObject * getLocalEnvironment(RexxString *name)
void terminatePoolActivity()
NumericSettings * getNumericSettings()
void setNestedActivity(RexxActivity *a)
void cleanupActivityResources()
bool isSuspended()
void detachInstance()
void waitForDispatch()
void exitCurrentThread()
RexxActivationBase * getTopStackFrame()
RexxDirectory * getLocal()
void setSuspended(bool s)
bool setTrace(bool)
size_t previousIndex(size_t i)
Definition: ListClass.cpp:830
RexxObject * append(RexxObject *)
Definition: ListClass.cpp:538
size_t lastIndex()
Definition: ListClass.hpp:85
size_t items()
Definition: ListClass.hpp:97
RexxObject * removeItem(RexxObject *)
Definition: ListClass.cpp:1023
RexxObject * getValue(size_t i)
Definition: ListClass.cpp:276
RexxObject * removeFirstItem()
Definition: ListClass.hpp:111
bool savingImage()
Definition: RexxMemory.hpp:217
static wholenumber_t yieldCounter()
static thread_id_t queryThreadID()
static void yield()
void release(const char *ds, int di)
bool requestImmediate(const char *ds, int di)
void request(const char *ds, int di)
ssize_t wholenumber_t
Definition: rexx.h:230
pthread_t thread_id_t