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
upcall
is 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 proceed in
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
upcall
. A 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 request.
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 if:
sendmsg_to_kernel
call
returns to Venus. The process P will be scheduled at some point and
continues processing its
upcall
with the data buffer
replaced with the reply from Venus.
sendmsg_to_kernel
returns.
Now P awakes and continues processing
upcall
. There
are some subtleties to take account off. First P will determine if
it was woken up in
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
select
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.
\newpage