Path: utzoo!mnetor!uunet!husc6!cmcl2!brl-adm!umd5!ames!pasteur!ucbvax!VENUS.YCC.YALE.EDU!LEICHTER From: LEICHTER@VENUS.YCC.YALE.EDU ("Jerry Leichter ", LEICHTER-JERRY@CS.YALE.EDU) Newsgroups: comp.os.vms Subject: re: AST interrupts and process state Message-ID: <8801131949.AA26902@ucbvax.Berkeley.EDU> Date: 12 Jan 88 16:48:00 GMT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The ARPA Internet Lines: 114 The author starts off with a simple question: Can a process in Local Event Flag Wait (LEF) state be interrupted by AST's generated by $QIO requests? The answer to this question, as written, is YES, but... I do not want to complicate my program by nesting hibernations and am not entirely sure if $WAKEing one hibernation will leave the other pending hibernate intact or if it will wake the process altogether. Still a simple question with a simple answer (see below), but the waters getting murky... What I need to do is issue a $QIO to a mailbox and have its AST routine (as given by the astadr parameter to the $QIO) interrupt the process for a short time to let the sender of the mailbox message know that a resource is unavailable while waiting for another QIO read request to a network (EXOS TCP/IP is the software) to complete, signalling that a remote server has been restarted. After the notification of the server restart has been received, the program will then go back into HIB and wait for subsequent requests since the resource is again available. Looks good, absolutely standard use of QIO's and AST's. The routine in which all this is happening will also be entered from an AST processing routine that was started while the process was under one $HIBER. Now things have gotten completely murky, as it is no longer clear where and when the proposed wait for an event flag is to take place. Thus, when the server is again reachable, the process should reenter HIB. If I do use $HIBER to wait for the network QIO to complete, will a $WAKE also eliminate the original $HIBER or only the one entered to wait for the network? OK, we need to step back and understand how AST, event flags, and such work, as once you start digging, there isn't enough information here to really answer the question. First off, a process has an "AST active" bit that can be either on or off. When it is on, the process is running "in AST state"; it can receive no further AST's (at least at the same our an outer access mode. That needn't concern us for normal user-mode progamming, though it explains why DCL can receive a supervisor-mode CTRL/Y AST even while a program is executing in user-mode AST state.) When a process is NOT in AST state, it can usually be interrupted by AST's. There two exceptions: SUSP(ended) processes, and those that have disabled AST delivery with the SYS$SETAST() call. Both hibernation and LEF state can be interrupted by an AST. So, the first answer to the first question is yes - EXCEPT that saying that a process is in LEF state doesn't give the whole picture. It may have entered LEF state while in AST state (by doing a QIOW or a SYNC or an explict EF wait). In that case, the "AST active" bit is still on, and no further AST's can be delivered. (The same goes, of course, if the event flag wait was started after using SYS$SETAST to disable AST delivery; or if the process was suspended while waiting.) Now for hibernation. Hibernation is a very simple process state - a process is either hibernating or not. A hibernating process will come out of hiber- nation when it is woken, or when an AST is delivered to it. In the latter case, the previous hibernation state is remembered, and the process will resume hibernation after the AST routine exits. (However, a WAKE will clear the remembered hibernation state even while an AST is in progress, so another process can always issue an effective WAKE - and a process can issue a WAKE for itself while at AST level and thus "kick" its non-AST-level code.) If a process begins hibernating while in AST state, or with AST delivery disabled, no AST can be delivered to it to break it out of its hibernation. In that case, only a WAKE from another process will get it moving again. Again, there are complications if you consider inner access modes. Hiber- nation is process-wide; it is not tied to access mode. A process that issues a $HIBER call in kernel mode will wake up if another process issues a user- level $WAKE call for it. On the other hand, while a process is in an inner mode, it cannot receive any AST's for outer modes, so this particular avenue of awakening from the hibernation may be blocked. The fact that there's only one level of hibernation has an important consequence, due to the fact that DCL SPAWN and ATTACH rely on hibernation - processes may receive "unexpected" wakeups. Hence, correct code must NEVER assume that the simple fact that it woke from hibernation means that some event it was waiting for has taken place; it must check. That is, the ONLY correct way to use hibernation for synchronization is: sleep: while (event-hasn't-happened) $HIBER() wake: mark-event-as-happened; $WAKE(...) So, hibernations don't nest, and hibernating while in AST state is almost certainly not what you want to do. Finally, how do hibernation and LEF state mix? Well, since a process must take a deliberate action to enter either state - i.e., it can only enter either state from the CURR state - the answer, in a sense is, they don't. However, there is one situation in which both can (sort of) apply: Process hibernates, receives an AST (temporarily breaking it out of hibernation), then waits for an event flag. In that case, the process is in LEF state (with the AST active bit set); it's got a nested hibernation request waiting for it once it exits from its AST routine, which it will presumably do after its event flag wait completes. Since the AST active bit is set, no further AST's can be delivered to the process. BTW, if I remember right, the mechanism for all this is very simple: While a process is hibernating, its stored PC points to the call to SYS$HIBER. AST delivery simply makes the process computable; when the AST routine completes, the process returns to its stored PC, which calls SYS$HIBER again. A WAKE works because when applied to a process that is not currently hibernating - as a process executing an AST is not - it sets a "wake pending" bit in the process header. When this bit is set, the next call to SYS$HIBER returns immediately, without sleeping. -- Jerry