HP OpenVMS Systems Documentation

Content starts here

VMS DECwindows Transport Manual

Previous Contents Index

2.3 Transporting the Protocol Request

Once the transport layer receives the output request buffer from Xlib, it arranges to have the data transmitted to the server. The transport layer on the server side of the connection receives the data and notifies the server that data is available.


The Xlib output request buffer is actually a transport layer communication buffer (XTCB). The XTCB data structure is described in Section 3.2.4.

The connection could be across the network to the display, or within a workstation in the case where the client and server have established a local connection. The networking service is assumed to be reliable; Xlib, the transport layer, and the server assume that the data arrives intact and error-free.

The transport layer notifies the scheduler at user-AST level that it has data available for a connection. The dispatcher calls the transport layer to get the data.

2.4 Client Input

Input to clients comes in three forms: input events, errors, and replies. An event packet is the X11 protocol message sent from a server to a client that gives information about some event in the server, such as a windowing operation, a keyboard key transition, or a mouse movement. Clients can also use request packets (XSendEvent) to send events to another client by way of the server. An event packet consists of exactly 32 bytes.

An error packet is the X11 protocol message sent from a server to a client that indicates an error state in the server. An error packet consists of exactly 32 bytes.

A reply packet is the X11 protocol message sent from a server to a client in response to a client protocol request that generates data (for example, GetImage). A reply can be any length with a maximum size of some 16 gigabytes.

2.4.1 Handling Input

Most input events are reported to clients relative to windows. Events are usually sent to the smallest enclosing window in which the pointer is located that is interested in the type of event being sent. It is also possible to assign the keyboard input focus to a specific window. When the input focus is attached to a window, keyboard events go to the client that has selected input on that window, rather than to the window in which the pointer is located.

The input component of the server services the XEvent queue and interacts with the window manager to determine which window is associated with the position recorded in the input queue entry. The window ID to which the event is to be delivered is then recorded in the event packet. The input component calls the events component to send the input events to clients that want to know about input in this window ID.

Client programs can use the event_mask argument of the XSelectInput routine to select the events for which they want to receive notification. The server does not send events to a client unless the client has specifically asked to be informed of that type of event. One exception to this rule is that one client can use the XSendEvent routine to force events to be sent to other clients.

An interest list is attached to the window ID data structure. Each entry on the interest list describes filtering parameters defined by the client's event masks. If there are multiple windows interested in the event, the event is sent to multiple windows.

The events component calls the transport layer to transmit the processed input event packets to the Xlib input queue. The transport layer buffers the events packets on a per-connection basis and delivers them to the Xlib input queues. As in the case for output, the transport layer does not interpret the data. Input normally arrives at the client as an I/O completion. Typically, the client processes the input event and generates output requests.

The input event is retained by Xlib until a client requests the next, or the next matching, event. It is the responsibility of the client to request the event; if the client does not request the event, the event remains in the queue.

Xlib provides routines, such as XPeekIfEvent and XCheckIfEvent, that client programs can call to check for particular types of events on their respective input queues. These routines require client programs to supply a procedure that determines if the next event in the queue matches the one that the client wants.

Chapter 3
Transport Layer Architecture

This chapter describes the theory of operation and interconnection of each component of the VMS DECwindows transport layer. The relationship between the transport-common and transport-specific layers, as described in Section 3.3, is of particular importance.

The chapter begins with a description of the transport layer communication queues.

3.1 Transport Layer Communication Queues

The transport layer uses transport communication buffers (XTCBs) to pass data. (See Section 3.2.4 for more information on the XTCB data structure.)

When a connection is created, a specific transport calls the DECW$XPORT_ALLOC_INIT_QUEUES routine to create six communication queues that pass XTCBs between servers and clients and between transport-common and transport-specific components. The communication queues are relative queues as used by the VAX REMQxI and INSQxI instructions. With the exception of the local transport, the queues are private to one side of the connection.

The communication queue headers are stored in the XTCQ data structure. Each queue is named according to its function, as shown in Table 3-1.

A queue element (XTCB) must be removed from its queue before its contents can be modified by either the server or Xlib or by transport layer internal functions.

The component that adds XTCBs to a queue is called the producer; the component that removes XTCBs from a queue is called the consumer.

Table 3-1 Transport Layer Communication Queues
Queue Name Description
EventWorkQueue Queue of XTCBs containing events, errors, and replies to be sent to Xlib
(large and small)
Return queue for processed XTCBs from the EventWorkQueue
RequestWorkQueue Queue of XTCBs containing requests to be sent to a server
(large and small)
Return queue for processed XTCBs from the RequestWorkQueue

The transport layer communication queues are shown in Figure 3-1. For the purpose of simplicity, Figure 3-1 combines the free queues; there are actually separate free queues for large and small XTCBs.

Figure 3-1 Transport Layer Communication Queues

You can consider the buffers in the transport layer communication queues to be in an infinite loop similar to a ski lift; once a buffer is received at one end of the connection it is emptied and added to the returning loop.

The transport layer further distinguishes between the queues so that terminology is consistent on both sides of the client/server connection; when the term "input" is used in the context of a client, it means "event." Conversely, "input" in the context of the server means "request." Table 3-2 shows the delineation of the queues.

Table 3-2 Views for the Client/Server Communication Queue
General Queue Name Client View Server View
EventWorkQueue InputWorkQueue OutputWorkQueue
EventFreeQueue InputFreeQueue OutputFreeQueue
RequestWorkQueue OutputWorkQueue InputWorkQueue
RequestFreeQueue OutputFreeQueue InputFreeQueue

Figure 3-2 shows the result of adding the client/server views to the model of the queues shown in Figure 3-1.

Figure 3-2 Client/Server Communication Queue Views

In the case of local communication where the client and server are executing on the same hardware, the queues are shared between the client and server. Each queue has two meanings depending upon whether a server or a client is looking at the queue. For example, the EventWorkQueue is simultaneously the client's InputWorkQueue and the server's OutputWorkQueue.

3.1.1 Transport Common/Specific Queue Relationship

The transport layer seems to be a single entity that somehow moves data across the wire, but there are actually two transport layers involved: a transport layer on the client side and a transport layer on the server side. Each side of the client/server connection initializes the common transport and attaches one or more specific transports. Each transport layer builds and maintains its own set of connection queues; the queues are private to each side of the wire and are not actually shared across a network connection. The local transport is an exception; the queues are built in shared global sections.

General discussions of the relationship between the transport layer and other DECwindows components commonly treat the transport layer as a single entity that exists on both sides of the client/server connection. However, the transport layer consists of the transport-common and transport-specific components.

The transport-common and transport-specific components pass data to each other by means of a queue implementation that is similar to the queues employed between Xlib and the transport-common code. This intratransport queuing implementation is shown in Figure 3-3.

Figure 3-3 Transport Common/Specific Connection

3.1.2 Adding and Removing Buffers from the Queues

The server and Xlib call transport-common routines such as DECW$XPORT_READ, DECW$XPORT_FREE_INPUT_BUFFER, GET_OUTPUT_BUFFER, and DECW$XPORT_CHAINED_WRITE to remove or add buffers from the queues, as described in Section and Section

Some of the transport-common routines may call transport-specific routines such as XTFT$A_WRITE to actually get the buffer from the queue. Other transport-common routines, such as DECW$XPORT_READ, operate only in the common layer and communicate with the specific transport only by manipulating data structures.

The following is an example of the transport-common/transport-specific queue process:

  1. Xlib calls the DECW$XPORT_GET_OUTPUT_BUFFER routine to get a free XTCB. DECW$XPORT_GET_OUTPUT_BUFFER removes (REMQHI) an XTCB from the OutputFreeQueue.
  2. Xlib copies data to the XTCB and calls DECW$XPORT_CHAINED_WRITE.
  3. DECW$XPORT_CHAINED_WRITE inserts (INSQTI) the XTCB on the OutputWorkQueue. If the queue was empty, the XTFT$A_WRITE routine is called to determine if an I/O should be initiated.
  4. When the write completes, the XTCB is inserted on the tail of the OutputFreeQueue. Xlib is then notified if it is waiting for an output buffer. If the OutputWorkQueue is not empty, another I/O is initiated.

Figure 3-4 adds the transport-common/transport-specific queue process to Figure 3-3.

Figure 3-4 Transport Common/Specific Queues

On the server side of the connection, the underlying transport notifies the transport-specific layer that data is available. For example, DECnet delivers this notification in the form of a $QIO read completion for the connection; that is, the specific transport receives a read-completion AST in response to a $QIO read for a given connection.

When the specific transport receives a read completion, it calls the transport-common DECW$XPORT_READ_COMPLETE routine to perform the following steps:

  1. Inserts (INSQTI) the XTCB that now has data in it on the InputWorkQueue.
  2. If input notification is requested, it sends the server an input-notify AST to indicate that an XTCB is available for the connection.
  3. Removes (REMQHI) an XTCB from the InputFreeQueue.
  4. Initiates a new read into the XTCB.

The server calls DECW$XPORT_READ to remove (REMQHI) the XTCB from the InputWorkQueue. When the dispatcher is finished with the XTCB, it calls DECW$XPORT_FREE_INPUT_BUFFER to insert the XTCB on the InputFreeQueue, and the queue cycle is complete.

If the InputFreeQueue is empty and input for the connection is enabled when DECW$XPORT_FREE_INPUT_BUFFER inserts the XTCB, DECW$XPORT_FREE_INPUT_BUFFER calls XTFT$A_EXECUTE_FREE to remove (REMQHI) the XTCB it just placed on the InputFreeQueue. In the case of DECnet or TCP/IP, the XTCB is then used to store the result of the next QIO read operation for the connection.

3.1.3 Communication Queue Notification Flags

It is possible that at any given time all of a connection's input or output XTCBs will be in use. To provide for this possibility, there is a flag associated with each queue that tracks the state of the queue. When a queue has been exhausted, the component that is removing XTCBs from the queue (the consumer) sets the state flag to indicate that it wants to be notified when an XTCB becomes available.

If the component that is adding XTCBs to the queue (the producer) notices that the queue was empty, it tests the state flag and, if set, notifies the consumer that an XTCB is available.

The notification is context dependent. When the consumer is a transport-specific layer, as described in Section 3.1.1, the notification causes I/O to be initiated using the recently inserted queue element.

When the consumer is the transport-common layer, notification consists of delivering an AST or setting an event flag. For example, the transport-specific code on the server side of the connection sends the transport-common layer an AST to say that input is available for a connection.

The notification flags are shown in Table 3-3.

Table 3-3 Communication Queue Notification Flags
Flag Name Meaning
EventWorkQueueFlag Event consumer awaits event XTCBs
EventFreeQueueFlag Event producer awaits returned event XTCBs
RequestWorkQueueFlag Request consumer awaits request XTCBs
RequestFreeQueueFlag Request producer awaits returned request XTCBs

As in the case of the local communication queues, each interest flag in a local connection has two meanings depending upon whether a server or a client is looking at the queue: the EventWorkQueue is the client's InputWorkQueue and the server's OutputWorkQueue; the RequestFreeQueueInterest bit is the client's OutputFreeQueueInterest bit and the server's InputFreeQueueInterest bit.

A queue element consumer functions as follows:

  1. Sets the queue notification flag (in case the queue is empty).
  2. Removes an element from the queue.
    • If the queue is empty, the consumer can wait for notification that data is available or it can return without the buffer.
    • If the queue is not empty, the consumer clears the notification flag and returns with the buffer.

A queue element producer functions as follows:

  1. Inserts an element on the queue.
  2. If the queue was empty and the queue flag was set, clears the queue flag and generates a notification to tell the consumer that data is available.

3.1.4 Preventing Queue Access Conflict

The transport layer uses interlocked queues to synchronize access between the queue producer and consumer. Server or Xlib attempts to remove and insert buffers result in the interlocked instructions being used in user mode, possibly at AST level.

The queues are also accessed by inner-mode routines by using the following transport common routines:


Executive-mode code cannot use the REMQxI and INSQxI built-ins to access a relative queue that is modifiable by user-mode code because of the possibility of incorrectly accessing user-write-protected memory.

The REMQxI and INSQxI routines use the VAX PROBEW instruction to probe the memory occupied by a queue entry to determine if the memory has user-mode write access and return an ACCVIO status if it is not accessible.

The REMQxI and INSQxI emulations also perform a spin-and-wait to see if the queue is locked by another transport user. Special-Case Queue Conditions

There are two special-case queue conditions:

  • As described in Section 3.1.3, the queue consumer sets the notification (notify-if-empty) queue flag before attempting a REMQHI from the queue. If the queue is not empty, the consumer removes the queue element and clears the flag.
    The producer checks this flag after adding an element to the queue. If the producer is able to insert a queue element between the time when the consumer sets and clears the flag, the producer generates an input-available notification when none is necessary. This is called spurious notification, and queue consumers must be prepared for it.
  • A second condition occurs when the consumer can preempt the producer thread, such as the output half of a remote transport.
    For example, assume that the producer does an INSQTI of some element on the queue and is about to test the queue flag. However, before the producer can test the queue flag, the consumer does the following:
    1. Removes (REMQHI) an XTCB and processes it
    2. Fails when it attempts to remove another XTCB
    3. Sets the queue interest flag and quits

    The producer does not know that the queue is now empty; it continues to run and attempts to notify the consumer. In this case, however, notification consists of removing the head queue element and issuing a transport write operation from data in the queue element. Because the element is no longer on the queue, the notification procedure must be prepared to handle the empty queue.

3.2 Transport Layer Data Structures

The transport layer data structures maintain the state of the transport and each of the established connections. The transport layer data structures are created in stages as the transport-common code is initialized, a transport-specific mechanism is attached, and connections are established.

The XTPB, IXTCC, and XTDB data structures are allocated from memory pages that have user-mode read access/executive-mode write access (UREW) to prevent modification by less privileged access levels, including the transport-specific code that runs in user mode. The transport-common code depends on the accuracy of the contents of the XTPB, IXTCC, and XTDB data structures.

The transport layer data structures are described in Table 3-4.

Table 3-4 Transport Layer Data Structures
Name When Created Write Access Mode Description
XTPB Initialization
Transport attach
Connection open
exec Transport parameter block (XTPB) contains default transport parameters. There is a three-level hierarchy of XTPB data structures.
IXTCC Connection open exec Internal transport communications context (IXTCC) describes an established connection for executive-mode routines within the transport layer. The IXTCC is used by executive-mode routines to store protected data.
XTCC Connection open user
Transport communications context (XTCC) describes an established connection. The XTCC is used to pass user-mode data to executive-mode routines. The XTCC may be modified by user-mode code and is visible to either the server or Xlib.
XTDB Transport attach exec Transport descriptor block (XTDB) describes each attached transport.
XTCQ Connection open user
Transport communication queue (XTCQ) contains six per-connection communication queues and their states.
XTCB Connection open user
Transport communication buffers (XTCB) pass data in the transport layer.
XTFT Transport attach exec Transport function table (XTFT) contains the addresses of the transport-specific routines. The XTFT is the transport-common code's link to the transport-specific code.

The transport-common code creates the global XTPB structure at initialization time. The transport-common DECW$XPORT_ATTACH_TRANSPORT routine creates XTDB and XTPB data structures, as shown in Figure 3-5. The XTCC, XTCQ, and XTCB data structures are allocated from memory pages that are user-writable so that routines running in either user or executive mode can modify them.

Figure 3-5 Transport Attach Data Structures

The transport-common open routine creates IXTCC and XTPB data structures. The transport-specific connection open routine creates XTCC, XTCQ, and XTCB data structures, as shown in Figure 3-6.

Figure 3-6 Transport Connection Open Data Structures

The transport-specific connection open routine also creates XTCB data structures, as shown in Figure 3-7.

Figure 3-7 Transport Connection Open XTCB Data Structures

The shaded areas of Figure 3-8 show the transport layer data structures that have user-mode read access/executive-mode write access.

Figure 3-8 Transport Data Structures

Previous Next Contents Index