At the lowest level the communication between Venus and the FS driver proceeds through messages. The synchronization between processes requesting Coda file service and Venus relies on blocking and waking up processes. The Coda FS driver processes VFS- and pioctl-requests on behalf of a process P, creates messages for Venus, awaits replies and finally returns to the caller. The implementation of the exchange of messages is platform specific, but the semantics have (so far) appeared to be generally applicable. Data buffers are created by the FS Driver in kernel memory on behalf of P and copied to user memory in Venus.
The FS Driver while servicing P makes
upcall's to Venus.
Such an upcall is dispatched to Venus by creating a message structure.
The structure contains the identification of P, the message sequence
number, the size of the request and a pointer to the data in kernel
memory for the request. Since the data buffer is re-used to hold the
reply from Venus, there is a field for the size of the reply. A flags
field is used in the message to precisely record the status of the
message. Additional platform dependent structures involve pointers to
determine the position of the message on queues and pointers to
synchronization objects. In the
upcall routine the message
structure is filled in, flags are set to 0, and it is placed on the
pending queue. The routine calling
responsible for allocating the data buffer; it's structure will be
described in the next section.
A facility must exist to notify Venus that the message has been
created, and implemented using available synchronization objects in
the OS. This notification is done in the
upcall context of the
process P. When the message is on the pending queue, process P cannot
upcall. The (kernel mode) processing of P in the
filesystem request routine must be suspended until Venus has replied.
Therefore the calling thread in P is blocked in
pointer in the message structure will locate the synchronization
object on which P is sleeping.
Venus detects the notification that a message has arrived, and the FS
driver allow Venus to retrieve the message with a
getmsg_from_kernel call. This action finishes in the kernel
by putting the message on the queue of processing messages and setting
flags to READ. Venus is passed the contents of the data buffer. The
getmsg_from_kernel call now returns and Venus processes the
At some later point the FS driver receives a message from Venus,
namely when Venus calls
sendmsg_to_kernel. At this moment
the Coda FS driver looks at the contents of the message and decides
sendmsg_to_kernelcall returns to Venus. The process P will be scheduled at some point and continues processing its
upcallwith the data buffer replaced with the reply from Venus.
Now P awakes and continues processing
upcall. There are some
subtleties to take account off. First P will determine if it was woken
upcall by a signal from some other source (for example an
attempt to terminate P) or as is normally the case by Venus in its
sendmsg_to_kernel call. In the normal case, the upcall routine
will deallocate message structure and return. The FS routine can
proceed with its processing.
In case P is woken up by a signal and not by Venus, it will first look at the flags field. If the message is not yet READ, the process P can handle it's signal without notifying Venus. If Venus has READ, and the request should not be processed, P can send Venus a signal message to indicate that it should disregard the previous message. Such signals are put in the queue at the head, and read first by Venus. If the message is already marked as WRITTEN it is too late to stop the processing. The VFS routine will now continue.
If a VFS request involves more than one upcall, this can lead to complicated state, an extra field "handle_signals" could be added in the message structure to indicate points of no return have been passed.
The Unix implementation of this mechanism has been through the
implemenation of a character device associated with Coda. Venus
retrieves messages by doing a
read on the device, replies are
sent with a
write and notification is through the
system call on the file descriptor for the device. The process P is
kept waiting on an interruptible wait queue object.
In Windows NT and the DPMI Windows 95 implementation a DeviceIoControl
call is used. The DeviceIoControl call is designed to copy buffers
from user memory to kernel memory with OPCODES. The
sendmsg_to_kernel is issued as a synchronous call, while the
getmsg_from_kernel call is asynchrounous. Windows EventObjects
are used for notification of message arrival. The process P is kept
waiting on a KernelEvent object in NT and a semaphore in Windows 95.