ChorusOS 5.0 Features and Architecture Overview

Time Management

The ChorusOS operating system provides the following time management features:

The interrupt-level timing feature is always available and provides a traditional, one-shot, timeout service. Time-outs and the timeout granularity are based on a system-wide clock tick.

When the timer expires, a caller-provided handler is executed directly at the interrupt level. This is generally on the interrupt stack, if one exists, and with thread scheduling disabled. Therefore, the execution environment is restricted accordingly.

General Interval Timer (TIMER)

The TIMER feature implements a high-level timer service for both user and supervisor actors. One-shot and periodic timers are provided, with timeout notification via the execution of a user-provided upcall function by a handler thread in the application actor. Handler threads can invoke any microkernel or subsystem system call. This service is implemented using the TIMEOUT feature.

The extended timer facility uses the concept of a timer object in the actor environment. Timers are created and deleted dynamically. Once created, they are addressed by a local identifier in the context of their owning actor, and are deleted automatically when that actor terminates. Timer objects provide a naming mechanism and a locus of control for timing activities. All high-level timer operations, for example, setting, modifying, querying, or canceling pending timeouts, refer to timer objects. Timer objects are also involved in coordination with the threads used to execute application-level notification handlers.

Applications will typically use extended timer functions via a standard application-level library (see "POSIX Timers (POSIX-TIMERS)"). Timer handler threads are created and managed by this library. The library is expected to preallocate stack area for the notification functions, create the thread, and initialize the thread's priority, per-thread data, and all other aspects of its execution context, using standard system calls. The thread then declares itself available for execution of the tier notification (timerThreadPoolWait(2K)) system call to wait for the first or next relevant timeout event. Event arrival will cause the thread to return from the system call, at which point the library code can call the application's handler. The thread pool interface is designed to allow one or a small number of handler threads to service an arbitrary number of timers. An application can thus create a large number of handlers without the expense of a dedicated handler thread for each one.

At most, a single notification will be active for a given timer at any point in time. If no handler thread is available when the timer interval expires, either because the notification function is still executing from a previous expiration or because the handler thread(s) is(are) occupied executing notifications for other timers, an overrun occurs. When a handler thread becomes available (namely, re-executes timerThreadPoolWait()), it will return immediately and the notification function can be invoked immediately. At return from timerThreadPoolWait(), an overrun count is delivered to the thread. An overrun count value pertains to a particular execution of the notification function. The overrun count is defined as the number of timer expirations that have occurred since the preceding invocation of the notifying function without a handler thread being available. Thus for a periodic timer, an overrun count equal to one indicates that the current invocation was delayed, but by less than the period interval.

For details, see the TIMER(5FEA) man page.

TIMER API

The general interval timer (TIMER) API is summarized in the following table:

Function 

Description 

timerThreadPoolInit()

Initialize a thread pool 

timerThreadPoolWait()

Wait for timer events 

timerCreate()

Create a timer 

timerDelete()

Delete a timer 

timerGetRes()

Get timer resolution 

timerSet()

Set a timer 

Virtual Timer (VTIMER)

The VTIMER feature is responsible for all functions pertaining to measurement and timing of thread execution. It exports a number of functions that are used typically by higher-level operating system subsystems, such as, UNIX.

VTIMER functions include thread accounting (threadTimes(2K)) and virtual timeouts (svVirtualTimeoutSet(2K) and svVirtualTimeoutCancel(2K)). A virtual timeout handler is entered as soon as the designated thread or threads have consumed the specified amount of execution time. Virtual timeouts can be set either on individual threads, for support of subsystem-level virtual timers (for example, SVR4, setitimer, VIRTUAL, and PROF timers), or on entire actors, for support of process CPU limits.

A virtual timeout handler is entered as soon as one or more designated threads have consumed the specified amount of execution time.

Execution time accounting can be limited to execution in the thread's home actor (internal execution time), or can include cross-actor invocations such as system calls (total execution time).

The svThreadVirtualTimeout() and svThreadActorTimeout() handlers are invoked at thread level and thus can use any API service, including blocking system calls. Timeout events are delivered to application threads, such as threadAbort(), that is, a thread executes a virtual time handler on its own behalf.

For details about virtual time, see the VTIMER(5FEA) man page

VTIMER API

The virtual time API is summarized in the following table:

Function 

Description 

svActorVirtualTimeoutCancel()

Cancel an actor virtual timeout 

svActorVirtualTimeoutSet()

Set an actor virtual timeout 

svThreadVirtualTimeoutCancel()

Cancel a thread virtual timeout 

svThreadVirtualTimeoutSet()

Set a thread virtual timeout 

svVirtualTimeoutCancel()

Cancel a virtual timeout 

svVirtualTimeoutSet()

Set a virtual timeout 

threadTimes()

Get thread execution times 

virtualTimeGetRes()

Get virtual time resolution 

Time of Day (DATE)

The DATE feature maintains the time of day expressed in Universal Time, which is defined as the interval since 1st January 1970. Since the concept of local time is not supported directly by the operating system, time-zones and local seasonal adjustments must be handled by libraries outside the microkernel.

For details, see the DATE(5FEA) man page.

DATE API

The DATE API is summarized in the following table:

Function 

Description 

univTime()

Get time of day 

univTimeAdjust()

Adjust time of day 

univTimeGetRes()

Get time of day resolution 

univTimeSet()

Set time of day 

Date Management

ChorusOS 5.0 provides time and date management services that comply to Time Zone and Day Light Saving Time behaviors.

Date Management API

The date management utilities and API is summarized in the following table:

Function 

Description 

date()

Print or/and set the date 

settimeoftheday()

System call to set the time of the day 

gettimeoftheday()

System call to get the time of the day 

adjtime()

System call to adjust the time of the day smoothly (used by the Network Time Protocol, NTP) 

ctime()

Returns time argument as local time in ASCII string 

localtime()

Returns time argument as local time in a structure 

gmtime()

Returns time argument without local adjustment 

asctime()

Returns ASCII time from time structure argument 

mktime()

Returns time value from time structure argument 

strftime()

Format printf like time from structure argument 

tzset()

Set time zone information for time conversion routines 

Real-Time Clock (RTC)

The RTC feature indicates whether a real-time clock (RTC) device is present on the target machine. When this feature is set and an RTC is present on the target, the DATE feature will retrieve time information from the RTC. If the RTC feature is not set, indicating an RTC is not present on the target, the DATE feature will emulate the RTC in software.

For details, see the RTC(5FEA) man page.

Watchdog Timer (WDT)

The watchdog timer feature enables a two-step watchdog mechanism on hardware. It consists of a lower-level system layer provided by the driver, that exposes a DDI, and a higher-level layer that hides the DDI and provides an easier API for any user program. The watchdog itself has two steps:

The interrupt step:

If the watchdog is not patted within a certain delay, an interrupt handler provided by the system is invoked. This interrupt handler attempts to shut down the system and to perform a system dump of the node to collect evidence of the problem.

The reset step:

If the interrupt step gets stuck or lasts too long, the watchdog resets the board, causing it to reboot.

The watchdog is either started by the system at system initialization or possibly by the boot loader. It is expected that a dedicated user-level process will be responsible for patting the watchdog throughout the normal life of the system. A failure in the patting process will lead to the interrupt step of the watchdog mechanism.

To cope gracefully with transitions at initialization time, as well as at system shut-down time, the system is designed to pat the watchdog by itself for a configurable amount of time at system initialization and system shut down. During these periods, where a patting process in user mode might not be possible, the system will play that role implicitly. However, the duration of these initialization and shut-down periods is bound to system configurable values, so it is impossible for initialization to reach the point where the user-level patting process begins without the watchdog interrupt occurring. Similarly, shut down is guaranteed to be bound, or the watchdog interrupt will occur.

Some hardware can support more than one watchdog. The API copes with such situations by associating handles to watchdogs. The WDT feature API is similar to the watchdog API for the Solaris operating environment.

For details on watchdog timer, see the WDT(5FEA) man page.

WDT API

The watchdog timer API is summarized in the following table:

Function 

Description 

wdt_pat()

Pat (reload) the watchdog timer 

wdt_alloc()

Allocate a watchdog timer 

wdt_realloc()

Reallocate a watchdog timer 

wdt_free()

Disarm and free a watchdog timer 

wdt_get_maxinterval()

Get the maximum limit (hardware) of a watchdog 

wdt_set_interval()

Set the interval duration of a watchdog 

wdt_get_interval()

Get the interval duration of a watchdog 

wdt_arm()

Arm a watchdog 

wdt_disarm()

Disarm a watchdog 

wdt_is_armed()

Check whether a watchdog is armed 

wdt_startup_commit()

Tells the system the initialiazation phase is over 

wdt_shutdown()

Tells the system to start patting for shut down 


Note -

The wdt_realloc() function enables a process to regain control over a watchdog allocated by a possibly dead process.


Benchmark Timing (PERF)

The benchmark timing (PERF) feature provides a very precise measurement of short events. It is used primarily for performance benchmarking.

The PERF API closely follows that of the TIMER feature.

For details, see the PERF(5FEA) man page.

High Resolution Timing

The high resolution timer feature provides access to a fine-grained counter source for applications. This counter is used for functions such as fine-grained ordering of events in a node, measurements of short segments of code and fault-detection mechanisms between nodes.

The high resolution timer has a resolution better than or equal to one microsecond, and does not roll over more than once per day.

High Resolution Timer API

The high resolution timer API is summarized in the following table:

Function 

Description 

hrTimerValue()

Get the current value of the fine-grained timer in ticks 

hrTimerFrequency()

Get the frequency of the fine-grained timer in Hertz 

hrTimerPeriod()

Get the difference between the minimum and the maximum of the possible values of the fine-grained timer in ticks