jamin@eddie.mit.edu (Sugih Jamin) (11/10/89)
In article <8551@microsoft.UUCP> robertre@microsoft.UUCP (Robert Reichel ms2) writes: >In article <32295@ucbvax.BERKELEY.EDU> jamin@cogsci.berkeley.edu (Sugih Jamin) writes: >> [Why does one need to reinstate a signal handler after every use?] >To control reentrancy in your signal handler. This point has been well discussed by others. I just want to mention that it would have been nice of OS/2 to take care of it the way BSD does, instead of having the programmer take care of it {him,her}self. >>One doesn't have to do the same in BSD, does one? >Don't know. Does it matter? I think it was Newton who said something about standing on the shoulders of giants. I mentioned BSD just to point out a different implementation which I happen to think is cleaner. Similarly, I think Mach's way of handling threads is much more elegant than OS/2's. >>Some time ago I posted a message about managing stacks for >>threads. Does anybody, especially people at Microsoft, know >>why OS/2 was not designed to manage the stacks internally? > >Consider that different applications may have different needs. >It is reasonable for an application that is going to be creating >and killing lots of threads to maintain a pool of stacks for those >threads, so as not to endure the overhead of continually having >to allocate and free stack space (which may fail in tight memory >situations). The idea was to provide flexibility to the application >writer. The overhead shouldn't be too bad if OS/2 manages threads' carcasses the way UNIX does those of child processes. A fork(2) simply breathes new life into an abandoned cadaver, if I'm not wrong. >>Assume that the total amount of memory I need at >>any one time is not more than 64K (otherwise I could use DosAllocHuge, >>which brings me to my next question: will DosSubAlloc/DosSubFree >>perform slower on a huge chunk of memory?) > >You cannot use the suballocation calls on a huge segment. Read >the manual entry for DosSubSet. Ah, the manual. It, the manual, says that I must use DosSubSet on a chunk of memory allocated with DosAllocSeg or DosAllocShrSeg. It doesn't say I must not use it with DosAllocHuge. Normally, I would assume that only DosAllocSeg and DosAllocShrSeg work with DosSubSet. But I have been burned once for assuming what the manual doesn't say. I am referring to DosGiveSeg and DosGetSeg. The manual for DosGetSeg says that even when one already has a selector to the shared memory, one still has to call DosGetSeg. But it turns out that one doesn't need to call DosGetSeg if the selector one got came from DosGiveSeg. I found this out from the M&T book. Besides, calling DosSubSet on memory allocated with DosAllocHuge didn't return any error. Now that we have mentioned the manual, allow me to ask, "Why is Microsoft so inconsistent in making up function names?" For dealing with semaphores, for example, we have DosOpenSem, DosCreateSem, etc., but we also have DosSemRequest, and DosSemWait. A simple test: is it DosSemClear or is it DosClearSem one should call to clear a semaphore? Then, what is the difference between DosGet and DosQuery? Is it DosGetMachineMode or DosQueryMachineMode? Then there is that Hungarian notation. It simply defeats the whole purpose of data abstraction, doesn't it? Even the manual itself got confused over it. In more than one instances, the manual errorneously describes a variable which name begins with a 'p' as a pointer. Not to mention that the manual for LAN Manager doesn't follow the same notation (nor does it use the OS/2 types). Somebody here said that OS/2 has a lot of neat features, just that some of them are not properly implemented. I totally agree with this view. Even the manual is not properly prepared. OS/2 in its current state really is half of an operating system. sugih
ander@pawl.rpi.edu (Michael R. Primm) (11/11/89)
One problem with emulating the fork(2) idea of "resurrecting" old thread cadavers is that threads should never have cadavers in the first place. The whole distinction between a thread and a child process is that a thread shares EVERYTHING with its fellow threads Therefore, OS/2 processes don't spin off copies of themselves (and their data areas) when a new thread is created, only a new context is created. In any case, I do like having the option of controlling the threads at a low level (just handing the thread a stack and starting it has got to be faster than having the operating system allocate the space, start the thread, and remember to deallocate the space after the thread dies). BUT, I think such an option would have been very helpful, given the likely frequent use of such a feature. --Mike Primm
guy@auspex.auspex.com (Guy Harris) (11/11/89)
>"Does it matter" means "is it important what BSD does since we're talking >about OS/2". Of course the behavior must be well defined for each >operating system. The behavior was "well-defined" in pre-BSD UNIX, it just wasn't very *good*. "Well-defined" isn't sufficient, and, therefore, the fact that it does matter under UNIX leaks into OS/2 as well, if OS/2's behavior loses as pre-BSD UNIX's does.... >>This meant that the signal handler wouldn't be reentered >>if another instance of the same signal were delivered to the process >>while handling one instance of that signal, unless the process >>re-established the signal handler; instead, the process would simply >>die! This has been known to kill real live applications. > >This is, I believe, one of the reasons signal() was replaced by >sigset()? Yup, although "sigset" was replaced by "sigvec" in 4.2BSD, which was adopted in modified form in POSIX as "sigaction". >In OS/2 the return does not implicitly acknowledge the signal. >One must call DosSetSigHandler to acknowledge the signal. I'm >no BSD expert, but from what you describe it sounds as if the >implicit blocking of further signals upon entering the signal >handler is similar to OS/2's behavior, ie, they are latched in >one at a time at well defined places. Well, I'm no OS/2 expert, I just know what I found in the aforementioned book, so I can't compare them, either. Here's the BSD behavior, hopefully described without need for implicit knowledge of said behavior; how does OS/2 behave (as described without need for implicit knowledge of said behavior - i.e., I don't know what "latched in" means or what the "well defined places" are, or what it means to "acknowledge" the signal, so it's hard for me to say whether that matches BSD behavior or not): A process has a "signal mask", with one bit for each possible signal (e.g. since SIGINT - which seems to correspond to the OS/2 "CTRL-C" signal, value 1 - has value 3, the third bit corresponds to SIGINT: /* * Macro for converting signal number to a mask suitable for sigblock(). */ #define sigmask(m) (1 << ((m)-1)) from 4.3BSD). If the bit for a given signal is not set, the signal is not blocked, which means that if it is sent to a process (either with a "kill()" call or by the system internally generating the signal), the action specified for the signal is taken. This action can be: SIG_IGN, which is "ignore", i.e. completely throw the signal away, don't queue it; SIG_DFL, which is "terminate process" except for some signals where it's "ignore"; or call the handler specified for that signal. If the bit for a given signal *is* set, the signal is blocked, which means that if it is sent to a process, the action is *not* taken, but a bit is set in an internal mask specifying that the signal is pending. When the process's signal mask is changed so that the bit gets turned off, i.e. the signal is unblocked, the action specified for the signal is taken at that time. If the action for a non-blocked signal is to call a handler, when the handler is called the signal is then blocked, so that further occurrences of the signal are posted (actually, only one is posted; if the signal is sent 5 times while it's blocked, it will be delivered only once when unblocked) but not taken. If the signal handler returns normally (e.g., doesn't use "longjmp"), the signal is automatically unblocked. A process can also explicitly block a signal with "sigblock()", or set the signal mask to an arbitrary value, and get the previous value, with "sigsetmask". The "OS/2 Programmer's Guide" doesn't make any explicit mention of a signal mask, so I don't know whether, when a signal handler is called: the signal is blocked, so that further occurrences are posted but not delivered; the signal action becomes "terminate process", so that further occurrences kill the process, as in the bad old days of UNIX; the signal action becomes "ignore", so that further occurrences are not only not delivered, but not even posted; none of the above. If the signal is blocked, does DosSetSigHandler unblock it?
ander@pawl.rpi.edu (Michael R. Primm) (11/12/89)
According to "Advanced OS/2 Programming" by Microsoft Press, when a signal handler is invoked, no further signals of that type are processed until DosSetSigHandler() is called again with an action code of 4 (reset current signal). Also, DosHoldSignal() can be used to temporarily postpose signal handling (signals generated while a hold is in effect are not lost, but wait until the hold ends). As far as I can tell, "masking" signals can be done by simply setting them to have a handler which does nothing but reset the current signal ( or possibly nothing, but I'm not sure if some additional burden would be put on the system by accumulating signals (if they do accumulate...I tend to doubt it, since OS/2's signals are meant to emulate hardware interrupts)). If you wanted to, writing up a routine which could enable and disable signals using a mask should be easy....just keep a static array of pointers to each signal handler, define a "null" handler routine, and have the routine remake a DosSetSigHandler call for each signal which changes state (enabled to disabled, or vice versa). Basically, OS/2's kernal support is complete enough to generate pretty much any service you want....since most of the calls are supported as DLLs, anyone can write up additional services which can work just as well. IMHO, its kinda nice having access to lower level calls...you don't have a specific philosophy imposed upon you as much as on other systems (i.e. you can have any semaphores you want, as long as they're FIFO, etc). --Mike Primm
robertre@microsoft.UUCP (Robert Reichel ms2) (11/14/89)
In article <1989Nov10.025654.3274@eddie.mit.edu> jamin@eddie.MIT.EDU (Sugih Jamin) writes: >In article <8551@microsoft.UUCP> robertre@microsoft.UUCP (Robert Reichel ms2) writes: >>In article <32295@ucbvax.BERKELEY.EDU> jamin@cogsci.berkeley.edu (Sugih Jamin) writes: >>> [Why does one need to reinstate a signal handler after every use?] >>To control reentrancy in your signal handler. > >This point has been well discussed by others. I just want to mention that >it would have been nice of OS/2 to take care of it the way BSD does, instead >of having the programmer take care of it {him,her}self. Fine. I disagree. >Ah, the manual. It, the manual, says that I must use DosSubSet on a >chunk of memory allocated with DosAllocSeg or DosAllocShrSeg. It >doesn't say I must not use it with DosAllocHuge. Normally, I would >assume that only DosAllocSeg and DosAllocShrSeg work with DosSubSet. >But I have been burned once for assuming what the manual doesn't say. >I am referring to DosGiveSeg and DosGetSeg. The manual for DosGetSeg >says that even when one already has a selector to the shared memory, >one still has to call DosGetSeg. But it turns out that one doesn't need to >call DosGetSeg if the selector one got came from DosGiveSeg. I found >this out from the M&T book. The manual is correct, so I don't see how you were "burned". DosGiveSeg makes a selector valid in another process's context (ie copies descriptor information from the LDT of the process making the GiveSeg call into the LDT of the target process). The recipient is able to use the segment immediately, so of course you don't need to call DosGetSeg. DosGetSeg is a two step process. First, you must find out the *value* of the selector you want to get. You must do this via shared memory or your favorite IPC mechanism. Once you have the value, you must call DosGetSeg to make it valid in your context (ie copy its descriptor information into your LDT). Simply knowing a descriptor value won't do a darn thing for you. Similarly, GiveSeg is also a two step process. First call GiveSeg to implant the descriptor information in the target process, and *then* pass the descriptor to the target so that it knows which one to use. Note that GiveSeg returns the value that is to be passed to the target. >Besides, calling DosSubSet on memory allocated with DosAllocHuge >didn't return any error. And it will work correctly in the first 64K subsegment. If you choose to say that this means that it will "work" for a huge segment, that's up to you. The code will not allocate anything from subsequent 64K subsegments. -- My opinions are my own and to not necessarily reflect those of Microsoft Corporation. Robert Reichel {decvax,uunet,uw-beaver}!microsoft!robertre
robertre@microsoft.UUCP (Robert Reichel ms2) (11/14/89)
In article <2620@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: > [description of signal bitmask deleted] > >If the bit for a given signal *is* set, the signal is blocked, which >means that if it is sent to a process, the action is *not* taken, but a >bit is set in an internal mask specifying that the signal is pending. >When the process's signal mask is changed so that the bit gets turned >off, i.e. the signal is unblocked, the action specified for the signal >is taken at that time. What you're describing is the same. We maintain an extra piece of information, because it is illegal to send a signal (other than SIG_KILL) to a process that does not have a handler for it. So in addition to maintaining the current disposition of the signal, we need to keep track of whether it's a valid signal for that process in the first place. >If the action for a non-blocked signal is to call a handler, when the >handler is called the signal is then blocked, so that further >occurrences of the signal are posted (actually, only one is posted; if >the signal is sent 5 times while it's blocked, it will be delivered only >once when unblocked) but not taken. If the signal handler returns >normally (e.g., doesn't use "longjmp"), the signal is automatically >unblocked. This is identical to OS/2, except for the automatic unblocking on return. Doesn't your last sentence contradict what an earier poster described, ie the "complex implementation that acknowledges the signal even if the process does a longjmp" (no, not an accurate quote, but that's how I understood what he said). I don't have the article with the statement handy. One "unblocks" a signal by acknowleging it. >A process can also explicitly block a signal with "sigblock()", or set >the signal mask to an arbitrary value, and get the previous value, with >"sigsetmask". Roughly the same. Substitute DosHoldSignal for sigblock() (I'd imagine, since sigblock() may do things that I'm not aware of). We don't allow direct manipulation of the bitmap. >The "OS/2 Programmer's Guide" doesn't make any explicit mention of a >signal mask, so I don't know whether, when a signal handler is called: > the signal is blocked, so that further occurrences are posted > but not delivered; Yes, as described above. > the signal action becomes "terminate process", so that > further occurrences kill the process, as in the bad old days > of UNIX; No. > the signal action becomes "ignore", so that further occurrences > are not only not delivered, but not even posted; No. At most one is posted, subsequent attempts return error to the sender. >If the signal is blocked, does DosSetSigHandler unblock it? Yes, when called with SIG_ACK. -- My opinions are my own and to not necessarily reflect those of Microsoft Corporation. Robert Reichel {decvax,uunet,uw-beaver}!microsoft!robertre
guy@auspex.auspex.com (Guy Harris) (11/17/89)
>What you're describing is the same. We maintain an extra piece >of information, because it is illegal to send a signal (other than >SIG_KILL) to a process that does not have a handler for it. Hmm. The *OS/2 Programmer's Guide* says "To receive a flag event, the process must register a signal handler in Thread 1 with the DosSetSigHandler function call. If this registration is not done, the system handles the flag for the process and takes appropriate default actions." That sounds more like the UNIX behavior than what you describe; i.e., you're allowed to send a signal with DosFlagProcess even if the process hasn't explicitly registered a handler. (Which one is SIG_KILL? The *OS/2 Programmer's Guide* lists signal 3 as "Terminate"; is that the one to which you're referring?) >Doesn't your last sentence contradict what an earier poster described, >ie the "complex implementation that acknowledges the signal even if >the process does a longjmp" (no, not an accurate quote, but that's how >I understood what he said). In vanilla BSD, "longjmp" does restore the signal mask and unblock the signal. In POSIX, it does so only if the matching "setjmp" was actually a "sigsetjmp" that specified that the signal mask be saved; otherwise, it doesn't. >One "unblocks" a signal by acknowleging it. The word "acknowledge" doesn't appear in the index of the *OS/2 Programmer's Guide*, or at least not the edition here, and it definitely doesn't refer to registering a signal handler with DosSetSigHandler as "acknowledging" it. You later say that DosSetSigHandler unblocks a signal if called with SIG_ACK, but the *OS/2 Programmer's Guide* doesn't mention any argument that would mean something like that, so either the Programmer's Guide is incorrect or the interface to DosSetSigHandler changed after that edition of the Programmer's Guide was written, apparently. (The one from which I'm reading this has no "Nth edition" numbering in any obvious place, and has a copyright date of 1988.) >Roughly the same. Substitute DosHoldSignal for sigblock() (I'd imagine, since >sigblock() may do things that I'm not aware of). All "sigblock()" does is 1) add the signal in question to the list of signals being blocked and 2) return the previous signal bit mask. >We don't allow direct manipulation of the bitmap. That could be a problem if you implement a POSIX interface to OS/2, since POSIX *does* allow direct manipulation of the signal mask. Presumably, if, as, and when a POSIX interface is provided for OS/2, a mechanism will be provided to allow direct manipulation of the signal mask.
ccastmj@prism.gatech.EDU (Joseph Lawrence Martin) (11/18/89)
In message: <1989Nov10.025654.3274@eddie.mit.edu> jamin@eddie.mit.edu (Sugih Jamin), writes: > Ah, the manual. It, the manual, says that I must use DosSubSet on a > chunk of memory allocated with DosAllocSeg or DosAllocShrSeg. It > doesn't say I must not use it with DosAllocHuge. Normally, I would > assume that only DosAllocSeg and DosAllocShrSeg work with DosSubSet. > ... > this out from the M&T book. Besides, calling DosSubSet on memory > allocated with DosAllocHuge didn't return any error. All DosAllocHuge does is allocate a series of memory blocks whose selectors are evenly spaced throughout one's LDT (this space between them is found from a function call). Once a block's selector is known, it can be used as if it were a stand-alone memory segment when used with "simple" calls like DosSub{Set,Alloc,Free}, but only as a single segment. Those functions will not cross the segment boundaries. I think that the only connection that remains between the segments allocated with DosAllocHuge is that they can be deallocated all at once (I think) with a function call. > Now that we have mentioned the manual, allow me to ask, "Why is > Microsoft so inconsistent in making up function names?" For dealing > with semaphores, for example, we have DosOpenSem, DosCreateSem, etc., > but we also have DosSemRequest, and DosSemWait. A simple test: I think that the reason behind the inconsistent naming "conventions" is tied to the classic "7-letter limit" for distinct external link-time references, and if all the semaphore commands were DosSem..., then there would only be 1 letter left (at least) for distinguishing all the semaphore commands (risky). That is, DosSemWait and DosSemWhatsit would be the same. I am not sure if this is totally accurate, but it looks plausible. Of course, they could have been named by different committees working on commands split up arbitrarily, but that never happens. :-) > Then there is that Hungarian notation. It simply defeats the whole > purpose of data abstraction, doesn't it? Even the manual itself got > confused over it. In more than one instances, the manual errorneously Yes, that notation is weird and ambiguous at best. And mentioning confused manuals, I have noticed several inconsistencies in Iacobucci's (no offense) book on OS/2, mainly in some of the descriptions of the interfaces to the function calls. I would use the descriptions in the book, but when I was unsure about a function's interface, I would have to break out the Tech Ref. Maybe these glitches will be fixed in a later edition of the book. Disclaimer: I speak for myself alone, and not for my employer (as if any of you know where I work :-). -- Joseph Lawrence Martin Georgia Institute of Technology, Atlanta Georgia, 30332 uucp: ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!ccastmj Internet: ccastmj@prism.gatech.edu
robertre@microsoft.UUCP (Robert Reichel ms2) (11/21/89)
In article <2639@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: >Hmm. The *OS/2 Programmer's Guide* says "To receive a flag event, the >process must register a signal handler in Thread 1 with the >DosSetSigHandler function call. If this registration is not done, the >system handles the flag for the process and takes appropriate default >actions." That sounds more like the UNIX behavior than what you >describe; i.e., you're allowed to send a signal with DosFlagProcess even >if the process hasn't explicitly registered a handler. (Which one is >SIG_KILL? The *OS/2 Programmer's Guide* lists signal 3 as "Terminate"; >is that the one to which you're referring?) I don't have a copy of this handy. I assume it's what came with the SDK? Regardless, you can bang on something with DosFlagProcess all you want, but unless it has a handler registered, you're going to get an error back. SIG_KILL is what is sent by DosKillProcess. You can't send it via DosSendSignal. I apologize for the confusion on some of the names and constants, for reasons unknown to me the same thing is often referred to by different names in different places. The IBM Tech ref doesn't use SIG_KILL, but rather SIGTERM. >>One "unblocks" a signal by acknowleging it. > >The word "acknowledge" doesn't appear in the index of the *OS/2 >Programmer's Guide*, or at least not the edition here, and it definitely >doesn't refer to registering a signal handler with DosSetSigHandler as >"acknowledging" it. You later say that DosSetSigHandler unblocks a >signal if called with SIG_ACK, but the *OS/2 Programmer's Guide* doesn't >mention any argument that would mean something like that, so either the >Programmer's Guide is incorrect or the interface to DosSetSigHandler >changed after that edition of the Programmer's Guide was written, >apparently. (The one from which I'm reading this has no "Nth edition" >numbering in any obvious place, and has a copyright date of 1988.) Again, I'm not sure what's in the Programmer's Guide. The IBM Tech Ref describes the acknowledge parameter as having a value of 4 and the action of "The current signal is reset without affecting the disposition of the signal." Here's the lot: Value Description 0 The system default action is installed for the signal 1 The signal is to be ignored 2 The routine receives control when the SigNumber occurs 3 It is an error for any program to signal this SigNumber to this process 4 The current signal is reset without affecting the disposition of the signal SigNumber Number Term Definition 1 SIGINTR Ctrl-C 3 SIGTERM Program terminated 4 SIGBREAK Ctrl-Break 5 Process Flag A 6 Process Flag B 7 Process Flag C Not to sound like I'm plugging a product, but a 4th volume of the OS/2 Programmer's Reference just came out, and it has a fair number of corrections to the stuff that was in the first three volumes. They missed some stuff (sigh) but fixed quite a bit also. It might clear up some confusion out there. -- My opinions are my own and to not necessarily reflect those of Microsoft Corporation. Robert Reichel {decvax,uunet,uw-beaver}!microsoft!robertre
robertre@microsoft.UUCP (Robert Reichel ms2) (11/21/89)
In article <9094@microsoft.UUCP> robertre@microsoft.UUCP (Robert Reichel ms2) writes: >I don't have a copy of this handy. I assume it's what came with the >SDK? Regardless, you can bang on something with DosFlagProcess all >you want, but unless it has a handler registered, you're going to >get an error back. Ha! What a hosehead. The default action for a flag is ignore, so the sender won't get an error back. Serves me right for trusting my memory. Sorry 'bout that. Even Mother makes mistakes sometimes... -- My opinions are my own and to not necessarily reflect those of Microsoft Corporation. Robert Reichel {decvax,uunet,uw-beaver}!microsoft!robertre