The infrastructure provides support for implementing a select mechanism. This is modeled on the mechanism in the BSD kernel, but has been modified to make it implementation independent.
The main part of the mechanism is the select()
API call. This processes its arguments and calls the
fo_select()
function pointer on all file objects
referenced by the file descriptor sets passed to it. If the same
descriptor appears in more than one descriptor set, the
fo_select()
function will be called separately
for each appearance.
The which
argument of the
fo_select()
function will either be
CYG_FREAD to test for read conditions,
CYG_FWRITE to test for write conditions or zero to
test for exceptions. For each of these options the function should
test whether the condition is satisfied and if so return true. If it
is not satisfied then it should call
cyg_selrecord()
with the
info
argument that was passed to the function
and a pointer to a cyg_selinfo
structure.
The cyg_selinfo
structure is used to record information about current
select operations. Any object that needs to support select must
contain an instance of this structure. Separate cyg_selinfo
structures should be kept for each of the options that the object can
select on - read, write or exception.
If none of the file objects report that the select condition is
satisfied, then the select()
API function puts
the calling thread to sleep waiting either for a condition to become
satisfied, or for the optional timeout to expire.
A selectable object must have some asynchronous activity that may
cause a select condition to become true - either via interrupts or the
activities of other threads. Whenever a selectable condition is
satisfied, the object should call cyg_selwakeup()
with a pointer to
the appropriate cyg_selinfo
structure. If the thread is still waiting,
this will cause it to wake up and repeat its poll of the file
descriptors. This time around, the object that caused the wakeup
should indicate that the select condition is satisfied, and the
select()
API call will return.
Note that select()
does not exhibit real time
behaviour: the iterative poll of the descriptors, and the wakeup
mechanism mitigate against this. If real time response to device or
socket I/O is required then separate threads should be devoted to each
device of interest and should use blocking calls to wait for a
condition to become ready.