mjbo@orstcs.UUCP (mjbo) (01/07/87)
Subject: DOS calls from interrupts --------------------------------------- I have read in several places, including the most recent BIX section of Byte, that it is not legal to call on DOS services from an interrupt-service routine. I would like to write a TSR program to hide in the background and receive data from a serial port using an interrupt routine to store the data in a buffer. When the buffer fills, I would like to store the data in a Hard-disk file dedicated to that purpose. (sort of a print spooler in reverse). Can this be done safely? If so, what restrictions are there on the DOS file-handling calls? Can a foreground program read from the input spooler file without messing it up for the interrrupt service routine> Any hints, answers or references to books or magazine articles would be appreciated. Mark J. Borgerson Dept. of Computer Science. Oregon State University (mjbo@orstcs.csnet) Just Get my name right--so you don't confuse me with my employer.
backman@interlan.UUCP (Larry Backman) (01/12/87)
In article <216700005@orstcs.UUCP> mjbo@orstcs.UUCP (mjbo) writes: > >I have read in several places, including the most recent BIX >section of Byte, that it is not legal to call on DOS >services from an interrupt-service routine. >I would like to write a TSR program to hide in the >background and receive data from a serial port using >an interrupt routine to store the data in a buffer. >When the buffer fills, I would like to store the >data in a Hard-disk file dedicated to that purpose. >(sort of a print spooler in reverse). Can this be done >safely? If so, what restrictions are there on the >DOS file-handling calls? Can a foreground program >read from the input spooler file without messing >it up for the interrrupt service routine> > Calling DOS from an ISR can be done safely; its tricky, and there are a number of things to be taken into account. However, you must use undocumented DOS calls to do so. When an interrupt service routine is kicked off, there is no guarentee where your CS:IP and stack pointeres were before the interrupt occurred. For all you know, you may have interrupted DOS itself, possibly in the middle of a critical section of code. As evryone knows, DOS is not a re-entrant operating system, it is singled threaded, and cannot handle concurrent system calls. However, the folks in Bellevue still needed to be able to detremine when it was safe to do something within their own operating system thus the following two undocumented functions. 1). The "dirty bit". INT 21 function 34 returns the status of DOS's dirty bit indicating whether DOS is in a critical section. If AL returns with a 0, its safe to access DOS, if it returns non-zero, DOS cannot be safely interrupted. 2). The scheduler INT 28 is the DOS scheduler interrupt. When DOS is active but idle ( the keyboard scan loop for instance) it periodically issues an INT 28, allowing other sleeping processes a chance to run. A resident program (such as PRINT or MODE) can grab this vector, and do its thing safely when scehduled by an INT 28. Thes two functions provide the hooks necessary to call DOS from an ISR. Needless to say your ISR must be tied to some sort of non-interrupt code which is capable of performing actions at a later time. Lets say your ISR captures an interrupt, has a full buffer and wants to write that buffer out to file. First the ISR saves the state of the machine and switches the stack. The stack switch is necessary since the DOS stack is only guarenteed to be 80 bytes deep, not enough for any serious processing especially if you intend to re-enter DOS! Once you have swapped stacks you may re-enable interrupts if you so desire. Now comes the fun part! Issue an INT 21 function 34; if it comes back with AL set to 0 your golden; do whatever you want right then and there! If however, it comes back indicating that DOS is in a critical section you must then use the scheduler interrupt to do your DOS access. So, when you started this program you undoubtabl did things like replacing interrupt vectors, well make sure you replace INT 28 with a function of your own. Your printer interrupt handler should be able to share a semaphore with the INT 28 handler, so that when your printer handler is blocked from performing a DOS access, it sets this semaphore saves a pointer to the buffer cleans up after itself and IRETS. Now next time DOS calls INT 28 our handler is activated; it checks the semaphore and if it is set performs the DOS access that was previously blocked. If the semaphore is not set, as should be the case 99% of the time, the INT 28 handler simply IRETS. I hope this provides enough information to get you started, be warned that its tricky and a good debugger is a must. I also suggest disassem- bling PRINT.COM to see how a Microsoft approved resident DOS access works. Feel free to call me if you need more information.. Larry Backman Micom - Interlan, Inc. 155 Swanson Rd Boxborough, Ma. 01719 617-263-9929 x291 ulowell! -\ mit-eddie! --> interlan!backman ihnp4! -/
jrv@siemens.UUCP (01/13/87)
backman@interlan writes: > <deleted discussion of DOS re-entrancy> > > 1). The "dirty bit". > INT 21 function 34 returns the status of DOS's dirty > bit indicating whether DOS is in a critical section. > If AL returns with a 0, its safe to access DOS, if > it returns non-zero, DOS cannot be safely interrupted. > Something is a little strange here. When the resident program gets control via an interrupt and decides it is time to do a DOS function it seems to me to be a little touch and go to CALL DOS and execute function 34 to find out if you can safely make a DOS CALL! Instead Int 21 function 34 should be called before the program is made resident. This function also returns a pointer to the location for the DOS dirty bit in ES:BX. This address should be saved and when the resident program needs to test if DOS calls are safe the value can be tested directly. Jim Vallino Siemens Research and Technology Lab. Princeton, NJ {allegra,ihnp4,seismo,philabs}!princeton!siemens!jrv CSNet: jrv@siemens.siemens-rtl.com
news@cit-vax.Caltech.Edu (Usenet netnews) (01/15/87)
Organization : California Institute of Technology Keywords: TSR, DOS Re-entrancy From: tim@tomcat.Caltech.Edu (Tim Kay) Path: tomcat!tim (1014-Larry Backman) writes: > > Calling DOS from an ISR can be done safely; its tricky, and there > are a number of things to be taken into account. However, you must > use undocumented DOS calls to do so. > > [description of how to do it deleted] I wonder if a ^C handler could be written that would kill the current program even if the program isn't doing any dos calls. Currently, if you hit ^Break or ^C, a bit is set. Then when you call dos, it checks the bit. If set, the ^C handler is called, and your program (by default) is terminated. The problem is that many programs don't make dos calls, and they can't be killed. For example, if you are running a Turbo Pascal program that gets into an infinite loop, you have to reboot the machine. (I know that there is a {$U+} switch, but this makes the program run slower, so I would rather not use it. My C compiler doesn't have the equivalent of {$U+}.) Would it be possible to write a TSR program that notices when ^C is hit and sets a bit. The next time a clock interrupt happens (as described in the article), both this bit and the dirty bit are checked. If ^C has been hit, and it is safe to call dos, then the handler should issue a dos terminate call to terminate the interrupted program. However, before the current program is terminated, this handler should check the address of the ^C handler (int 23h) to see if the current program is handling its own ^Cs. If it is, then the handler should let the current program take the ^C. Does this make sense? Has such a program been written? Could it be done? (Can you call terminate from inside the clock interrupt handler?) Timothy L. Kay tim@csvax.caltech.edu Department of Computer Science Caltech, 256-80 Pasadena, CA 91125
backman@interlan.UUCP (Larry Backman) (01/19/87)
>I wonder if a ^C handler could be written that would kill the current >program even if the program isn't doing any dos calls. > >Currently, if you hit ^Break or ^C, a bit is set. Then when you call >dos, it checks the bit. If set, the ^C handler is called, and your >program (by default) is terminated. The problem is that many programs >don't make dos calls, and they can't be killed. For example, if you >are running a Turbo Pascal program that gets into an infinite loop, >you have to reboot the machine. >Would it be possible to write a TSR program that notices when ^C is >hit and sets a bit. >The next time a clock interrupt happens (as described in the article), >both this bit and the dirty bit are checked. If ^C has been hit, and >it is safe to call dos, then the handler should issue a dos terminate >call to terminate the interrupted program. > >Does this make sense? Has such a program been written? Could it be done? >(Can you call terminate from inside the clock interrupt handler?) > I just spent a couple days last week playing the ^Break/^C game from within a NETBIOS application. If a NETBIOS request has been issued and is pending on the network's response, the only keys that work are\ Ctl-Alt-Del. The INT 23 handler does not see the ^Break or ^C until after a NETBIOS request completes. However, if the NETBIOS request is hung, your dead!! The BIOS break interrupt, INT 1B, will see the ^Break key, but not the Control-C key. In my situation, I fortunately have already captured the keyboard at INT 9, and can filter out whatever keystrokes I want from there, and set semaphores from within the keyboard handler that will be later used by an event processor. I also remember going through contortions to be able to terminate from within the clock handler. I don't have code in front of me but as I recall, the trick was to call INT 21 function 49 (FREE MEMORY) twice, first to free the programs allocated memory, and second to free the PSP of the program. At this point we exitted using INT 21 function 4C, Larry Backman Micom - Interlan, Inc.
michaelm@3comvax.UUCP (Michael McNeil) (01/22/87)
In article <119@interlan.UUCP> backman@interlan.UUCP (1014-Larry Backman) writes: > I also remember going through contortions to be able to terminate from > within the clock handler. I don't have code in front of me but as I > recall, the trick was to call INT 21 function 49 (FREE MEMORY) twice, > first to free the programs allocated memory, and second to free the > PSP of the program. At this point we exitted using INT 21 function 4C, > > Larry Backman > Micom - Interlan, Inc. The memory block of the program begins with the program's PSP, and therefore the PSP is freed with the program. You meant that the second call frees the program's environment, didn't you? Michael McNeil 3Com Corporation Santa Clara, California {hplabs|fortune|idi|ihnp4|tolerant|allegra|glacier|olhqma} !oliveb!3comvax!michaelm
brianc@cognos.UUCP (Brian Campbell) (01/23/87)
In article <1501@cit-vax.Caltech.Edu> tim@tomcat.caltech.edu (Tim Kay) writes: >> >> Calling DOS from an ISR can be done safely; its tricky, and there >> are a number of things to be taken into account. However, you must >> use undocumented DOS calls to do so. >> >> [description of how to do it deleted] > >I wonder if a ^C handler could be written that would kill the current >program even if the program isn't doing any dos calls. > >Currently, if you hit ^Break or ^C, a bit is set. Then when you call >dos, it checks the bit. If set, the ^C handler is called, and your >program (by default) is terminated. The problem is that many programs >don't make dos calls, and they can't be killed. For example, if you >are running a Turbo Pascal program that gets into an infinite loop, >you have to reboot the machine. (I know that there is a {$U+} switch, >but this makes the program run slower, so I would rather not use it. >My C compiler doesn't have the equivalent of {$U+}.) > >Would it be possible to write a TSR program that notices when ^C is >hit and sets a bit. >The next time a clock interrupt happens (as described in the article), >both this bit and the dirty bit are checked. If ^C has been hit, and >it is safe to call dos, then the handler should issue a dos terminate >call to terminate the interrupted program. I believe that there is such a TSR utility. It was presented in one of the earlier issues of PC-Magazine last year. I think it was called UNCRASH. The idea was that hitting Ctrl-Break once would function as always, hitting it twice did something further, and hitting it three times would get you out of just about anything (including a JMP $+0) and terminate the program. I think it was implemented using the keyboard interrupt, but I'm not sure on that. If necessary, I can dig out the issue and either post or email the code (assuming I'm not breaking any copyrights Ziff-Davis may have). Brian Campbell