Name

Time change notification — Registering and deregistering for notification of changes to system time

Synopsis

#include <cyg/clock/api.h>

Cyg_ErrNo cyg_clock_timechange_register(cyg_clock_timechange_info *info);

Cyg_ErrNo cyg_clock_timechange_deregister(cyg_clock_timechange_info *info);

Description

These functions are used to allow users of this package to register and deregister for notifications of changes to system time. This may help allow the user to know when to update any timers or alarms.

Parameters which affect the method of delivering notifications are passed in within the info function argument. Other fields in that same structure are then used to pass information about time updates back to the user when a time change event occurs, which happens as a consequence of calls to either cyg_clock_set_systime() or to cyg_clock_adjust_systime().

There are two primary mechanisms for notification: the user may supply a callback function; or the user can supply a condition variable, which they may then wait on to be signalled.

The cyg_clock_timechange_info structure is defined by including <cyg/clock/api.h> and has the following contents relevant to the user:

/* Forward definition to avoid circular dependency */
struct cyg_clock_timechange_info_s;

typedef struct cyg_clock_timechange_info_s cyg_clock_timechange_info;

typedef void (cyg_clock_timechange_cb_fn_t)( cyg_clock_timechange_info *changeinfo );

struct cyg_clock_timechange_info_s {
    CYG_ADDRWORD                  userdata;
    cyg_drv_mutex_t               *mutex;
    cyg_drv_cond_t                *cv;
    cyg_clock_timechange_cb_fn_t  *cb;

    /* VALUES ABOVE ARE SET BY USER BEFORE REGISTRATION
     * VALUES BELOW ARE SET BY THE CLOCK PACKAGE ON TIME CHANGE EVENTS
     */

    cyg_bool                      adjtime;
    struct timespec               newtime;
    struct timespec               offset;
};

Other members of this structure exist, but are private to the common clock package's implementation and do not form part of the API. They must not be modified by the user.

The cyg_clock_timechange_info structure passed in must be persistent while the registration is in effect, as it will be used by the common clock package to maintain the registration. The address of the same structure object must be passed in on deregistration.

cyg_clock_timechange_info details

Here is a description of the purpose of each of the cyg_clock_timechange_info structure members:

userdata

This is user-supplied data, which the user is free to set to any value if it may help uniquely identify the registration.

This value must be set prior to registration.

mutex

If non-NULL, a mutex protecting this structure's contents. Once registered with the clock package, it must be locked before reading/writing the cyg_clock_timechange_info structure to avoid any chance of simultaneous access. It is not mandatory in case users can guarantee non-simultaneous access by some other means.

This value must be set prior to registration.

cv

If non-NULL, a condition variable which should be signalled when time is updated. It must be associated with the above mutex. It should not be used if setting a callback function.

This value must be set prior to registration.

cb

If non-NULL, a user-supplied callback function to be called on time changes. It should not be used if the cv condition variable has been set to be signalled.

This value must be set prior to registration.

adjtime

The value of this boolean field is set by the common clock package on time change events. It will be true if is this is a fine adjustment (from cyg_clock_adjust_systime()), or false if the time has been set with cyg_clock_set_systime().

If reading this field, but before unlocking the mutex (if applicable) it must be reset to true. This is because the clock package will only ever set it from true to false, never from false to true. This is so that if multiple time change events occur before the user has processed any of the events, an indication that the time was "set" will override any indication of fine adjustment.

If the time update was due to a fine adjustment (adjtime is true) then the time change will not necessarily have yet been reflected in what can be read from the system clock - the effect on the system clock happens over a period of time as described earlier.

This field does not need to be initialized prior to registration.

newtime
The new time at the point the time update happened. Note that the relevance of this depends on the real-time properties of the program - if the system has been busy performing other operations, including consequences of notifying other users, it may be quite a long time in the past by the time the user can process the event.
offset

The offset (difference) from the previous time. If it is positive, the time moved forwards, if negative, the time moved backwards.

It is a mandatory part of the API contract that after reading this value, but before unlocking the mutex (if applicable) it must be reset to 0. This is required so that if multiple time changes occur before any of the events are processed by the API user, the effect on offset can be cumulative - the clock package can simply modify the existing offset, thus guaranteeing that when the user reads the offset, it will be the offset since it was last read by the user.

Using a callback function

Some special care is required if using the callback function method for notifications.

If a callback function is used, it must be brief, as further users of this package who have registered a callback will not be notified until the callback returns. For this reason, and to improve determinism, and to avoid delaying clock package operations, the condition variable approach should be preferred.

The callback function method is still available however as it is realized that sometimes there may be no alternative.

Users should not call back into any time-keeping functions (in this package or others) from a callback function, in order to avoid re-entrancy issues. An exception is for the time conversion functions.

Even with a callback function, it is recommended to still use a mutex lock to prevent the timechange info structure being updated while it is in the process of being read; and if such a mutex is provided with the 'mutex' member, it will be locked before the callback is called, and unlocked after.

Return value

These functions return a standard error code, as defined in <errno.h>, or ENOERR on success.