libes@nbs-amrf.UUCP (08/06/86)
Is it possible to do critical regions in VMS? I would prefer non-privileged code but, if necessary, some weird privs would be acceptable. My problem is as follows: int x = 0; main() { while (1) { increment(); decrement(); } } increment() {x++;} decrement() {x--;} The user can call subroutines increment and decrement in strictly alternating sequence (as is done here in main()). However, he may ^c or exit (via forcex() or the debugger) at any time. I would like to ensure that x is 0. The reason I can't just set it to 0, is that x is actually shared with several other processes (all doing the same thing). I'm at a loss on how to do this. I'm already using an exit handler, but the exit handler can't tell if it needs to decrement x or not (x actually takes on values > 1, so it can't tell if we've incremented x a different number of times than we've decremented it). No matter how I write it, there is always a window in which I will have a problem. If I could do critical regions in VMS I would like to do something like this: increment() { enter_critical_region(); /* block ^c, ^y, forcex(), etc */ x++; incremented = TRUE; exit_critical_region(); /* ok, now I'm willing to exit */ } exit_handler() { if (incremented) x--; } (In case it's important, I'm using Fortran (patching someone else's code). I'm assuming a language-independent VMS-dependent solution.) I would appreciate it if anyone has a solution to this seemingly simple problem. Thanks. (If anyone knows how to do critical regions in general in VMS, I would like to know, as all the people around here that I asked said that they had run into this problem before to no avail.) Don Libes {seismo,umcp-cs}!nbs-amrf!libes (301) 921-2171
DCATHEY%MCCORE%ti-eg.CSNET@CSNET-RELAY.ARPA ("David L. Cathey, DEIS/DCS) (08/08/86)
Yes, it is possible to do critical regions in VMS. However, the more critical it is, the more privileged you need to be. Since you are wanting a critical region to guard against any action that the operating system might take against you, very privileged code is required (like Kernel mode at elevated IPL...). However by looking at your example, there may be a more elegant solution. Does the counter need to be in any particular form? How about ENQueueing a lock (probably a NULL lock) for the "increment" function and DEQueueing a lock for the "decrement" function. This will provide a mechanism to "increment" a variable that when the process goes away, or the image is run down, will automatically be "decremented". The $GETLKI system service (by specifing LKI$_LCKCOUNT (lock count) in the item list) will be able to tell you the "value" of the variable. If this variable is global across the entire system, you will need the SYSLCK privilege. If all the process are in the same job group, it will require no privileges. This does not really answer the question about critical regions, but allows the operating system to work for you so that the critical region isn't needed. If this doesn't help, then I think you will have to look at User-written System Services in order to control the incrementing and decrementing of a variable. The run-down vector in the USS can be used to decrement if needed so that you stay properly synchronized. David L. Cathey VAX System Support Texas Instruments Incorporated [Not only are these views not those of my employer, I had to tie him up so I could type this in...]