Table of Contents Previous Chapter ACIS

15.0 Real-Time Executive (36-53212 A)

15.1 Purpose

The Real-Time Executive (RTX) category provides a top level interface to the underlying real-time executive. This serves to isolate the rest of the application code from the details of the executive, and facilitates the development of additional executive features.

15.2 Uses

The Executive classes provide the following features:

  1. Launch and maintain multiple preemptive tasks

  2. Notify running tasks of discrete events

  3. Broadcast events to all tasks within the system

  4. Lock and unlock access to resources shared by more than one task

  5. Maintain and use inter-process queues

  6. Allocate and release buffers from fixed size buffer pools

  7. Maintain and provide the number of timer ticks since the last reset

  8. Perform "aliveness" tests on each running task

15.3 Organization

Figure 50 illustrates the top-level relationships between these classes provided by the executive interface.

FIGURE 50. Real-Time Executive Interface Class Diagram


The Real-time Executive system uses Nucleus RTX to implement most of its features. The executive also relies heavily on the ACIS start-up code to initialize the RTX structures, and launch the executive. Nucleus RTX itself relies heavily on the low-level interrupt handler and on a timer-tick interrupt (see Section 15.4 ).

Task - This abstract class represents a single, independent thread of control. Its implementation uses the underlying multi-tasking facilities of the RTX. This class also uses the event notification facilities of RTX to provide task suspension and notification features. This class provides functions to obtain its RTX task id (getTaskId), notify the Task of an event (notify), check to see if an event has been reported (requestEvent), suspend execution for a period of time (sleep), suspend execution until an event has been reported (waitForEvent), and suspend execution until all other tasks of the same priority have had a chance to run (yield). Each subclass of Task must implement a goTaskEntry function, which will be invoked by the taskManager during system start-up. Once the system is running, the only direct action performed on one task by another task through event notification (notify, broadcast).

TaskManager - This class is responsible for coordinating the activities of individual tasks. It uses the Task class to coordinate these activities. Within ACIS, there is only one global instance of the TaskManager class, called taskManager. This class provides a function used during start-up to add a new task (addTask), and a static member function invoked by Nucleus to start a particular task (goInvokeTask). This class provides run-time functions to broadcast events to all tasks (broadcast), to disable and enable task preemption in the currently active task (forbidPreempt, permitPreempt), iterate through each configured task (nextTask), and obtain a pointer to the currently running task (queryCurrentTask).

Queue - This class represents an a abstract queue of items. It's implementation uses the inter-process queue facilities of the RTX. This class provides functions used by its subclasses to add items to the end of the queue (enqueue) and remove items from the start of the queue (dequeue). It also provides a function which suspends the running task on an empty queue until an item is placed into the queue, and then removes and returns the item (waitForItem). This class provides a generally accessible function which returns the number of items currently contained within the queue (howMany).

Semaphore - This class represents a resource lock or flag. Its implementation uses the underlying resource facilities of the RTX. This class provides functions which allocate the semaphore instance (request), and de-allocate the instance (release). It also provides a function which suspends the current task on an allocated instance until it is released (waitFor). It also provides a function which returns the current state of the instance (retrieveStatus).

MemoryPool - This class represents a pool of equally sized blocks of memory. It uses the underlying fixed-size memory management features of the underlying RTX. This class provides functions used by its subclasses to allocate a buffer from the pool (allocate) and release an allocated buffer back to the pool (deallocate). It also provides functions which suspend the current task on an empty pool until a buffer is released, and allocates the released buffer (waitForBuffer). It provides a general function which indicates the number of buffers currently available in the pool (available).

TaskMonitor - This class is a subclass of Task and is responsible for ensuring that none of the tasks within the instrument have crashed. This class operates by notifying each Task instance in the system and waiting for the task to reply (respond). Between each query, the TaskMonitor resets the watchdog timer (Watchdog). If a task does not respond within the watchdog time-out period (current ~8 minutes), the watchdog timer will expire and reset the instrument.

SystemClock - This class is responsible for maintaining the number of Back End Timer ticks since the last instrument reset. The constructor for this class starts the TimerDevice, and provides a function which supplies the current timer tick value (currentTime). NOTE: If the Back End Processor runs continuously, this counter will wrap about once every 13 years.

TimerCallback - This class is a subclass of Devices::DevCallback and is responsible for passing control to Nucleus RTX during timer interrupt processing (invoke).

Devices::Watchdog - This class is a subclass of Devices::IntrDevice and is provided by the Devices class category and is periodically reset by the TaskMonitor class. Refer to Section 7.0 for a description of this class

Devices::Timer - This class is a subclass of Devices::IntrDevice and is provided by the Devices class category. It is used by the SystemClock class to provide system timer ticks to Nucleus RTX. Refer to Section 7.0 for a detailed description of this class.

15.4 Interrupt Support and Task Event Definitions

15.4.1 Preemptive Context Switching

In order for Nucleus RTX to provide preemptive context switching, it must be called at the start of interrupt processing and must be allowed to control the return from the interrupt. Specifically, the low-level interrupt handler must call the Nucleus RTX function SKD_Interrupt_Context_Save prior to calling any C or C++ code. This function saves the state of all registers associated with the active task when the interrupt was taken. Once the interrupt handler is done, it must call SKD_Interrupt_Context_Restore. This function determines which task to run next, and restores the task's registers.

15.4.2 Task Notification Event Definitions

Tasks can suspend and resume their execution using event flags. Up to 32 flags can be waited on and sent to a particular task. These flags are specified as bit definitions in an unsigned integer value. Some of these flags are global, in that they may be sent to any task within the instrument, and other flags are privately used by a particular task. To avoid conflicting definitions, the lower 16-bits of an event word are used for these private task events, and the upper 16-bits are used for global events.The currently defined global event flag bit definitions are as follows (TBD):

enum EventPublic
{
  EV_TASKQUERY         = 1 << (0+16),  // Task Monitor Query
  EV_SECOND_TICK         = 1 << (1+16),  // 1 second tick (TBD)
  EV_STANDBY_ACTIVE         = 1 << (2+16),  // Standby Signal went Active
  EV_STANDBY_INACTIVE     = 1 << (3+16),  // Standby Signal when Inactive
  EV_RADMON_ACTIVE         = 1 << (4+16),  // Radiation Monitor went Active
  EV_RADMON_INACTIVE         = 1 << (5+16),  // Radiation Monitor Inactive
  EV_RESERVED         = 1 << (6+16)   // Reserved
}

15.5 Scenarios

15.5.1 Use 1: Launch Multiple Tasks

This section describes the overall initialization procedure used by ACIS to start-up the executive and launch the system's tasks. The configured task register and scheduling contexts are maintained within Nucleus RTX, and are identified using task ids. Each Task class instance within ACIS contains a copy of this Nucleus id. The TaskManager maintains an array of pointers to Task instances, where the array is indexed using Nucleus task identifiers.

The system initialization requirements of the Real-time Executive system are complicated slightly by the nature of Nucleus RTX coupled with the initialization behavior of C++. The requirements are as follows:

In order to allow the executive classes to acquire RTX resources upon initialization, the software must either:

The ACIS software design uses the second alternative. Figure 51 illustrates the key elements of start-up scenario:

FIGURE 51. Executive Initialization Scenario


  1. After performing the low-level processor initialization and patching, the system start-up function sets up the Nucleus RTX configuration data structures. This function installs all of the key ACIS tasks in an initial "Stopped" state. The entry point of each task is the taskManager's goInvokeTask() function. It also installs a low-priority "initialization" task in an initial "Start" state. The initial task also comes up in a non-preemptive state, meaning that as tasks are started, they won't take control from the initialization task until preemption is enabled.

  2. The system start-up function tells RTX to initialize and to start executing.

  3. RTX initializes and passes control to the only non-stopped task in the system, the low-priority initialization task.This task's entry function then invokes the function main().

  4. main() then invokes the built-in C++ function __main(), which proceeds to invoke the constructors of every global class instance in the system.

  5. __main() invokes the constructor for the taskManager instance

  6. __main() invokes the constructors for each of the task instances in the system

  7. Each task instance constructor calls taskManager.addTask() to record the task in the manager's data structures.

  8. taskManager tells RTX to start the installed task.The task doesn't actually run at this point because preemption is still disabled.

  9. The task's initialization code is now free to acquire whatever RTX resources it needs.

  10. Once all of the constructors are invoked and __main() returns, main() finally tells taskManager to enable preemption.

  11. The taskManager then instructs RTX to enable preemption.

  12. Once preemption is enabled, RTX invokes each of the installed tasks, in order of their priority. Higher priority tasks run until they suspend, and then the next lower priority task is invoked, etc.

  13. taskManager's goInvokeTask() function then invokes the active task instance's goTaskEntry() function and the task is now off and running.

15.5.2 Use 2: Notify tasks

This section briefly describes how individual tasks are notified of discrete events within the system.

Within ACIS, each Task instance has an associated dedicated Nucleus RTX Event Group (see Section 4.5 ). Whenever a task waits for an event, it only waits on events from this group. When a client notifies the task of the event, it invokes the task's notify() member function. This function then uses the underlying RTX to signal the task's Event Group, and reschedule the task. Whenever the task wakes up, it consumes the received event, and continues execution.

FIGURE 52. Task Notification


  1. The task cannot proceed until some event is received, so it invokes waitForEvent to block until the event is received.

  2. waitForEvent invokes the underlying NU_Wait_For_Events function, passing the task-specific event group id.

  3. Some other task or interrupt handler signals the waiting task with the desired event, using notify.

  4. notify then tells RTX to set the event(s) in the task's event group using NU_Set_Events

  5. RTX returns control to the waiting task (appearing to return from NU_Wait_For_Events and waitForEvent). The task then proceeds to process the event.

15.5.3 Use 3: Broadcast events

This section briefly describes how a client broadcasts an event to all tasks in the system.

This feature uses the TaskManager to iterate through each task in the system, notifying each task of the event. To ensure that the task priorities are adhered to, the TaskManager disables preemption during this process.

FIGURE 53. Event Broadcasting


  1. One or more tasks block for an event using waitForEvent

  2. waitForEvent calls RTX's NU_Wait_For_Events to suspend the task

  3. Some non-suspended task or interrupt handler tells the taskManager to broadcast an event to all tasks.

  4. It then forbids preemption, using forbidPreempt

  5. forbidPreempt calls the RTX function, NU_Disable_Preemption to prevent control from being stolen from the active task

  6. The taskManager then calls notify for every task in the system.

  7. Each task's notify function calls RTX's NU_Set_Events to signal the task

  8. After all of the tasks have been notified, the taskManager invokes permitPreempt

  9. permitPreempt uses the RTX NU_Enable_Preemption function to, once again, allow other tasks to take control from the one doing the notify. At this point, the tasks which were woken by the notify will take control, in the order of their relative priorities.

15.5.4 Use 4: Lock resources

This section briefly describes how resources are locked and unlocked by one or more clients.

The Executive uses a Semaphore Class to implement exclusive access locks. Each semaphore instance is associated with some sharable item within ACIS, and contains a Nucleus RTX resource identifier. Users of the sharable item must coordinate their use of the item using the associated Semaphore instance. In practice, access to a shared resource's semaphore may be hidden from the user by the member functions of the resource, but this is beyond the scope of this example. Figure 54 shows a scenario where one task obtains a resource's semaphore, causing another task to block until the semaphore is released. The memory required for the RTX resource is allocated by RTX during its start-up procedure.

FIGURE 54. Resource Arbitration


  1. task 1 gets the lock associated with the shared resource by invoking request

  2. The semaphore's request function then invokes RTX's NU_Request_Resource, which succeeds and locks the associated RTX resource.

  3. task 1 proceeds to use the shared resource in relative safety

  4. task 2 wants access to the shared resource, and is willing to wait for it, so it invokes the waitFor function to attempt to obtain the resource, and, if necessary, block until it becomes available (or until it times out).

  5. The waitFor function invokes RTX's NU_Request_Resource function again, this time passing in a time-out value. Since the resource is currently locked by task 1, NU_Request_Resource suspends task 2.

  6. task 1 finally finishes with the resource and unlocks it using release.

  7. release invokes NU_Release_Resource. Once this happens, task 2 is woken up, and its call to NU_Request_Resource returns, re-locking the resource for task 2's benefit.

  8. task 2 then proceeds to use the resource, releasing when it's done (not shown).

In general, the Semaphore class's request function is used for "balking requests", where, if the semaphore is already locked, the client does not want to block until the semaphore is released. If the client wants to wait until the semaphore is released, it should use the waitFor function. This function also provides a time-out feature. If the client is suspended longer than the time-out argument passed to waitFor, waitFor will fail to obtain the lock on the semaphore.

15.5.5 Use 5: Maintain queues

This section briefly describes a scenario where two clients are using a queue to pass information between them.

ACIS uses a Queue class to manage first-in, first-out inter-process queues of information. Each instance of a queue is associated with an Nucleus RTX queue. The memory required for the RTX queue is allocated by RTX during its start-up procedure.

FIGURE 55. Simple Queue Use Example


  1. A supplier produces an item

  2. and calls enqueue to copy the item into the item queue, passing the address of the item

  3. The Queue instance, item queue, invokes the RTX NU_Send_Item function to place the item at the end of the queue

  4. NU_Send_Item copies the data to the end of the queue

  5. The consumer invokes dequeue, passing a pointer to a buffer to store the item

  6. dequeue invokes the RTX function NU_Retrieve_Item to copy the next item from the start of the queue, and remove the copied item from the queue

  7. The consumer then uses the retrieved item.

15.5.6 Use 6: Acquire and release memory

This section briefly describes how memory is allocated and released from a pool of buffers.

The executive category provides a MemoryPool class which manages pools of equally sized buffers. Each MemoryPool instance refers to a unique RTX memory partition. The memory for the pool is allocated by RTX during its start-up procedure.

FIGURE 56. Simple Memory Pool Use


  1. user 1 calls MemoryPool's allocate to obtain a buffer.

  2. allocate invokes the RTX function NU_Alloc_Partition to obtain a buffer from the pool. For this example, assume that there is only one buffer in the pool, and so after the NU_Alloc_Partition call, the pool is empty.

  3. user 1 successfully gets the last buffer in the pool and starts using it

  4. user 2 attempts to get a buffer, blocking if necessary, using waitForBuffer.

  5. waitForBuffer calls NU_Alloc_Partition. Since the pool is empty, NU_Alloc_Partition blocks until a buffer is released (or until it time-out)

  6. user 1 finally finishes with the buffer and calls deallocate to release it

  7. deallocate invokes RTX's NU_Dealloc_Partition to release the buffer. Once the buffer is released, user 2's call to waitForBuffer/NU_Alloc_Partition succeeds and returns with the allocated buffer.

  8. user 2 is now free to use the obtained buffer

15.5.7 Use 7: Provide current time

Nucleus RTX maintains an internal timer tick counter, which it increments for each call to CLD_Timer_Interrupt. This function, CLD_Timer_Interrupt, also performs all of the executive's time-based scheduling operations, such as suspension time-outs.

The Executive interface uses the SystemClock class to install an interrupt callback instance into the TimerDevice, and to access the Nucleus timer tick counter.

Figure 57 illustrates timer interrupt handling, and how clients access the Nucleus timer tick counter value.

FIGURE 57. Executive Timer Interrupt Handling and Counter Access


  1. During system initialization, the systemClock installs the timerCallback instance into the timerDevice, using timerDevice.installCallback().

  2. systemClock then starts the timer, using timerDevice.start().

  3. Later, once the timer hardware count expires, a timer interrupt is taken. As part of its interrupt processing, the timerDevice invokes the installed callback, timerCallback.invoke().

  4. timerCallback.invoke() calls Nucleus RTX function, CLD_Timer_Interrupt(), to count the tick, and schedule its tasks.

  5. Clients obtain the current timer tick counter by calling systemClock.currentTime().

  6. currentTime() then calls the Nucleus RTX function, NU_Read_Time), to obtain its timer tick counter.

15.5.8 Use 8: Verify task health

In order to ensure that no task has crashed and entered an infinite loop, the executive implements a utility task, TaskMonitor, which periodically polls each task in the system, and resets the watchdog timer between each query. If a task does not respond within the time-out period of the watchdog timer, the instrument is reset by the timer hardware.

Figure 58 illustrates the how the TaskMonitor behaves in the system.

FIGURE 58. TaskMonitor queries and responses


  1. After system initialization, the executive calls the main function of the monitor's task, goTaskEntry(). This function sets the current task pointer to 0, and enters an infinite loop. At the top of the loop, the taskMonitor resets the watchdog timer, using watchdogDevice.touch().

  2. The taskMonitor then queries the taskManager for the next task in its list, passing taskManager.nextTask() the current task pointer.

  3. taskMonitor then notifies the referenced task using task->notify().

  4. taskMonitor then sleeps for a TBD period of time, using sleep, to space out the queries and allow lower priority tasks to run.

  5. Once sleep returns, the taskMonitor suspends until the queried task responds, using waitForEvent().

  6. Once the task receives the query, it replies to the monitor using the monitor's binding function, taskMonitor.respond().

  7. respond() wakes up the task portion of the taskMonitor using notify(). At this point, the taskMonitor touches the watchdog, and repeats from step 2.

  8. When the taskMonitor sends itself a query, its call to waitForEvent() (step 5) will return indicating the query. In this case, the taskMonitor calls its respond() function which then notifies the task. The subsequent call to waitForEvent() will return with the response immediately, and the taskMonitor proceeds with the next task.

15.6 Class TaskManager

Documentation:
The TaskManager is responsible for co-ordination the execution of tasks within the executive. It supplies operations which apply globally to all tasks.
Export Control:
Public
Cardinality:
1

Hierarchy:

Superclasses:

none

Public Uses:

Task

Public Interface:

Operations:

TaskManager()
addTask()
broadcast()
forbidPreempt()
goInvokeTask()
nextTask()
permitPreempt()
queryCurrentTask()

Protected Interface:

Has-A Relationships:


Task* taskList[]: This is an array of pointers to tasks. The array is indexed by the Nucleus RTX Task Identifier associated with a given task.
Concurrency:
Synchronous

15.6.1 TaskManager()

Public member of:
TaskManager
Documentation:
This is the constructor for the TaskManager. It initializes all state variables.
Preconditions:
Nucleus RTX is running, but only the current task is active.
Semantics:
Flag preemption as disabled
Zero the array of task pointers.

Postconditions:
The TaskManager is ready to accept addTask requests and, in general, ready to go.
Concurrency:
Sequential

15.6.2 addTask()

Public member of:
TaskManager
Return Class:
void

Arguments:

Task* task
unsigned taskId
Documentation:
This function instructs the TaskManager to add task to its list of tasks, and to associate the task with the RTX identifier, taskId.
This function is intended to be used by the Task class's constructor to register the task with the TaskManager.
Preconditions:
Preemption of the currently running task must be disabled
taskId must be an existing Nucleus RTX task index
A task using taskId must not have already been installed
task must not be NULL
Semantics:
Install task in the Task array entry indexed by taskId slot.
Tell Nucleus RTX to start the task (preemption disabled so task won't run right away)

Postconditions:
task is installed in the TaskManager's array and is ready to run once preemption is enabled and all higher priority tasks suspend.
Concurrency:
Sequential (note the preemption requirement)

15.6.3 broadcast()

Public member of:
TaskManager
Return Class:
void

Arguments:

unsigned eventMask
Documentation:
Notify all tasks of the events indicated in eventMask
Preconditions:
None
Semantics:
Forbid preemption, notify all tasks of eventMask, and restore preemption

Postconditions:
All tasks in the system will have been notified
Concurrency:
Synchronous

15.6.4 forbidPreempt()

Public member of:
TaskManager
Return Class:
void
Documentation:
Prevents the current task from being preempted. Within a given task, subsequent calls to forbidPreempt() prior to permitPreempt() accumulate. An equal number of calls to permitPreempt() are needed to enable preemption.
NOTE: THIS DOES NOT DISABLE INTERRUPTS!!!
Preconditions:
Must be at task level (not at interrupt level)

Semantics:
Prevent preemptive context switch, call NU_Disable_Preemption

Postconditions:
Preemption is disabled

Concurrency:
Synchronous

15.6.5 goInvokeTask()

Public member of:
TaskManager
Return Class:
void
Documentation:
This function invokes the goTaskEntry() function of the Task instance associated with the currently running RTX task.
Preconditions:
Nucleus RTX is running, and the active task has been installed using addTask.
Semantics:
Get the current task id from RTX using NU_Current_Task, use as index into task table and return the referenced Task pointer and calls its goTaskEntry() member function.
Concurrency:
Synchronous

15.6.6 nextTask()

Public member of:
TaskManager
Return Class:
Task*

Arguments:

Task* oldTask
Documentation:
This function allows clients to iterate through each task in the system. If oldTask is NULL, this function returns the first task in the system. If it is not NULL, it returns a pointer to the next task.
Preconditions:
oldTask is either NULL or a pointer to a Task installed via addTask.
Semantics:
If oldTask is NULL, retrieve the Task pointer indexed by 0.
If oldTask is not NULL, retrieve the id of oldTask, and add 1. If result greater than or equal to the number of installed tasks, wrap the index to 0, and get the first Task. If result is a valid index, get pointer to indexed Task.

Postconditions:
Returns pointer to the "next" Task instance
Concurrency:
Synchronous

15.6.7 permitPreempt()

Public member of:
TaskManager
Return Class:
void
Documentation:
Allow the current task to be preempted. Within a given task, one call to permitPreempt() for each outstanding call to forbidPreempt() is needed to enable preemption. Additional calls to permitPreempt() have no effect.
NOTE: THIS DOES NOT ENABLE INTERRUPTS!!!
Preconditions:
Must not be in an interrupt handler

Semantics:
Allow task to be preempted by another higher priority task.

Postconditions:
Current task may now be preempted by another
Concurrency:
Synchronous

15.6.8 queryCurrentTask()

Public member of:
TaskManager
Return Class:
Task*
Documentation:
Returns a pointer to the currently active task. If this function is called as part of an interrupt handler, it returns a pointer to the task that was interrupted. If all tasks were suspended when the interrupt is taken, this function returns 0.
Preconditions:
None
Semantics:
Get the currently active task

Postconditions:
Return value points to the active task
Concurrency:
Synchronous

15.7 Class Task

Documentation:
The Task Class defines a thread of control within the system.
Export Control:
Public
Cardinality:
n

Hierarchy:

Superclasses:

none

Public Interface:

Operations:

Task()
getTaskId()
goTaskEntry()
notify()
requestEvent()
sleep()
waitForEvent()
yield()

Protected Interface:

Has-A Relationships:


unsigned rtxTaskId: This variable contains the Nucleus RTX Task Identifier associated with this instance of a task.

unsigned rtxEventGroupId: This variable contains the Nucleus RTX Event Group identifier associated with the event group dedicated to this task instance.
Concurrency:
Active

15.7.1 Task()

Public member of:
Task

Arguments:

unsigned taskId
Documentation:
This initializes an instance of Task. taskId is the Nucleus RTX task identifier associated with the instance.
Preconditions:
Nucleus RTX must be already running. taskManager must exist and must have been initialized (constructed).
Semantics:
Store taskId in both rtxTaskId and using for rtxEventGroupId. Call taskManager.addTask() to register the task with the manager.
Postconditions:
The task is installed and ready to run.
Concurrency:
Sequential

15.7.2 getTaskId()

Public member of:
Task
Return Class:
unsigned
Documentation:
This function returns a numeric task identifier. This function is intended for use only by the TaskManager.
Preconditions:
None
Semantics:
Get rtxTaskId
Postconditions:
Return rtxTaskId
Concurrency:
Synchronous

15.7.3 goTaskEntry()

Public member of:
Task
Return Class:
void
Documentation:
This function is an abstract function which represents the main entry point of a task. All subclasses of Task must implement a version of this function.
Preconditions:
The task must not have already been started.
Semantics:
Subclasses of task must implement this function. In general, it contains the main loop of the task.
Postconditions:
THIS FUNCTION MUST NEVER RETURN.
Concurrency:
Synchronous

15.7.4 notify()

Public member of:
Task
Return Class:
void

Arguments:

unsigned eventMask
Documentation:
This function notifies the task that the events specified in eventMask bit-field have occurred.
Preconditions:
None
Semantics:
Set the events in the event group specified for the task using NU_Set_events. Use rtxEventGroupId as the notification group.
Postconditions:
Adds the events specified eventMask to current pending events and causes task to resume if it was blocked on one or more of the events
Concurrency:
Synchronous

15.7.5 requestEvent()

Public member of:
Task
Return Class:
unsigned

Arguments:

unsigned eventMask
Documentation:
This function tests to see if one or more events specified in eventMask are set, and if so, consumes and returns those set events. Events not specified in eventMask are not affected. Unlike waitForEvent, this function does not block.
Preconditions:
None
Semantics:
Use NU_Get_Events with the NU_NO_TIMEOUT argument to cause it to return immediately.
Postconditions:
Consumes any pending events which were active and specified in eventMask. It returns a mask containing the events which were consumed.
Concurrency:
Synchronous

15.7.6 sleep()

Public member of:
Task
Return Class:
void

Arguments:

unsigned timeout
Documentation:
This function suspends the task for at least timeout number of timer ticks (1/10 second per tick).
Preconditions:
None
Semantics:
Use NU_Sleep to suspend the task
Postconditions:
Once timeout is reached, the task will be scheduled to run.
Concurrency:
Synchronous

15.7.7 waitForEvent()

Public member of:
Task
Return Class:
unsigned

Arguments:

unsigned eventMask
Documentation:
This function causes the task to suspend execution until one or more of the events ids in eventMask is set (via a Task::notify() or TaskManager::broadcast()). The returned eventMask contains the events which were waited for that were notified.
Preconditions:
None
Semantics:
Suspends task execution until one or more event ids in eventMask is set. Use NU_Wait_For_Events with NU_WAIT_FOREVER as the argument.
Postconditions:
Resumes execution
Returns the events which were satisfied
Clears the waited for/received events pending_events
Concurrency:
Synchronous

15.7.8 yield()

Public member of:
Task
Return Class:
void
Documentation:
This function allows other tasks of the same priority level to run. This function will not return until at least all other tasks of the same priority have either suspended, or yielded.
Preconditions:
None
Semantics:
Use NU_Relinquish to give up control
Postconditions:
Once all other tasks of the same priority have suspended or yielded, this function will return.
Concurrency:
Synchronous

15.8 Class SystemClock

Documentation:
This class represents the executive's system clock.
Export Control:
Public
Cardinality:
1

Hierarchy:

Superclasses:

none

Implementation Uses:

Timer
TimerCallback

Public Interface:

Operations:

currentTime()
Concurrency:
Synchronous
Persistence:
Persistent

15.8.1 currentTime()

Public member of:
SystemClock
Return Class:
unsigned
Documentation:
This function returns the number of timer-ticks (1/10 second units) since the point at which interrupts were first enabled after start-up.
Semantics:
Call NU_Read_Time to get the current timer tick count value.
Concurrency:
Synchronous

15.9 Class TimerCallback

Documentation:
This class is responsible for passing control to Nucleus RTX during timer tick interrupt handling.
Export Control:
Public
Cardinality:
1

Hierarchy:

Superclasses:

DevCallback

Public Interface:

Operations:

invoke()
Concurrency:
Synchronous
Persistence:
Persistent

15.9.1 invoke()

Public member of:
TimerCallback
Return Class:
void

Arguments:

IntrDevice* devptr
Documentation:
This function is invoked by the timer device interrupt handler, and is responsible for passing control to Nucleus RTX. devptr points to the device issuing the callback. This function calls the Nucleus CLD_Timer_Interrupt() to maintain its timer tick counter, and perform any time-based context switch preparation.
Concurrency:
Guarded

15.10 Class TaskMonitor

Documentation:
The Task Monitor is responsible for testing each task in the system, including itself, and resetting the watchdog timer as each tested task responds.
Export Control:
Public
Cardinality:
1

Hierarchy:

Superclasses:

Task

Implementation Uses:

Watchdog
TaskManager

Public Interface:

Operations:

TaskMonitor()
goTaskEntry()
respond()

Private Interface:

Has-A Relationships:


Task* curquery: This is a pointer to the task instance currently being queried by the task monitor. If no query is outstanding, this pointer is 0.

const unsigned delay: This is the number of timer ticks to sleep between task queries. Its value is TBD.
Concurrency:
Active
Persistence:
Persistent

15.10.1 TaskMonitor()

Public member of:
TaskMonitor

Arguments:

unsigned taskid
Documentation:
This function is the task's constructor. taskid is the Nucleus RTX identifier associated with the task.
Concurrency:
Sequential

15.10.2 goTaskEntry()

Public member of:
TaskMonitor
Return Class:
void
Documentation:
This is the main entry point for the task monitor. This function consists of an infinite loop, which queries the TaskManager for each task, and then queries each task. As each task responds, this function resets the watchdog timer.
Semantics:
Zero curquery and enter the infinite loop. Touch the watchdogDevice. Pass curquery to taskManager.nextTask() and store in curquery. Query the task using notify(). sleep for delay ticks. Wait for either the responds, or a query. If query, call respond() and try again. Once response is received, repeat infinite loop.
Concurrency:
Synchronous

15.10.3 respond()

Public member of:
TaskMonitor
Return Class:
void
Documentation:
This function is used by the system's tasks (including itself) to respond to queries from the task monitor.
Semantics:
notify taskMonitor that the queried task is alive.
Concurrency:
Synchronous

15.11 Class Semaphore

Documentation:
This class is used to provide a mechanism by which several tasks can coordinate their use of a shareable resource.
Export Control:
Public
Cardinality:
n

Hierarchy:

Superclasses:

none

Public Interface:

Operations:

Semaphore()
release()
request()
retrieveStatus()
waitFor()

Protected Interface:

Has-A Relationships:


unsigned rtxSemId: This variable contains the Nucleus RTX Resource Id associated with this instance of a semaphore.
Concurrency:
Synchronous

15.11.1 Semaphore()

Public member of:
Semaphore

Arguments:

unsigned semId
Documentation:
This is the constructor for the class. semId is the RTX resource id to associate with this instance.
Preconditions:
Nucleus RTX must be running
Semantics:
Store semId in rtxSemId
Postconditions:
The Semaphore is ready to be used.
Concurrency:
Sequential

15.11.2 release()

Public member of:
Semaphore
Return Class:
void
Documentation:
This function unlocks a semaphore, indicating that the associated resource is available for use.
Preconditions:
Resource must already have been locked
Semantics:
Call NU_Release_Resource to indicate that the resource is available.
Postconditions:
Resource must now be unlocked and available. Any tasks which blocked on the resource are now unblocked (but the highest priority task will then get control and re-lock it).
Concurrency:
Synchronous

15.11.3 request()

Public member of:
Semaphore
Return Class:
Boolean
Documentation:
This function provides a non-blocking way of obtaining ownership of a resource. It returns BoolTrue if the semaphore was successfully obtained and locked, and BoolFalse if someone else has already locked it.
Preconditions:
None
Semantics:
Call NU_Request_Resource passing NU_NO_TIMEOUT to prevent blocking.
Postconditions:
If lock is available, lock it and return BoolTrue
If lock is unavailable, return BoolFalse
Concurrency:
Synchronous

15.11.4 retrieveStatus()

Public member of:
Semaphore
Return Class:
Boolean
Documentation:
This function retrieves the status of the semaphore. If locked it returns BoolTrue, otherwise it returns BoolFalse.
Preconditions:
None
Semantics:
Use NU_Retrieve_Resource_Status. Examine number tasks on the resource. 0 tasks means no-one's got it locked.
NOTE: Be careful here. If you get preempted between the query and testing the result, the answer may not be right (hence the Guarded concurrency qualifier on the function).
Postconditions:
If locked, return BoolTrue
If unlocked, return BoolFalse
Concurrency:
Guarded

15.11.5 waitFor()

Public member of:
Semaphore
Return Class:
Boolean

Arguments:

unsigned timeout
Documentation:
This function waits for and obtains a semaphore. If successful, it returns BoolTrue. If timeout, expressed in timer ticks (1/10 second) expires, it returns BoolFalse.
Preconditions:
None
Semantics:
Use NU_Request_Resource, using timeout to bound the blocking time.
Postconditions:
If the lock becomes available, it locks it and returns BoolTrue.
If timeout expires before the lock is released, it returns BoolFalse.
Concurrency:
Synchronous

15.12 Class Queue

Documentation:
The Queue class serves to encapsulate the inter-process queueing facilities of the RTX. It provides the underlying mechanisms to add, retrieve and query queue items. (NOTE: The dequeue, enqueue and waitForItem functions are not type-safe. Subclasses must provide type-safe wrappers around these functions)
Export Control:
Public
Cardinality:
n

Hierarchy:

Superclasses:

none

Public Interface:

Operations:

Queue()
howMany()

Protected Interface:

Operations:

dequeue()
enqueue()
waitForItem()

Has-A Relationships:


unsigned rtxQueueId: This variable holds the Nucleus RTX Queue identifier associated with this instance of a queue.
Concurrency:
Synchronous

15.12.1 Queue()

Public member of:
Queue

Arguments:

unsigned queueId
unsigned itemSize
unsigned itemCnt
Documentation:
This is the constructor for the queue class. queueId identifies which RTX queue to use. itemSize and itemCnt are used to ensure that the queue's parameters match those assumed by the underlying RTX queue instance. itemSize is the maximum number of 32-bit words for any item placed into the queue, and itemCnt is the maximum number of items that can be held by the queue.
Preconditions:
Nucleus RTX must be running
The RTX queue identified by queueId must hold itemCnt elements whose size is itemSize number of words.
Semantics:
Check the queue count and item size against the reference RTX queue. Store the queueId in rtxQueueId
Postconditions:
The queue is ready for use.
Concurrency:
Sequential

15.12.2 dequeue()

Protected member of:
Queue
Return Class:
Boolean

Arguments:

void* item
Documentation:
This function copies the first element from the queue into the buffer pointed to by item, and removes the element from the queue. If no elements are in the queue, the function immediately returns BoolFalse. If the element was successfully copied, it returns BoolTrue.
Preconditions:
The calling subclass MUST ensure that item points to a buffer large enough to hold the size for this element.
Semantics:
Dequeue item into specified buffer using NU_Retrieve_Item
Postconditions:
Buffer pointed to by item contains first element
The first element has been removed from the queue
Concurrency:
Synchronous

15.12.3 enqueue()

Protected member of:
Queue
Return Class:
Boolean

Arguments:

const void* item
Documentation:
Enqueues item into this instances RTX queue. If the queue is full, the function returns BoolFalse, and nothing will be enqueued. If the queue has room, the item is copied, and the function returns BoolTrue.
Preconditions:
Item must point to buffer containing element whose size is less than or equal to the queue item size.
Semantics:
Copy data pointed to by item into the queue, using NU_Send_Item.
Postconditions:
If not full, item's data is appended to the end of the queue and the function returns BoolTrue. If full, nothing copied and function returns BoolFalse.
Concurrency:
Synchronous

15.12.4 howMany()

Public member of:
Queue
Return Class:
unsigned
Documentation:
Returns the number of items in the queue.
Preconditions:
None
Semantics:
Retrieve the number of items in the queue
NOTE: You may get preempted and someone enqueues or dequeues an element before you act on the return value (hence the Guarded concurrency qualifier).
Postconditions:
Returns the number of enqueued items
Concurrency:
Guarded

15.12.5 waitForItem()

Protected member of:
Queue
Return Class:
Boolean

Arguments:

void* item
unsigned timeout
Documentation:
This function attempts to dequeue an element into item. If an element is present, or one is enqueued prior to timeout, item will be filled with a copy of the element and the function returns BoolTrue. If timeout, expressed in timer ticks (1/10 seconds), expires, item is left alone and the function returns BoolFalse.
Concurrency:
Synchronous

15.13 Class MemoryPool

Documentation:
This class manages a collection of equally sized buffers.
Export Control:
Public
Cardinality:
n

Hierarchy:

Superclasses:

none

Public Interface:

Operations:

MemoryPool()
available()

Protected Interface:

Operations:

allocate()
deallocate()
waitForBuffer()

Has-A Relationships:


unsigned rtxPoolId: This variable holds the Nucleus RTX Memory Pool identifier.
Concurrency:
Synchronous

15.13.1 MemoryPool()

Public member of:
MemoryPool

Arguments:

unsigned poolId
unsigned bufsize
unsigned nbufs
Documentation:
This is the constructor for the class. poolId identifies which RTX memory partition to use for this instance. bufsize and nbufs are used to ensure that the pool's parameters match those assumed by the underlying RTX memory pool instance. bufsize is the maximum number of 32-bit words for any buffer contained within the pool, and nbufs is the maximum number of buffers maintained by the pool.
Preconditions:
Nucleus RTX must be running
The RTX memory pool identified by poolId must hold nbufs buffers whose size is bufsize number of words.
Semantics:
Verify pool buffer size and buffer count. Copy poolId to rtxPoolId
Postconditions:
The memory pool is ready for use.
Concurrency:
Sequential

15.13.2 allocate()

Protected member of:
MemoryPool
Return Class:
void *
Documentation:
Attempts to allocate one buffer from this pool. Returns pointer to the buffer on success. Returns 0 if no buffers are available.
Preconditions:
None
Semantics:
Attempt to grab a buffer from the pool using NU_Alloc_Partition
Postconditions:
If buffer is available, decrease space remaining and return ptr to buffer.
If nothing is available, return 0
Concurrency:
Synchronous

15.13.3 available()

Public member of:
MemoryPool
Return Class:
unsigned
Documentation:
Return number of blocks available in this Pool.
Preconditions:
None
Semantics:
Obtain the available number of blocks using NU_Available_Partitions
NOTE: You may be preempted before you use the result, and the higher priority task may allocate or release a buffer, changing the true answer (hence the Guarded concurrency qualifier).
Postconditions:
If pool is empty, return 0 If no blocks are allocated, return maximum number of blocks. If some blocks are allocated, return number of remaining
Concurrency:
Guarded

15.13.4 deallocate()

Protected member of:
MemoryPool
Return Class:
void

Arguments:

void* block
Documentation:
Return Memory Block, pointed to by block, to the pool.
Preconditions:
block must have been allocated from this pool
Semantics:
Release block back to pool using NU_Dealloc_Partition.
Postconditions:
Block is released to pool, available space increases
If tasks were waiting on the empty pool, they are unblocked.
Concurrency:
Synchronous

15.13.5 waitForBuffer()

Protected member of:
MemoryPool
Return Class:
void*

Arguments:

unsigned timeout
Documentation:
This function attempts to allocate a buffer from the pool, and blocks until one is available, or until timeout, specified in timer ticks (1/10 second) is reached. If it succeeds, it returns a non-NULL pointer to the block. If it times out, it returns NULL.
Preconditions:
None
Semantics:
Call NU_Alloc_Partition, passing timeout. If no buffer is available, the task is suspended until a buffer is released by another task, or until timeout is reached. If a buffer becomes available, allocated and return with its pointer.
Postconditions:
If buffer is or becomes available prior to timeout, allocated it and return its pointer. If timeout is reached, return 0.
Concurrency:
Synchronous
 

Table of Contents Next Chapter