john13@garfield.UUCP (John Russell) (10/24/87)
-- I recently read that non-reentrant programs can still be made resident as long as you only attempt to run one copy at a time. The fellow who mentioned it talked about doing this with his Modula-II compiler, and it does indeed sound like a useful setup if you DO have enough ram to keep a semi-large executable in memory but DON'T have enough to run Sculpt 3D, Videoscape 3D and a compile/edit session all at the same time. I know this isn't the favourite topic for the CBM people on the net, but is this fact at least accurate? It would seem to be handy for advanced users who would take adequate care. (On the wish list, if not a resident that works well for everything, how about a DOS loader that looks at a resident program's reference count and refuses to let you run it if it's non-zero and the program is non-reentrant?). John PS: Killer .sig line, Bryce :-). -- To preserve deniability, I have not informed the University of this posting. But if I had, they would have been 100% behind it, yessirree bob. This posting has statements that are evasive, misleading, and just plain wrong. But that is only because I love the UseNet with all my heart!
page@ulowell.cs.ulowell.edu (Bob Page) (10/24/87)
john13@garfield.UUCP (John Russell) wrote: >I recently read that non-reentrant programs can still be made resident as >long as you only attempt to run one copy at a time. Absolutely untrue. Suppose you have global variables in your program. On startup they're zero. Your program mucks around with them, then exits. The data stays resident too, not just the text. You start up your program again, your program uses the data from the last run. That includes things like loop counters, File Handles, Window Pointers, devices, etc, which might not be there any more. Guess what happens... Sure, you could program around this by always freeing and zeroing everything you use on exit, and zeroing everything on startup, but you can't depend on other programmers to do that, and even so, there are other dangers of RESIDENT lurking, which I have more than once discussed here. Don't use RESIDENT. The concept is great; the implementation flawed. Wait until there's one that works. ..Bob -- Bob Page, U of Lowell CS Dept. page@ulowell.{uucp,edu,csnet}
bryce@hoser.berkeley.edu (Bryce Nesbitt) (10/25/87)
In article <4086@garfield.UUCP> john13@garfield.UUCP (John Russell) writes: >-- >I recently read that non-reentrant programs can still be made resident as >long as you only attempt to run one copy at a time.... This is nice if you have enough memory to keep ONE copy of the program (say, a compiler) in RAM, but not enough to keep the program in RAM *and* in the RAM disk. >I know this isn't the favourite topic for the CBM people on the net, but is >this fact at least accurate? Not a CBM person, but... yes it is... read on. >It would seem to be handy for advanced users >who would take adequate care. (On the wish list, if not a resident that >works well for everything, how about a DOS loader that looks at a resident >program's reference count and refuses to let you run it if it's non-zero >and the program is non-reentrant?). There are two clases of resident compatibility: REUSABLE This means you can run a program, exit, then run the same memory image again. The only restriction is no self modifying code that does not unmodify itself, and don't destroy any static initialized data that is need next run. Most C programs qualify. For the purposes of this resident, RESUABLE also implied CLEAN. This means that at any time a copy of the program could be made... no self modifying of any initized code or data permitted. This was expected to change to accomodate static initilization better... probably by keeping a separate copy of any volitile hunks. REENTRANT This means you can run the same program twice in the same memory image. We'll assume a single progcessor environment :-). MMU's can be convinced this type of thing is proper, so no troubles here. With this more stringent requirement you can't do *any* self modifying code, you must specifically AllocMem *ANY* memory that you write to. THIS MEANS NO GLOBALS FROM C! Worse yet, the standard startup modules violate this rule for stdin, stdout, sysbase etc. Since local varriables are allocated on the stack at run time, that is ok. Few Amiga programs qualify as of yet. All the BCPL programs in the c: directory do. For comparison, all of the Amiga ROM routines must be reentrant, since any task can call them. Under V1.1 DisplayBeep() was not reentrant, causing problems (source: V1.2 change notes). REENTRANT implies RESUSABLE and CLEAN. A while back I wrote most of a Resident that used a great deal of heuristics to determine what class an executable was in. For example it could detect BCPL and notice BSS hunks. It could also notice a special HUNK that had a format something like this: hunk_startupinfo LONG numlongs ;how long is this hunk? LONG minstacksize ;absolute minimum stack needed LONG flags This project lost steam when I got enough memory not to care. Now everything lives in VD0: and will come back "from the dead". A recoverable resident is a hot idea... The flags are I_AM_REENTRANT I_AM_REUSABLE I_AM_CLEAN and SEPARATE_INVOCATION. (more flags could be added) The first three are obvious, the third can be set to force separete invocation even if the program is reentrant and/or reusable. If the program is NOT reusable the new resident was to treat itself as a RAM disk, it would "reload" the program for each invocation. If the program was clean and reusable, but NOT reentrant, the new resident was to look at the use count. If it was in use, it would "reload" another copy. Else it would simply start it running in place. Not clean, but not resuable was only at the planning stage. It would either require another entire copy of the program, or a way to flag the dirty hunks. If the program WAS reentrant, the new resident would increment the use counter and start the program in place. None of this was very complex. As a long term solution it is probably better to have a "real" DOS. (or some real CAOS :-) |\ /| . Ack! (NAK, SOH, EOT) {o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (") U "Here. This'll shoot the lips off a cockroch" -Freedom Fighter
dillon@CORY.BERKELEY.EDU (Matt Dillon) (10/25/87)
>I recently read that non-reentrant programs can still be made resident as >long as you only attempt to run one copy at a time. I am pretty sure the 'resident' programs are stored as segment lists (via LoadSeg). In this case, you cannot make a program resident unless it was written to be resident, EVEN IF YOU ONLY RUN ONE COPY AT A TIME!. The reason is simply... global variables. If the program modifies any of it's global variables, they will stay modified when the program is rerun at some later time. When one makes a declaration like: int GlobalVariable = 4; One assumes that the variable will hold 4 when the program is first run. Not so if the program modifies it and you then attempt to run the program again (if it is resident). The value will not initially be 4 on the second running. -Matt
shs@ji.Berkeley.EDU (Steve Schoettler) (10/27/87)
In article <21428@ucbvax.BERKELEY.EDU> bryce@hoser.berkeley.edu.UUCP (Bryce Nesbitt) writes: > >REENTRANT This means you can run the same program twice in the same memory >image. We'll assume a single progcessor environment :-). You don't have to. The requirements for multiple processors running the same code image are the same as those for multiple tasks running the same code (in terms of code and data spaces). Now, if you have to synchronize them, that's another story. > > A recoverable resident is a hot idea... > >If the program is NOT reusable the new resident was to treat itself as >a RAM disk, it would "reload" the program for each invocation. > I had an idea about a year ago but forgot about it until now. What about sorting an exacutable file's hunks on the disk so that the data hunks come first? Then rewrite LoadSeg() to first look and see if the program is "resident" and if so, only load in the new data hunks. This could result in much faster loading for programs already running, and more efficient memory usage. Programs could modify variables (including globals) however they wanted because they would all have their own data space. You also have to rewrite UnloadSeg to know about this. Since each task has a segment list, it would have to be organized as follows, with the data segments at the head of the list and the code segments at the tail: task1->seglist-> first second last data -> data -> ... -> data - block block block \ \ \ first last /-> code -> ... -> code / block block task2->seglist-> first second last / data -> data -> ... -> data - block block block Reorganization like this would make a fork() routine trivial: :-} copy all data blocks, create a task and build a its segment list as shown above, copy the stack and registers, do a get_aX() (whatever it takes to point to the base of data space) and return from fork() appropriately. Now that I remember, I started to write something to do this, but when you start getting into the internals of LoadSeg and the DOS loaders, it gets ugly. Is this plausible? Anyone else want to pick up the ball? Steve Schoettler ...ucbvax!ji!shs
bryce@hoser.berkeley.edu (Bryce Nesbitt) (10/27/87)
In article <21466@> shs@ji.Berkeley.EDU.UUCP (Steve Schoettler) writes: >In article <21428@> bryce@hoser.berkeley.edu.UUCP (Bryce Nesbitt) writes: >> >>If the program is NOT reusable the new resident was to treat itself as >>a RAM disk, it would "reload" the program for each invocation. > > I had an idea about a year ago but forgot about it until now. > > What about sorting an exacutable file's hunks on the disk so that the data >hunks come first? Then rewrite LoadSeg() to first look and see if the >program is "resident" and if so, only load in the new data hunks. >.... > Programs could modify variables (including globals) however they wanted >because they would all have their own data space. You forget that code segments have absolute references into the data segements. For this reason it is not possible to have multiple data segments for multitple tasks. (Unless the programs knew about it in advance... which is not what we are talking about) > Steve Schoettler > ...ucbvax!ji!shs |\ /| . Ack! (NAK, SOH, EOT) {o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (") U "Fanitic: One who can't change his mind, and won't change the subject."
keith@tic.UUCP (Keith Clifford) (11/01/87)
In article <21466@ucbvax.BERKELEY.EDU>, shs@ji.Berkeley.EDU (Steve Schoettler) writes: > What about sorting an exacutable file's hunks on the disk so that the data > hunks come first? Then rewrite LoadSeg() to first look and see if the > program is "resident" and if so, only load in the new data hunks. > Programs could modify variables (including globals) however they wanted > because they would all have their own data space. It's always disappointing to find out a great idea which you had, someone else had first (multiple processes running the same code, the rest of the stuff is new to me). Some distinctive way of telling that the code is reentrant would have to be determined (one that some other non-reentrant code would not mimmick by accident). So I would prefer adding new routines like LoadRentrant and CreateRentrant and leave the house keeping up to the programmer as is consistant with exec programming philosophy. Processes are entered at the first location of the first segment by the caller, possibly a CreateProc, but this would require putting code in a data segment (ICH). All of this is of course surmountable but the monster grows. When the idea first came to me, I approached it with the intent of replacing C: for useful routines like copy, cd, dir, and newcli. Rewriting all of these routines in assembly creating a device driver/handler that could load a copy of data into memory from the device and would pass control to it. I have a hack set of routines that sets up and runs multiple tasks using the same code. If anyone is interested I could ship you source and executables. But thank you. You've given me some ideas which could prove fruitful (if I ever get motivatuffic