iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) (08/23/88)
[In "Re: Need info on exceptions", "Morgan W. Jones" said:] > > In article <1754@munsell.UUCP> jdj@munsell.UUCP (Joel Jennings) writes: > >I am looking for a way to cause my program to take an exception periodically > >so that it can write out intermediate results of a long calculation* (see > > One approach that seems reasonable would be to send a message to the > timer.device asking it to send you a message in ten minutes (600 secs). > Arrange that the reply port that it sends to generates a software > interrupt of priority higher than your program (so that it preempts > it), and this swi can delete the message, ask that another message > be sent in ten minutes, and write out your intermediate data. Of > course, you'd have to make sure that a swi can do things like delete > messages, send messages, open files, etc. > Unfortunately it can't. "To avoid serious problems, the interrupt routine must not use any of the memory allocation or deallocation functions"--RKM. That's apparently because critical system code is surrounded by Forbid(), but not Disable(). That doesn't seem to leave much that interrupts can do. Once again, we're stuck with polling (and this on a multitasking OS).
iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) (08/23/88)
[In "Re: Need info on exceptions", Ronald G Minnich said:] > > In article <413@brambo.UUCP> morgan@brambo.UUCP (Morgan W. Jones) writes: > >One approach that seems reasonable would be to send a message to the > >timer.device asking it to send you a message in ten minutes (600 secs). > Hmm, we have a very nice OS here with a shared address space and > named blocks of memory and lightweight tasks and .... > we are still thinking in terms of Unix. > > Or, maybe: > Spawn a lightweight process (task is such a better word, > but Mach kinda changed the meaning). Since it shares your > context it *knows* where to look and how often to print. > I am lying maybe since i have not done much with tasks. > Can someone flesh this one out? > > On unix you HAVE to have the signal cause sharing data in > memory is so damn hard. On amiga sharing (even unintentional) is > the easiest thing. Many processes can easily share an array. So > why not do it, and save yourself the trouble of having signal > handlers and such? > In principle, Tasks are not supposed to know about each other's memory space. In practice, the Manx geta4() function makes the globals common. I would think the "correct" way on the Amiga would be to send a message to the Task with the address of the array to be accessed, then wait for a reply. Even if Tasks are directly sharing memory, they need to be synchronized to avoid reading and writing data at the same time, so you do need at least a signal. -- Bill Kinnersley Physics Department BITNET: iphwk@mtsunix1 Montana State University INTERNET: iphwk%mtsunix1.bitnet@cunyvm.cuny.edu Bozeman, MT 59717 CSNET: iphwk%mtsunix1.bitnet@relay.cs.net (406)994-3614 UUCP: ...ucbvax!mtsunix1.bitnet!iphwk "This message was packed as full as practicable by modern electronic equipment. Some settling of contents may have occurred during transmission."
rminnich@super.ORG (Ronald G Minnich) (08/24/88)
In article <3794@louie.udel.EDU> iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: >I would think the "correct" way on the Amiga would be to send a >message to the Task with the address of the array to be accessed, >then wait for a reply. Sure, that is ONE way. Point is, on the Amiga, there are LOTS of ways. >Even if Tasks are directly sharing memory, they need to be synchronized >to avoid reading and writing data at the same time, so you do need >at least a signal. well, for some cases, yes you need synchronization. But for the specific case of having information available about the state of a computation, you absolutely do not. The reason is that the variables related to 'doneness' of the computation are just simply going to get larger with time*. So what if you read the variable just before it gets increased? Your monitor process might be a little off, but such would be the case if the clock interrupt came in before the variable got increased. Back to the question at hand. The signalling that the person was looking for was to allow a process to be interrupted and thus get state information ('doneness' of the computation) out of that process. This sort of thing has been done for years and years on Unix and when you think about what is happening it is really a poor man's way of spawning a lightweight process that prints out state informatino and quits. In addition the parent blocks. And you have all this yucky overhead. On the amiga, on the other hand (or on the Sequent with its microtasking library, or maybe SunOS4 with its task library) you can have a compute task and an information task. You don't interrupt the computation to get information about the computation, and you can get information at any time, not just when a clock strikes. ron * Let's see, can we see they are monotonically increasing? Sure, why not?
peter@sugar.uu.net (Peter da Silva) (08/24/88)
In article ... iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: > Unfortunately it can't. "To avoid serious problems, the interrupt > routine must not use any of the memory allocation or deallocation > functions"--RKM. That's apparently because critical system code > is surrounded by Forbid(), but not Disable(). > That doesn't seem to leave much that interrupts can do. Once again, > we're stuck with polling (and this on a multitasking OS). You shouldn't be doing much in an interrupt, on any system. These are real hardware-type interrupts, you know. For software interrupts, you can probably get away with doing memory hacking, since you know that the task which posted them wasn't doing anything dangerous when it was posted. But, really, you don't need to do anything like that, anyway... because you can signal a sleeping task to do the actual grunt-work. For this application, you should probably have the computation done with a subtask which signals the sleeping main program at appropriate points in the calculation.
dillon@CORY.BERKELEY.EDU (Matt Dillon) (08/25/88)
Time to go into a brief description of the three types of interrupts
that exist on the Amiga:
(1) Task Exceptions (via SetExcept() and standard signals). This is a
task-level interrupt and only interrupts the task it is attached to.
Other tasks still run... the interrupt only interrupts the one task.
That is, any number of tasks may be handling exceptions all simultaniously.
This is analogous to UNIX signals with one major exception.... system
calls can get interrupted in the middle (i.e. library calls). Although
all run-time libraries are reentrant between tasks, this is not always
so within a given task. For instance, you cannot interrupt a DOS Write()
with an exception and then do a Write() from within the exception!!
Another for instance: you CAN call AllocMem().
So you have to be very careful as to when to allow an exception and when not
to. Forbid() effectively disables exceptions (but also task switching).
Also, there is a bug in the exception handler in that if an exception
occured during a Forbid() it does NOT execute when you Permit()... i.e.
you also have to do a SetExcept(0,0) to force EXEC to check for active
exceptions after you Permit().
The 'simple' description of an exception is this: First, a task gets
signalled and if the exception bit for that signal bit is set, the
EXCEPTION-ENABLE BIT AND THE SIGNAL BIT IS CLEARED and the task then enters
its exception handler. D0 contains a mask of the exception that occured
(more than one bit may be set if more than one exception occured
at once). The exception handler thus must be reentrant for different
exception bits.
After the handler runs, it must return a bitmask in D0 of those exceptions
that occured. EXEC automatically ENABLES the exceptions specified by
the bitmask. However, it doesn't check to see if they re-occured at this
time... Thus, there is a window of vulnerability here. Usually, I
reenable the exceptions manually with a SetExcept() call from the handler
and return 0 in D0. Unlike other types of interrupts, EXEC saves and
restores ALL of our registers (except the stack pointer) for us. But,
you cannot make assumptions as to the contents of the registers (except
for D0 and A1(=tc_ExceptData). Specifically, there is no guarentee
A4 will contain the small-code-model data segment base so you must reload
it if you intend to use that model inside the handler.
(2) Software Interrupts. Software interrupts are HIGHER priority than tasks
but LOWER priority than interrupts. Essentially, these are pseudo
hardware interrupts but without the timing restrictions in real
interrupts.... you can do things that you would not want to do in normal
interrupts because they would otherwise take too long.
BUT! A software interrupt is not a task, and you still may not use
memory allocation/free functions within one (same restrictions as for
hardware interrupts apply with the exception that you can take a longer
time in the soft int). For example, instead of calling ReplyMsg() from
an HARD interrupt handler you might want to Cause() a softint instead.
This allows the HARD int to end (and other HARD ints to occur).
A software interrupt uses the same structure as a hardware interrupt.
(3) Hardware Interrupts. Real honest to goodness hardware interrupts.
Implemented by SetIntVector() and AddIntServer() and the like. These
are real hardware interrupts and the service routine should take as
little time as possible in them... I mean as *little* time as possible.
Make your code tight. Calling something like ReplyMsg() or PutMsg(),
while it works, usually takes too much time for an interrupt handler
to spare. Cause() a softint for things that take too much time so
other interrupts can go. I don't know how much time Signal() takes.
There are two flavors. (1) Direct hardware interrupts (SetIntVector()),
and (2) Chained hardware interrupts. In many cases there are also
resources (misc.resource, for instance) to arbitrate usage of some of
the interrupt vectors.
-Matt
:In article ... iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes:
:> Unfortunately it can't. "To avoid serious problems, the interrupt
:> routine must not use any of the memory allocation or deallocation
:> functions"--RKM. That's apparently because critical system code
:> is surrounded by Forbid(), but not Disable().
:
:> That doesn't seem to leave much that interrupts can do. Once again,
:> we're stuck with polling (and this on a multitasking OS).
:
:You shouldn't be doing much in an interrupt, on any system. These are real
:hardware-type interrupts, you know. For software interrupts, you can
:probably get away with doing memory hacking, since you know that the task
:which posted them wasn't doing anything dangerous when it was posted. But,
:really, you don't need to do anything like that, anyway... because you can
:signal a sleeping task to do the actual grunt-work.
morgan@brambo.UUCP (Morgan W. Jones) (08/26/88)
In article <3793@louie.udel.EDU> iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: >[In "Re: Need info on exceptions", "Morgan W. Jones" said:] >> course, you'd have to make sure that a swi can do things like delete >> messages, send messages, open files, etc. >Unfortunately it can't. "To avoid serious problems, the interrupt >routine must not use any of the memory allocation or deallocation >functions"--RKM. That's apparently because critical system code >is surrounded by Forbid(), but not Disable(). I'm not so sure. True, if you are dealing with "real", harware generated interrupts you run into this problem. Software interrupts, however, are generated by the operating system. Thus, it seems that it would be impossible to destroy kernel data from inside a software interrupt - they should all be valid. Software interrupts are actually recommended in the RKM for use when you want to do a lot of processing inside an interrupt so that the system doesn't slow down - this implies that the system multi-tasks during software interrupts and so the software interrupt should appear as a task to the O/S. Any Gurus want to comment on this? -- Morgan Jones morgan@hcr.UUCP Human Computing Resources, Toronto, Canada "BMATH - 8 months and counting ..."
dillon@CORY.BERKELEY.EDU (Matt Dillon) (08/28/88)
:generated interrupts you run into this problem. Software interrupts, :however, are generated by the operating system. Thus, it seems that :it would be impossible to destroy kernel data from inside a software :interrupt - they should all be valid. Software interrupts are :actually recommended in the RKM for use when you want to do a lot of :processing inside an interrupt so that the system doesn't slow down - :this implies that the system multi-tasks during software interrupts :and so the software interrupt should appear as a task to the O/S. : :Any Gurus want to comment on this? Yes I would. You are dead wrong. Sorry. SOFTWARE INTERRUPTS ARE JUST LIKE HARDWARE INTERRUPTS! The only difference is that normal hardware interrupts can occur while one is processing a software interrupt. The system does not multi-task while one is processing a software interrupt. Neither can you AllocMem() inside a software interrupt. same rules apply as for hardware interrupts. -Matt
iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) (08/29/88)
[In "Re: Need info on exceptions", Ronald G Minnich said:]
:
: In article <414@brambo.UUCP> morgan@brambo.UUCP (Morgan W. Jones) writes:
: >Somebody forgot their Operating Systems course, eh?
: >The problem with all of these approaches, of course, is that you've
: >got two processes reading the same data at the same time, or, more
: >specifically, one reading the data while the other is still writing.
: Seems like you might need to actually use this sort of system
: for a while before you understand it. I can't see why this is
: so hard for people to get.
: No, this is NOT A PROBLEM. You have a single writer, single reader.
: The variable relating to DONENESS will INCREASE SLOWLY AS THE
: COMPUTATION PROCEEDS. YOU CAN LOOK AT IT AT ANY TIME!
: PEOPLE DO THIS SORT OF THING ALL THE TIME!!! AMAZING, HUH?
: The writer is the compute process. the reader is the 'front panel'.
: Think a little bit before you comment. Or get a little experience
: with this sort of thing before you comment. Or don't comment.
: Seems that your level of knowledge does not extend much PAST
: an operating systems course!
: Or, try again,
: NO, YOU DON'T NEED SEMAPHORES FOR THIS PROBLEM!!!!
: Get it?
: ron
:
Seems to me it depends on what you're computing, Ron. You're right if
it's just one variable.
Suppose one task is updating a chess board and the other task is printing
it out. The printer may start up just as a piece has been moved to
a new square, but not yet erased from the previous one.
In general, the data set may pass through inconsistent states, and a
semaphore is a way of preventing this problem.
--Bill K.
mlelstv@faui44.informatik.uni-erlangen.de (Michael van Elst ) (08/29/88)
In article <3793@louie.udel.EDU> iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: >[In "Re: Need info on exceptions", "Morgan W. Jones" said:] >> >> In article <1754@munsell.UUCP> jdj@munsell.UUCP (Joel Jennings) writes: >> >I am looking for a way to cause my program to take an exception periodically >> >so that it can write out intermediate results of a long calculation* (see >> >> ... asks about software interrupts from the timer.device ... >> >Unfortunately it can't. "To avoid serious problems, the interrupt >routine must not use any of the memory allocation or deallocation >functions"--RKM. That's apparently because critical system code >is surrounded by Forbid(), but not Disable(). > >That doesn't seem to leave much that interrupts can do. Once again, >we're stuck with polling (and this on a multitasking OS). Hello, I don't think that you have to poll for this. There are two approaches to this problem. If your program is designed as an event loop (i.e. a loop Wait()ing for messages and then working on each of them) you can easily send a request to the timer.device to wake you up. When the timer replies your request you can write out your intermediate results and post another request to the timer. Thereis a problem if you have to Wait() at another point in your program (likewise a DOS call, that Wait()s internally for IO to complete). You MUST disable any verify IDCMP messages for intuition is locked until you reply. If then a requester wants to apear ("Please insert...") you get a deadlock situation. You might disable other event sources (i.e. menus) if handling an event lasts for a longer time. Otherwise input events might be allocated at your message port and might not be freed until your program ends. If your program cannot be designed as an event loop (in this case it seems to be so for you want to calculate something) you may spawn another process that deals with the DOS and that is woken up by the timer.device. The problem there is to get a real 'Process' because you have to call DOS routines, a simple 'Task' cannot do this. The only legal way to create a process is to call the DOS function CreateProc but it uses a structure called SegList. Therefore you have to LoadSeg() your updating process and to communicate with it to get pointers to your first process' memory. Or you have to construct your own SegList but I haven't found a method to do this from C. (I think Lattice C can do it but I am not sure) A simpler method to get around the need for a process is to construct your main program as an event loop and spawning a 'Task' to do your calculations. To display your calculations (if it is for example a Mandelbrot set or a raytracing picture) you then can send messages to your main process to indicate that a part of the calculation can be used. The task model is sufficient for most applications for you hardly need two or more processes twiddling with DOS. And even this could be done by a single process using asynchronous IO (i.e. sending DOS packets instead of calling DOS functions). Enough said. Michael van Elst E-mail: UUCP: ...seismo!unido!fauern!faui44!mlelstv E-mail: UUCP: ...uunet!unido!fauern!faui44!mlelstv <- when seismo ceases operation
rminnich@super.ORG (Ronald G Minnich) (08/29/88)
In article <3867@louie.udel.EDU> iphwk%MTSUNIX1.BITNET@cunyvm.cuny.edu (Bill Kinnersley) writes: >Seems to me it depends on what you're computing, Ron. You're right if >it's just one variable. Yes, true if it is one variable you are ok. If it is not, then you need semaphores. The original question, as i understood it, was to monitor the progress of a computation, which i assumed would be indicated by one variable. A proposed way was to use the amiga equivalent of signal(), since "that's how it was done on Unix". I feel very strongly that if you can avoid it then don't use interrupts, software or hardware. They are an invitation to trouble, and besides, there are much much much better ways to solve some of these problems on the amiga. I mean, geez, you just do an ObtainSemaphore and a ReleaseSemaphore and there is one to poll a Semaphore. What more could you ask? And they work. Take a look at how people use signals and longjmp() and things on Unix. In many cases it is really gross, but there is no other way because most Unix systems do not even support mmap(), much less a simple system such as shmget(). And the way shmem() works is real gross. But on the amiga we can share memory just by sending each other messages. That is a wonderful capability. A few years ago an unnamed person at an unnamed company wrote a system for IPC that used a high-speed network being developed at Udel. That network presented hosts with the shared-memory model. The ipc system allowed you to send messages that contained memory handles. When i explained that the Amiga IPC already did all this stuff, and that the network hardware would do well on an amiga, i mostly got blank stares ("put a network on a game machine?..."). But the fact remains that the amiga IPC is well designed and sophisticated, and well worth using as a way to share memory between several tasks- something not easily done on Unix. ron
BEB%UNO.BITNET@cunyvm.cuny.edu (08/30/88)
Getting back to the original posting for a second: (not that all this stuff on exceptions and tasking and critical sections wasn't real interesting) I would like to know: Is this application an essentially iterative process? If so, why not just pick some arbitrary number of iterations to count, then checkpoint? If the e.t. of the iterations is non-linear, than how about some similar non-linear decrease in iterations between checkpoints? The advantage here is you avoid the overhead and complexity of multiple tasks and the synchronization thereof, and you don't have to worry about invalid data. Bruce death before disclaimer <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> <>Handle: Bruce Bettis USnail: University of New Orleans <> <>BITnet: <BEB@UNO.BITNET> Computer Research Center <> <>Voices: (504) 286-7067 New Orleans, La. 70148 <> <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
koster@cory.Berkeley.EDU (David Ashley) (08/30/88)
Really getting back to the first question, what would be a good idea is trying to find out why the #1 task bombs in the first place. Rather than work around the bombing, trying to save the state of the system, fix the problem.