DATA SHARING, ALIASING, AND SYNCHRONIZATION
DATA SHARING, ALIASING, AND SYNCHRONIZATION
segments. If there are call gates in the GDT at PL 3, then these procedures are accessible to all other procedures in the system.
SEND_MESSAGE fills a message with the specified data and descriptors, removes the descriptors from the descriptor table, and links the message at the tail of the message queue. If a task is waiting at the mailbox, SEND_MESSAGE causes it to be linked into the ready queue so that it will find the message the next time it is scheduled to run.
If RECEIVE.-MESSAGE finds no messages waiting at the mailbox, then it links"the task into a waiting queue. The task queue threads through the task database. The task will continue executing when another task sends a message to the mailbox. If (or when) a message is waiting, RECEIVE_MESSAGE writes the data portion of the message at a specified location in the receiving task's space and installs the descriptor portion in specified slots in one of the receiving task's descriptor tables (GDT or LDT).
These examples do not include management of space and queues for messages because conventional algorithms apply. .External procedures GELMSG~PACE, ENQUEUE_MESSAGE, DEQUEUE_MESSAGE, and FREE_MSG_SPACEprovide these functions.
Special handling is required to accommodate the fact that a descriptor in a message is temporarily not in any descriptor table. There are two cases to consider: .
• The descriptor is the sole descriptor for the segment. In this case, no changes can be made to the segment because it is temporarily inaccessible. You should take care that no failure in the commu-nication process causes the descriptor to become lost. A memory area without a descriptor cannot be freed.
• The descriptor is an alias (Le., one of several descriptors for the same segment). Since the segment is (presumably) accessible via the other aliases, it is possible for some task to request some operation on the segment during the time the descriptor in the. message is absent from any descriptor table.
Normally, the operating system updates all aliases when it makes any major changes to a segment (for example, relocation or swapping to secondary storeJ~ This is not possible (given the aliasing scheme previously presented in this chapter) when the alias is not in a descriptor table. To solve the problem, this example assumes there are two procedures;
a. DISABLRALIAS..YTR that marks the alias list element to indicate to the alias manager that the alias is in a mailbox
b. FI~LIAS..YTR that, when the message is delivered, updates the alias pointer with the new location of the alias and with any segment information that may have changed while the alias was absent from the alias list.
Dynamic systems may need to create and delete mailboxes dynamically. The only difficulty in creating a mailbox is ensuring that no task uses it while it is being constructed. (The next section considers this problem.) To delete a mailbox the operating system must awaken any tasks that are waiting for messages, delete any descriptors (aliases) that reside in undelivered messages, and delete the undelivered messages themselves.
The operating system may, as part of the process of task creation, give each task at least one mailbox.
If the mailbox feature is the only means of passing aliases among tasks, a task cannot receive an alias for a mailbox unless it already has a mailbox. Some operating system designs may require every task to have a mailbox for such purposes as receiving memory segments from the memory-allocation module.
5 .... 12 121960-001
DATA SHARING, ALIASING, AND SYNCHRONIZATION
PL/M-286 COMPILER 960-508 date PAGE 1
system-ID PL/M-286 Vx.y COMPILATION OF MODULE MAILBOX OBJECT MODULE PLACED IN :Fl:MBOX.OBJ
COMPILER INVOKED BY: PLM286.86 :Fl:MBOX.PLM DEBUG
1
$ PAGEWIDTH(71) TITLE('9613-5138') INCLUDE (:Fl:NUCSUB.PLM)
$ NOLIST MAILBOX: DO;
/*******************************************************/
/* Definitions */
DECLARE FAILED LITERALLY 'S13130H', OK LITERALLY '13';
/*******************************************************/
/* Externals */
NULLIFY: PROCEDURE (SLOT) EXTERNAL;
DECLARE SLOT SELECTOR;
END NULLIFY;
STORE DESCR: PROCEDURE (SLOT,PTR) EXTERNAL;
DECLARE SLOT SELECTOR, PTR POINTER;
END STORE_DESCR;
LOAD DESCR: PROCEDURE(PTR,SLOT) EXTERNAL;
DECLARE PTR POINTER, SLOT SELECTOR;
END LOAD _DESCR;
DISPATCHER: PROCEDURE EXTERNAL;
END DISPATCHER;
ENQUEUE WAIT: PROCEDURE(QUEUE ID) EXTERNAL;
DECLARE QUEUE ID SELECTOR; -END ENQUEUE_WAIT;
DEQUEUE WAIT: PROCEDURE(QUEUE ID, EXCEP P) EXTERNAL;
DECLARE QUEUE ID SELECTOR, EXCEP P POINTER;
END DEQUEUE_WAIT;
-DISABLE ALIAS PTR: PROCEDURE(SLOT) EXTERNAL;
DECLARE SLOT-SELECTOR;
END DISABLE_ALIAS_PTR;
FIX ALIAS PTR: PROCEDURE (ALIAS_LIST_ID) EXTERNAL;
DECLARE ALIAS LIST ID POINTER;
END FIX_ALIAS_PTR;
-GET MSG SPACE: PROCEDURE(BOX ID,MSG P P,EXCEP P)EXTERNAL;
DECLARE BOX ID SELECTOR, (MSG_P_P~ EXCEP_P)-POINTER;
END GET_MSG_SPACE;
Figure 5·7. Example of Mailbox Procedures
DATA SHARING, ALIASING, AND SYNCHRONIZATION
ENQUEUE MESSAGE: PROCEDURE(BOX ID, MSG_PTR) EXTERNAL;
DECLARE BOX ID SELECTOR, -MSG PTR POINTER;
END ENQUEUE_MESSAGE;
DEQUEUE_MESSAGE: IlROCEDURE(BOX_ID, MSG P P, EXCEP P) EXTERNAL;
DECLARE BOX ID SELECTOR, (MSG P P, EXCEP_P) POINTER;
END DEQUEUE_MESSAGE; -
-/*******************************************************/ EXCEP _P) PUBLIC REENTRANT;
DECLARE BOX ID SELECTOR, MDATA PTR POINTER, (SLOTl, SLOT2) SELECTOR;
DECLARE EXCEP P
CALL MOVB (MDATA PTR,@MESSAGE.MDATA,MDATA SIZE);
IF SLOT1=SELECTOR$OF (NIL)
-THEN MESSAGE.DESCR1(2)=0; /* Mark as null */
ELSE DO;
CALL STORE DESCR(SLOT1,@MESSAGE.DESCR1);
CALL DISABLE_ALIAS_PTR(SLOT1);
Figure 5·7. Example of Mailbox Procedures (Cont'd.)
5-14 121960-001
DATA SHARING, ALIASING, AND SYNCHRONIZATION
CALL STORE DESCR(SLOT2,@MESSAGE.DESCR2);
CALL DISABLE ALIAS PTR(SLOT2);
CALL NULLIFY(SLOT2);
END;
DISABLE;
CALL ENQUEUE MESSAGE(BOX ID, MSG PTR);
CALL DEQUEUE-WAIT(BOX ID~@EXCEP);
ENABLE; -
RECEivE_MESSAGE: PROCEDURE (BOX ID, MDATA PTR, SLOT1, SLOT2, EXCEP=P) PUBLIC-REENTRANT;
DECLARE BOX ID
CALL MOVB(@MESSAGE.MDATA, MDATA PTR, MDATA SIZE);
IF MESSAGE.DESCR1(2)<>1J /* Test-for null descriptor */
THEN DO;
CALL LOAD DESCR(@MESSAGE.DESCR1, SLOT1);
CALL FIX_ALIAS_PTR(@MESSAGE.DESCR1);
END;
IF MESSAGE.DESCR2(2)<>1J /* Test for null descriptor */
THEN DO;
CALL LOAD_DESCR(@MESSAGE.DESCR2, SLOT2);
Figure 5-7. Example of Mailbox Procedures (Cont'd.)
Intel
DATA SHARING, ALIASING, AND SYNCHRONIZATIONPL/M-286 COMPILER 960-508 date
95 96 97 98 99
3 3 2 2 2
CALL FIX ALIAS PTR(@MESSAGE.DESCR2);
END;
CALL FREE MSG SPACE(BOX ID,@MESSAGE);
EXCEP=OK; -
-END RECEIVE_MESSAGE;
PAGE 4
1*******************************************************/
100 1 END MAILBOX;
MODULE INFORMATION:
CODE AREA SIZE CONSTANT AREA SIZE VARIABLE AREA SIZE MAXIMUM STACK SIZE 193 LINES READ
o PROGRAM WARNINGS
" PROGRAM ERRORS DICTIONARY SUMMARY:
91KB MEMORY AVAILABLE 016EH 0000H 0000H 0020H
6KB MEMORY USED (6%) OKB DISK SPACE USED END OF PL/M-286 COMPILATION
366D 0D 0D 32D
Figure 5-7. Example of Mailbox Procedures (Cont'd.)
Variations on the Mailbox Theme
Some of the features appropriate for semaphores are also appropriate for mailboxes, namely:
• Conditional receive
• Timed wait
For applications in which speed is not the overriding goal, mailboxes can substitute for semaphores. A mailbox is analogous to a semaphore, with the counter of a semaphore corresponding to the number of messages waiting at a mailbox. A mailbox with null messages is identical in function to a semaphore.
Most applications that use mailboxes require different message formats (different data size, different number of descriptors) for different communication channels. With dynamically created mailboxes, message format may be defined by parameters to the creation procedure, encoded in the mailbox, and interpreted by the SEND_MESSAGE and RECEIVE_MESSAGE procedures.
5-16 121960·001
DATA SHARING, ALIASING, AND SYNCHRONIZATION
Systems that implement "pipes" as a form of intertask communication can call mailbox procedures from the device drivers for the pipes.
It is possible to use mailboxes as the sole means of interface between applications and operating system.
For example, the operating system has one mailbox through which it receives service requests from all applications; each task has a mailbox through which it receives responses from the operating system.
To get more memory, a task would send a memory request message to the operating system; the operat-ing system would return a message containoperat-ing an alias 'for the allocated memory segment and install the alias in the task's LDT. The advantage is simplicity. Only two global gates are needed: one for SEND_MESSAGE and one for RECEIVE_MESSAGE. A task can wait for only one purpose: for a message from a mailbox. The disadvantage is inefficiency. Any implementation of mailboxes is bound to be less efficient than the interlevel CALL instruction normally used to communicate with an operating system.
All of these forms of message-passing can use the primitive synchronization and descriptor-manipulation techniques illustrated in this section.B