home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / pexec / pexec.doc
Text File  |  1985-11-19  |  9KB  |  174 lines

  1. Subject: Allan Pratt's Pexec cookbook!
  2. Comment: Extracted from digest info-atari16 87-313
  3. To: info-atari16@score.stanford.edu
  4.  
  5. This is in response to a request from Christian Kaernbach which I got
  6. from  BITNET: I can't reply directly to BITNET, but I'm sure other people
  7. will find this interesting, too: it's a preliminary version of the
  8. long-awaited Pexec cookbook!
  9.  
  10. In broad terms, the things you have to know about Pexec are that it
  11. starts up a process, lets it execute, then returns to the caller
  12. when that process terminates.  The "caller" -- the process which used Pexec
  13. in the first place -- has some responsibilities: it has to make memory
  14. available to the OS for allocation to the child, and it has to build
  15. up the argument string for the child.
  16.  
  17. All GEMDOS programs are started with the largest block of OS memory
  18. allocated to them.  Except in very rare circumstances, this block
  19. is the one stretching from the end of the accessories and resident
  20. utilities to the beginning of screen memory. The point is that your
  21. program has probably been allocated ALL of free memory.  In order to
  22. make memory available for a child process, you have to SHRINK the
  23. block you own, returning the top part of it to GEMDOS.  The time to
  24. do this is when you start up.
  25.  
  26. If you use Alcyon C (from the developer's kit), you know that you
  27. always link with a file called GEMSTART.  If you've been paying
  28. attention, you should have gotten the *new* GEMSTART from Compuserve
  29. (or from somebody else who got it): I wrote that GEMSTART.  In
  30. GEMSTART.S, there is a lot of discussion about memory models, and then
  31. a variable you set telling how much memory you want to keep or give back
  32. to the OS.  Make your choice (when in doubt, use STACK=1), assemble
  33. GEMSTART.S, call the result GEMSEXEC.O (or something), and link the
  34. programs which Pexec with that file rather than the normal GEMSTART.
  35.  
  36. Now here's a discussion of what GEMSTART has to do with respect to
  37. keeping or returning memory:
  38.  
  39. Your program is invoked with the address of its own basepage as
  40. the argument to a function (that is, at 4(sp).l).  In this basepage
  41. is the structure you can find in your documentation.  The interesting
  42. fields are HITPA (the address of first byte NOT in your TPA),
  43. BSSBASE (the first address of your bss) and BSSLEN (the length of
  44. your BSS).
  45.  
  46. Your stack pointer starts at HITPA-8 (because 8 is the length of the
  47. basepage argument and the dummy return PC on the stack).  The space from
  48. BSSBASE+BSSLEN to your SP is the "stack+heap" space.  Library malloc()
  49. calls use this space, moving a pointer called the "break" (in the
  50. variable __break, or the C variable _break if you use Alcyon C) up as it
  51. uses memory.  Your stack pointer moves down from the top as it uses
  52. memory, and if the sp and _break ever meet, you're out of memory.  In
  53. fact, if they ever come close (within a "chicken factor" of about 512
  54. bytes or 1K), malloc() will fail because it doesn't want your stack to
  55. overwrite good data.
  56.  
  57. When a process starts, it gets *all* of memory allocated to it: from the
  58. end of any accessories or resident utilities up to the default screen
  59. memory.  If you want to use Pexec, you have to give some memory back to
  60. the OS.  You do this with the Mshrink call.  Its arguments are the
  61. address of the memory block to shrink (your basepage address) and the
  62. new size to shrink it to.  You should be sure to leave enough room above
  63. your BSS for a reasonable stack (at least 2K) plus any malloc() calls
  64. you expect to make.  Let's say you're writing "make" and you want to
  65. leave about 32K for malloc() (for your dependency structures).  Also,
  66. since make is recursive, you should leave lots of space for the stack -
  67. maybe another 16K.  The new top of memory that your program needs is:
  68.  
  69.     newtop = your bss base address + your bss size + 16K stack + 32K heap
  70.  
  71. Since your stack pointer is at the top of your CURRENT TPA, and you're about
  72. to shrink that, you'd better move your stack:
  73.  
  74.     move.l    newtop,sp
  75.  
  76. Now you want to compute your new TPA size and call Mshrink:
  77.  
  78.     move.l    newtop,d0
  79.     sub.l    basepage,d0    ; newtop-basepage is desired TPA size
  80.     move.l    d0,-(sp)    ; set up Mshrink(basepage,d0)
  81.     move.l    basepage,-(sp)
  82.     move.w    #$4a        ; fn code for Mshrink
  83.     trap    #1
  84.     add.l    #10,sp        ; clean up args
  85.  
  86. Now that you've shrunk your TPA, the OS can allocate this new memory to
  87. your child.  It can also use this memory for Malloc(), which is used
  88. occasionally by GEM VDI for blt buffers, etc.  Note that you only
  89. have to do this once, when you start up: after that, you can do as much
  90. Pexec'ing as you want.
  91.  
  92. When you want to exec a child, you build its complete filespec into one
  93. string, and its arguments into another.  The argument string is a little
  94. strange: the first character of the argument string is the length of the
  95. rest of the string!
  96.  
  97. Here is a simple system call: pass it the name of the file to execute
  98. and the argument string to use.
  99.  
  100.     long system(cmd,args)
  101.     char *cmd, *args;
  102.     {
  103.         char buf[128];
  104.  
  105.         if (strlen(args) > 126) {
  106.         printf("argument string too long\n");
  107.         return -1;
  108.         }
  109.         strcpy(buf+1,args);            /* copy args to buffer+1 */
  110.         buf[0] = strlen(args);        /* set buffer[0] to len */
  111.         return Pexec(0,cmd,buf,0L);
  112.     }
  113.  
  114. The first zero in the Pexec call is the Pexec function code: load and
  115. go.  The cmd argument is the full filespec, with the path, file name,
  116. and file type.  The third argument is the command-line argument string,
  117. and the fourth argument is the environment pointer.  A null environment
  118. pointer means "let the child inherit A COPY OF my environment."
  119.  
  120. This call will load the program, pass the arguments and environment to
  121. it, and execute it.  When the program terminates, the call returns the
  122. exit code from the program.  If the Pexec fails (not enough memory, file
  123. not found, etc.) a negative code is returned, and you should deal with
  124. it accordingly.  Note that error returns from Pexec are always negative
  125. LONGS, while return codes from the child will have zeros in the upper 16 bits.
  126.  
  127. EXIT CODES:
  128.  
  129. GEMDOS, like MS-DOS before it, allows programs to return a 16-bit exit
  130. code to their parents when they terminate.  This is done with the
  131. Pterm(errcode) call.  The value in errcode is passed to the parent
  132. as the return value of the Pexec system call.  The C library function
  133. exit(errcode) usually uses this call.
  134.  
  135. Unfortunately, the people who wrote the startup file for the Alcyon C
  136. compiler didn't use this.  The compiler calls exit() with an error code,
  137. and exit() calls _exit(), but _exit always uses Pterm0(), which returns
  138. zero as the exit code.  I fixed this by rewriting GEMSTART.S, the file
  139. you link with first when using Alcyon.
  140.  
  141. Even though new programs return the right exit code, the compiler
  142. itself still doesn't.  Well, I have patched the binaries of all the
  143. passes of the compiler so they DO.  It isn't hard, and I will post
  144. instructions at a later date for doing it.  IF YOU DO THIS, PLEASE
  145. DON'T BOTHER OUR CUSTOMER SUPPORT PEOPLE IF IT DOESN'T WORK.  THEY
  146. DON'T KNOW ANYTHING ABOUT IT.
  147.  
  148. I hope that this little cookbook makes Pexec less mysterious.  I haven't
  149. covered such topics as the critical-error and terminate vectors, even though
  150. they are intimately connected with the idea of exec'ing children.  A more
  151. complete cookbook should be forthcoming.
  152.  
  153. If there are any errors or gross omissions in the above text, please
  154. let me know BY MAIL so I can correct them coherently.  Landon isn't
  155. here to check my semantics, so I may have missed something.  [Landon
  156. is on vacation in France until early September.]
  157.  
  158. ********************************************************************
  159.  
  160. C. Kaernbach's question was why his accessory, which basically did
  161. a Pexec from a file selector, didn't always work.  The answer is that
  162. it works when used within a program which has returned enough memory to
  163. the OS for the child.  Why might it bomb?  Because if a program has
  164. returned a *little* memory to the OS (only about 2K), a bug in Pexec
  165. shows up that breaks the memory manager.  Accessories are strange beasts
  166. anyway, so for the most part combining two strange beasts (Accessories
  167. and Pexec) is bad news.
  168.  
  169. /----------------------------------------------\
  170. | Opinions expressed above do not necessarily  |  -- Allan Pratt, Atari Corp.
  171. | reflect those of Atari Corp. or anyone else. |     ...lll-lcc!atari!apratt
  172. \----------------------------------------------/    (APRATT on GEnie)
  173.  
  174.