dymm@b.cs.wvu.wvnet.edu (David Dymm) (03/11/89)
First, THANK YOU to all of the people who took the time to answer my first (& second) requests for help on the interrupt handler problem. I have a second problem that also involves interrupt handlers, but is somewhat different from the previous problems. I would appreciate comments, criticisms, laughter, etc. about the following architecture, and answers to the questions at the end. The architecture of the system is as follows (running on BSD 4-2 Unix on a Sun 3 and/or 4): Kernel (single process) | Separate Tasks (separate processes) ------ | ----------------------------------- | Round-Robin Dispatcher | task1 | task2 Query Processor | task3 | task4 | task5 | . | . The round robin dispatcher loops between the separate tasks. Each task is a separate process. The purpose of a task is to act as a query interface between some external user and the Kernel The task uses IPC to communicate user queries for information to the kernel, and to return the requested information from the kernel to the user. Each task is a small, efficient process used solely for communications. Each task is fast and will not cause appreciable degradation of the kernel. (Note: The nature of the tasks is such that the above architecture is required.) Most queries from the user (via a task) to the kernel are simple queries for information. The query is processed quickly by the kernel's "query processor", and the dispatcher can quickly move on to the next task. The user attached to the next task will see no appreciable time delay. However an Occasional query from a user will require an "appreciable" amount of computation by the query processor. This will delay the dispatcher and cause appreciable delays for the waiting users. SOLUTION (???): To handle these delays, use the system calls "signal" and "ualarm". "Signal" will interrupt the kernel in the middle of its processing, and cause the "alarm_handler" to execute. The alarm handler will do some minor processing, and then a "longjmp" back to the dispatcher. The dispatcher will then go on to the next task. When the dispatcher comes back to the interrupted task, it will "longjmp" to the end (IS THIS CORRECT??) of the alarm_handler which will do a "return (0)", and cause the dispatcher to pick up from where it left off when the task was interrupted. Assume 6 tasks where tasks 2, 5, and 6 pass queries causing the kernel to be slow and to be interrupted. The flow of the dispatcher should be: (top of dispatcher loop) task 1 -- ok task 2 ** slow, interrupt ==> to alarm_handler task 3 -- ok task 4 -- ok task 5 ** slow, interrupt ==> to alarm_handler task 6 ** slow, interrupt ==> to alarm_handler (back to top of dispatcher loop) task 1 -- ok task 2 ** was interrupted, so longjmp to alarm handler which does a return (0) task 3 -- ok task 4 -- ok task 5 ** was interrupted, so longjmp to alarm handler which does a return (0) task 6 ** was interrupted, so longjmp to alarm handler which does a return (0) (etc .......) PROBLEM: the system stack after the first loop through the dispatcher will look like the following: (top) task 6 task 5 task 2 When the stack gets popped in alarm_handler (via the "return (0)" ), task 6 will get popped first. But since task 2 got interrupted first, I want task 2 to get popped first. How do I manipulate the system stack to have tasks popped in the "correct" order ??? Are there any holes/bugs/etc. with the above architecture ??? Thanks in advance for any help, comments, criticisms, etc. David Dymm Software Engineer USMAIL: Bell Atlantic Knowledge Systems, 145 Fayette Street, Morgantown, WV 26505 PHONE: 304 291-9898 (8:30-4:30 EST) USENET: {allegra,bellcore, cadre,idis,psuvax1}!pitt!wvucsb!dymm INTERNET: dymm@b.cs.wvu.wvnet.edu
chris@mimsy.UUCP (Chris Torek) (03/12/89)
In article <321@h.cs.wvu.wvnet.edu> dymm@b.cs.wvu.wvnet.edu (David Dymm) writes: >... When the dispatcher comes back to the interrupted task, it will >"longjmp" to the end (IS THIS CORRECT??) If you mean `using the function longjmp() found in the C library', the answer is `no'. If you try this under 4.2BSD or 4.3BSD (by which I mean `4.2BSD or 4.3BSD', not `SunOS', nor any other system *derived from* 4.2BSD, although it *may* still happen there), you will get a `longjmp botch' and a core dump. >of the alarm_handler which will do a "return (0)", and cause the >dispatcher to pick up from where it left off when the task >was interrupted. It is possible (although difficult and nonportable) to do what you have described (a variant of coroutines), but you cannot use longjmp(), as it is restricted to jumping `upward' in the stack (assuming the stack grows downward). Coroutines jump upward half the time and downward half the time. (Well, close enough. :-) ) In addition, it is necessary to reserve sufficient stack space to each task so that no one task will write over another. How much space is required depends upon the tasks. Most existing 4BSD and SysV implementations will not help you detect collisions. Under operating systems that let you protect individual pages in different ways, you can make an inaccessible `red zone' below each task stack. SunOS 4.x should be able to do this. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris