<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9"> <TITLE> The Venus kernel interface: The message layer </TITLE> <LINK HREF="kernel-venus-protocol-4.html" REL=next> <LINK HREF="kernel-venus-protocol-2.html" REL=previous> <LINK HREF="kernel-venus-protocol.html#toc3" REL=contents> </HEAD> <BODY> <A HREF="kernel-venus-protocol-4.html">Next</A> <A HREF="kernel-venus-protocol-2.html">Previous</A> <A HREF="kernel-venus-protocol.html#toc3">Contents</A> <HR> <H2><A NAME="s3">3. The message layer </A></H2> <P> <P>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. <P>The FS Driver while servicing P makes <CODE>upcall</CODE>'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 <CODE>upcall</CODE> routine the message structure is filled in, flags are set to 0, and it is placed on the <EM>pending</EM> queue. The routine calling <CODE>upcall</CODE> is responsible for allocating the data buffer; it's structure will be described in the next section. <P>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 <CODE>upcall</CODE> context of the process P. When the message is on the pending queue, process P cannot proceed in <CODE>upcall</CODE>. 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 <CODE>upcall</CODE>. A pointer in the message structure will locate the synchronization object on which P is sleeping. <P>Venus detects the notification that a message has arrived, and the FS driver allow Venus to retrieve the message with a <CODE>getmsg_from_kernel</CODE> 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 <CODE>getmsg_from_kernel</CODE> call now returns and Venus processes the request. <P>At some later point the FS driver receives a message from Venus, namely when Venus calls <CODE>sendmsg_to_kernel</CODE>. At this moment the Coda FS driver looks at the contents of the message and decides if: <P> <UL> <LI> the message is a reply for a suspended thread P. If so it removes the message from the processing queue and marks the message as WRITTEN. Finally, the FS driver unblocks P (still in the kernel mode context of Venus) and the <CODE>sendmsg_to_kernel</CODE> call returns to Venus. The process P will be scheduled at some point and continues processing its <CODE>upcall</CODE> with the data buffer replaced with the reply from Venus. </LI> <LI> The message is a <EM>downcall</EM>. A downcall is a request from Venus to the FS Driver. The FS driver processes the request immediately (usually a cache eviction or replacement) and when finishes <CODE>sendmsg_to_kernel</CODE> returns.</LI> </UL> <P>Now P awakes and continues processing <CODE>upcall</CODE>. There are some subtleties to take account off. First P will determine if it was woken up in <CODE>upcall</CODE> by a signal from some other source (for example an attempt to terminate P) or as is normally the case by Venus in its <CODE>sendmsg_to_kernel</CODE> call. In the normal case, the upcall routine will deallocate message structure and return. The FS routine can proceed with its processing. <P> <P> <FIGURE> <EPS FILE="sleep"> <CAPTION> <A NAME="ServerOrg"></A> Sleeping and IPC arrangements</CAPTION> </FIGURE> <P>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. <BLOCKQUOTE>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.</BLOCKQUOTE> <P> <P> <H2><A NAME="ss3.1">3.1 Implementation details </A> </H2> <P>The Unix implementation of this mechanism has been through the implemenation of a character device associated with Coda. Venus retrieves messages by doing a <CODE>read</CODE> on the device, replies are sent with a <CODE>write</CODE> and notification is through the <CODE>select</CODE> system call on the file descriptor for the device. The process P is kept waiting on an interruptible wait queue object. <P>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 <CODE>sendmsg_to_kernel</CODE> is issued as a synchronous call, while the <CODE>getmsg_from_kernel</CODE> 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. <P>\newpage <HR> <A HREF="kernel-venus-protocol-4.html">Next</A> <A HREF="kernel-venus-protocol-2.html">Previous</A> <A HREF="kernel-venus-protocol.html#toc3">Contents</A> </BODY> </HTML>