event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
NAME
eventcounters: vpaddtoecvalue, vpadvanceec, vpawaitec,
vpconvertclockvaluetoecvalue,
vpconvertecvaluetoclockvalue, vpgetnextecvalue,
vphaseventoccurred, vpincrementecvalue, vpinitializeec,
vpinitializesequencer, vpreadec, vpticketsequencer,
vpareecvaluesequal - handle event counters
SYNOPSIS
#include "/usr/src/uts/aviion/ii/ivp.h"
void vpaddtoecvalue (ecvalueptr, addend)
vpecvalueptrtype ecvalueptr; /*READ/WRITE*/
uint32type addend; /*READ ONLY*/
void vpadvanceec (ecname)
vpecptrtype ecname; /*READ ONLY*/
booleantype vpareecvaluesequal (value1ptr, value2ptr)
vpecvalueptrtype value1ptr; /*READ ONLY*/
vpecvalueptrtype value2ptr; /*READ ONLY*/
void vpawaitec (eventlist, listsize, listindexptr)
vpeventtype eventlist[]; /*READ ONLY*/
int32type listsize; /*READ ONLY*/
int32ptrtype listindexptr; /*WRITE ONLY*/
void vpconvertclockvaluetoecvalue (clockvalueptr,
ecvalueptr)
miscclockvalueptrtype clockvalueptr; /*READ ONLY*/
vpecvalueptrtype ecvalueptr; /*WRITE ONLY*/
void vpconvertecvaluetoclockvalue (ecvalueptr,
clockvalueptr)
vpecvalueptrtype ecvalueptr; /*READ ONLY*/
miscclockvalueptrtype clockvalueptr; /*WRITE ONLY*/
void vpgetnextecvalue (ecname, ecvalueptr)
vpecptrtype ecname; /*READ ONLY*/
vpecvalueptrtype ecvalueptr; /*WRITE ONLY*/
booleantype vphaseventoccurred (eventptr)
vpeventptrtype eventptr; /*READ ONLY*/
void vpincrementecvalue (ecvalueptr)
vpecvalueptrtype ecvalueptr; /*READ WRITE*/
void vpinitializeec (ecname)
vpecptrtype ecname; /*READ ONLY*/
void vpinitializesequencer (seqname)
vpecptrtype seqname; /*READ ONLY*/
Licensed material--property of copyright holder(s) 1
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
void vpreadec (ecname, ecvalueptr)
vpecptrtype ecname; /*READ ONLY*/
vpecvalueptrtype ecvalueptr; /*WRITE ONLY*/
void vpticketsequencer (seqname, seqvalueptr)
vpecptrtype seqname; /*READ ONLY*/
vpecvalueptrtype seqvalueptr; /*WRITE ONLY*/
where:
addend The value to be added to the event-counter value.
clockvalueptr A pointer to a clock value or to the location where
the clock value is to be written.
ecname A pointer to the event counter to be advanced,
initialized, or read.
ecvalueptr A pointer to an event-counter value or to the
location where the event-counter value (or the event-
counter value plus one) is to be written.
eventlist An array of events for which the process will await.
eventptr A pointer to the subject event.
listindexptr A pointer to the array index (zero based) of an event
that is satisfied when the call returns.
listsize The number of elements in eventlist.
seqname A pointer to the sequencer to be initialized or
ticketed.
seqvalueptr A pointer to the location in which the new value of
the sequencer is to be written.
value1ptr A pointer to an event-counter value.
value2ptr A pointer to an event-counter value.
DESCRIPTION
The following routines are described in this man page:
vpaddtoecvalue Add amount to event counter
vpadvanceec Add one to an event counter
vpawaitec Perform await operation on one or
more events
vpconvertclockvaluetoecvalue Convert a clock value into an
event-counter value
vpconvertecvaluetoclockvalue Convert an event-counter value
into a clock value
vpgetnextecvalue Return event-counter value plus
one
vphaseventoccurred Determine whether event has
occurred
vpincrementecvalue Increment event-counter value
vpinitializeec Set event counter to zero
vpinitializesequencer Set sequencer to zero
vpreadec Read specified event counter
vpticketsequencer Add 1 to sequencer and return
value in variable
vpareecvaluesequal Compare two event-counter values
Overview to Using Event Counters
Event counters are the primary synchronization mechanism used in the
DG/UX kernel. The DG/UX system's treatment of event counters and the
Licensed material--property of copyright holder(s) 2
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
related concept of a sequencer comes from work by Reed and Kanodia.
See the Communications of the ACM papers listed in the "Other
Documents" section of the Preface to Programming in the DG/UX
Environment for more technical background on event counters and
sequencers.
The event-counter synchronization mechanism uses two basic elements:
event counters and events. An event counter is simply a count of the
number of times some condition of interest has happened. You create
an event counter by declaring a variable of event-counter type and
then initializing its count value to zero by calling
vpinitializeec.
Events are separate from event counters. Event counters allow you to
define "events" of interest by connecting an event counter with a
critical value. When the eventcount is equal to the critical value,
the event is said to be "satisfied" and the kernel automatically
awakens all processes waiting on the event. You create an event by
declaring a variable of event type (vpeventtype) and filling in the
name of the event counter (pointer to its count address) and the
critical value. Typically, you will define an event counter globally
and create successive events from it.
Typically, you will also want to wait for the event to occur once you
have created it. You do this by calling vpawaitec. The
vpawaitec routine actually allows you to suspend waiting for any of
a number of events supplied in an event list. If one or more of the
specified events is already satisfied when the await call is made,
await returns immediately and the process continues execution. If
none of the specified events is satisfied, the process enters the
awaiting state where it does not compete for CPU resources. Because
a process doing a vpawaitec may suspend indefinitely, it should
only hold locks while awaiting an event that can be counted on
occurring in a reasonable time (perhaps a second or less).
When one of the events is satisfied, the kernel will awaken the
waiting process and pass it the index of the event that has occurred.
The index identifies the event in the list that caused the await to
be satisfied. However, the event specified by the index is not
necessarily the only event that has occurred in the list. You may
determine if other events in the list have occurred by calling the
routine vphaseventoccurred for each entry in the event list. Note
that if you want to wait until ALL of the desired events have
occurred, you may need to do several calls to vpawaitec.
Frequently, the event you will want to create is the next occurrence
of the condition, that is, the next increment of the event counter.
You can create such an event by: 1) calling vpreadec which reads
the current count into an event value variable; and 2) calling
vpincrementec which adds one to that count value--making a critical
value equal to "the next occurrence." Alternatively, you can call
vpgetnextecvalue to perform these two steps in one indivisible
step; it reads and returns an incremented count into an event value
variable.
Licensed material--property of copyright holder(s) 3
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
Some part of your code will also have to increment the event counter
each time the condition of interest occurs. You increment (advance)
the event counter by calling vpadvanceec. After incrementing the
specified event counter, the advance operation checks to see whether
the new value of the incremented event counter causes any events to
be satisfied. If the process associated with a satisfied event is
still in the awaiting state, it is scheduled to run. Because
interrupts are one common condition of interest, interrupt service
routines are frequently the ones calling vpadvanceec.
Because event counters are monotonically increasing values, they map
very well into the normal concepts of clocks and times. This allows
clocks routines and timer routines to be based on the same event-
counter mechanism. A clock can be considered an event counter, and
when the clock reaches a certain value an event is triggered. The
two routines vpconvertclockvaluetoecvalue and
vpconvertecvaluetoclockvalue allow you to convert between clock
and event-counter values.
Because event counters are monotonically increasing values, they also
provide a natural ordering of events. This allows the event-counter
mechanism to be extended to support sequencing using the concept of
"sequencers." Often simply waiting on an event is not enough; what
is wanted is a way of ordering, or sequencing, the waiters on an
event. This is often the case when the event being awaited is access
to a resource of some sort, such as a critical section of code or
shared data. Sequencers support such ordering.
Sequencers, like event counters, are simply counters with values that
increase in a monotonic fashion. Like event counters, sequencers are
declared and initialized (in sequencer's case, by calling
vpinitializesequencer). Sequencers order events by issuing
sequential "tickets." You get a ticket by calling
vpticketsequencer which atomically increments the current value of
the sequencer and returns the new value. Thus, each caller of the
ticket operation gets a unique value and the values are ordered by
the order in which the calls to ticket were made: the first caller
will get 1, the second 2, and so on. You create events using these
ticket values and await them using vpawaitec. Each process will
see its event in turn--in the same order as the sequencer values.
This is exactly the same as in any store where you "take a number for
service."
Event counters offer several advantages over the more simplistic
synchronizations techniques used in most standard UNIX
implementations. First, because event counters actually count the
number of occurrences of an event, you can tell if an event has
already happened. Thus, in a sense event counters remember previous
events. If code tries to wait on an event that has already happened
(the event's critical value is less than the current count), the wait
returns immediately because the event has been satisfied. There is
no danger of the waiting process pending forever as with the standard
UNIX sleep and wakeup primitives.
Licensed material--property of copyright holder(s) 4
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
The vpareecvaluesequal routine for comparing event-counter values
is provided for convenience.
You must be careful of the order in which you perform the tasks
involved in creating and awaiting an event lest you accidentally
create an endless wait situation. Specifically, if you start the I/O
operation to be awaited before you create the event, the I/O may be
logged before you get the event counter and the condition you create
will be one count past the operation you started. The best sequence
for creating and awaiting events is: 1) create the event to be
awaited; 2) start the I/O operation; 3) check the event; 4) if it is
not satisfied (and you do want to suspend until it is), start the
await process. The typical code sequence is as follows:
devcirdbuildscattergatherarrays(requestblockptr);
requestcompletionevent.name = &requestblockptr->syncioec;
vpgetnextecvalue(&requestblockptr->syncioec,
&requestcompletionevent.value);
status = devcirdstartcommandlistrequest(requestblockptr);
if (status == OK)
{
vpawaitec(&requestcompletionevent, (int32type)1,
&resultindex);
}
If you use routines from this man page, you must allocate the space
used by the event and event-counter instances (see the Constants and
Data Structures subsection below). Event counters are normally
allocated from global memory. Event types are allocated dynamically,
as needed.
Constants and Data Structures
This subsection describes constants and data structures defined in
the include files cited in the SYNOPSIS section and used by the
routines documented in this man page.
Try to avoid dependencies on the specifics of these structures, such
as size or location of fields, because these specifics may change in
later releases of the software. You can verify exact variable
definitions in the appropriate include file. The best way to avoid
such dependencies is to use kernel-supplied routines to manipulate
these structures.
vpeventtype
typedef struct
{
vpecptrtype name;
vpecvaluetype value;
}
vpeventtype ;
This structure defines an event, which is an event counter name and
an event-counter value. The event is said to occur or to be
satisfied when the value of the event counter pointed to by the name
field is greater than or equal to the value field.
Licensed material--property of copyright holder(s) 5
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
vpaddtoecvalue
This routine adds the given value to the specified event-counter
value. The specified 32-bit integer is added to the specified event-
counter value.
vpadvanceec
This routine performs an advance (by one) on the specified event
counter. Any processes awaiting on the new value of the event
counter will be notified.
The event counter is indivisibly incremented, and any processes
awaiting on the new value are notified. If a higher priority process
becomes eligible to run as a result of the notification, it may be
rescheduled. Thus, your process may be preempted if you call this
routine.
vpareecvaluesequal
This routine compares two event-counter values for equality. This
routine compares two event-counter values and returns TRUE if they
are equal.
vpawaitec
This routine performs the await operation on one or more events. The
calling process will be suspended until at least one of the specified
events is satisfied.
This routine causes the calling process to be suspended until anyone
of the supplied events has been satisfied. If any of the events is
satisfied at the time the call is made, the process is not suspended.
When the call returns, the listindexptr is set to the index of an
event that is satisfied, but if more than one event is satisfied, no
statement is made about which event will be indicated by
listindexptr.
vpconvertclockvaluetoecvalue
This routine converts a clock value into an event-counter value.
Converting from clock value to event-counter value requires
converting the 64-bit clock value to a 32-bit event-counter value.
The number of bits to take from the high and low word of the clock
value are defined in ivp.h as VPCLOCKTOECHIGHBITS and
VPCLOCKTOECLOWBITS.
vpconvertecvaluetoclockvalue
This routine converts an event-counter value into a clock value.
Conversion from event-counter value to clock value requires
converting a 32-bit event-counter value to a 64-bit clock value.
The number of bits to assign to the high and low word of the clock
value are defined in ivp.h as VPCLOCKTOECHIGHBITS and
VPCLOCKTOECLOWBITS.
vpgetnextecvalue
This routine indivisibly reads the specified event counter and
Licensed material--property of copyright holder(s) 6
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
returns its value plus one.
The event counter is read indivisibly with respect to other
processors and with respect to the executing processor's interrupt
level. The value is then increased by one, which is equal to the
value that will be reached the next time the event counter is
advanced.
vphaseventoccurred
This routine determines whether the given event has occurred.
vpincrementecvalue
This routine increments the specified event-counter value. The
routine simply takes the event-counter value passed in and increments
it.
vpinitializeec
This routine initializes an event counter to zero.
vpinitializesequencer
This routine initializes a sequencer to zero.
vpreadec
This routine indivisibly reads the specified event counter and
returns the value in the variable pointed to by ecvalueptr.
The event counter is read indivisibly with respect to other
processors and with respect to the executing processor's interrupt
level.
vpticketsequencer
This routine indivisibly increments the value of the specified
sequencer and returns the new value (that is, the value after the
increment).
The sequencer value is incremented and then read as an indivisible
operation.
DIAGNOSTICS
Return Value
For vpareecvaluesequal:
TRUE The event-counter values are equal.
FALSE The event-counter values are not equal.
For vphaseventoccurred:
TRUE The event has been satisfied.
FALSE The event has not yet occurred.
For the other routines: none.
Errors
None.
Licensed material--property of copyright holder(s) 7
event_counters(3K) DG/UX 5.4R3.00 event_counters(3K)
SEE ALSO
systemclock(3K).
Programming in the DG/UX Kernel Environment.
Licensed material--property of copyright holder(s) 8