home *** CD-ROM | disk | FTP | other *** search
/ Internet MPEG Audio Archive / IMAA.mdf / util / dos / l3v100n / rsx / source / process.c < prev    next >
C/C++ Source or Header  |  1994-01-19  |  13KB  |  510 lines

  1. /* This file is PROCESS.C
  2. **
  3. ** contains :
  4. **
  5. **    - process handling
  6. **
  7. ** Copyright (c) Rainer Schnitker '92 '93
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include "DPMI.H"
  15. #include "PROCESS.H"
  16. #include "SIGNALS.H"
  17. #include "START32.H"
  18. #include "CDOSX32.H"
  19. #include "ADOSX32.H"
  20. #include "EXCEP32.H"
  21. #include "COPY32.H"
  22. #include "RSX.H"
  23. #include "LOADPRG.H"
  24. #include "FPU.H"
  25.  
  26. /* Global Var */
  27. NEWPROCESS process[N_PRZ + 1];    /* 4 processes ; 0=extender/emu387 */
  28. NEWPROCESS *npz;        /* current running process */
  29. unsigned int current_pid = 1;
  30.  
  31. /*
  32. ** set signal for one process
  33. */
  34. int send_signal(NEWPROCESS * p, int signal)
  35. {
  36.     if (!p || signal < 0 || signal >= MAX_SIGNALS)
  37.     return EINVAL;
  38.     p->sig_raised |= 1L << signal;
  39.     return 0;
  40. }
  41.  
  42. /*
  43. ** find empty processtable
  44. */
  45. static NEWPROCESS *find_empty_process(void)
  46. {
  47.     NEWPROCESS *p;
  48.  
  49.     for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
  50.     if (p->p_status == PS_EMPTY)
  51.         return p;
  52.     return NULL;
  53. }
  54.  
  55. /*
  56. ** init processes called from extender 16bit prg
  57. */
  58. void init_this_process()
  59. {
  60.     NEWPROCESS *p;
  61.  
  62.     for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
  63.     p->p_status = PS_EMPTY;
  64.  
  65.     npz = &RSX_PROCESS;
  66.     npz->pid = current_pid++;
  67.     npz->p_status = PS_RUN;
  68.     npz->p_flags = PF_EXTENDER;
  69. }
  70.  
  71. /*
  72. ** check illegal arguments
  73. */
  74. int verify_illegal(NEWPROCESS * p, DWORD where, DWORD lenght)
  75. {
  76.     if (where < 0x1000L || where + lenght >= p->membytes)
  77.     return 1;
  78.     else
  79.     return 0;
  80. }
  81.  
  82. /*
  83. ** find processtable
  84. */
  85. NEWPROCESS *find_process(unsigned pid)
  86. {
  87.     NEWPROCESS *p;
  88.  
  89.     for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
  90.     if (p->pid == pid)
  91.         return p;
  92.     return (NEWPROCESS *) 0;
  93. }
  94.  
  95. /*
  96. ** get wait_status
  97. */
  98. unsigned sys_wait(unsigned *status)
  99. {
  100.     NEWPROCESS *p;
  101.     int pid = -1;
  102.  
  103.     for (p = &LAST_PROCESS; p >= &FIRST_PROCESS; p--)
  104.     if (p->pptr == npz && (p->p_flags & PF_WAIT_WAIT)) {
  105.         *status = p->wait_return;
  106.         pid = p->pid;
  107.         p->p_flags &= ~PF_WAIT_WAIT;
  108.         if (p->p_status == PS_ZOMBIE)
  109.         clean_processtable(p);
  110.         break;
  111.     }
  112.     return pid;
  113. }
  114.  
  115. /*
  116. ** free process memory and selectors from DPMI-Server
  117. */
  118. void free_process(NEWPROCESS * p)
  119. {
  120.     if (p->code32sel == 0)    /* already cleaned ? */
  121.     return;
  122.     FreeMem(p->memhandle);
  123.     FreeLDT(p->code32sel);
  124.     FreeLDT(p->data32sel);
  125.     FreeLDT(p->data32sel + sel_incr);
  126.     p->code32sel = 0;
  127. }
  128.  
  129. /*
  130. ** clean processtable
  131. */
  132. void clean_processtable(NEWPROCESS * p)
  133. {
  134.     memset(p, 0, sizeof(NEWPROCESS));
  135. }
  136.  
  137. /*
  138. ** switch to next program, save mathe state, set npz
  139. */
  140. int switch_to_process(NEWPROCESS * nextp)
  141. {
  142.     /* if math used, save 387 regs */
  143.     if (npz->p_flags & PF_MATH_USED) {
  144.     if (copro == 3)
  145.         cpy32_16(emu_sel, copro_struct, &(npz->npx),
  146.              (DWORD) sizeof(union i387_union));
  147.     else if (copro == 1)
  148.         do_fnsave((unsigned) &(npz->npx));
  149.     }
  150.     /* change process table */
  151.     npz = nextp;
  152.     cbrkcall = 0;
  153.  
  154.     /* load 387 regs (init 387) */
  155.     if (copro == 3) {
  156.     if (npz->npx.soft.cwd)    /* emulation done ? */
  157.         npz->p_flags |= PF_MATH_USED;
  158.     cpy16_32(emu_sel, copro_struct, &(npz->npx),
  159.          (DWORD) sizeof(union i387_union));
  160.  
  161.     if (npz->p_flags & PF_MATH_USED)
  162.         emu_switch(MATH_USED, npz->p_flags & PF_DEBUG);
  163.     else
  164.         emu_switch(MATH_NEW, npz->p_flags & PF_DEBUG);
  165.     } else if (copro == 1)
  166.     if (npz->p_flags & PF_MATH_USED)
  167.         do_frstor((unsigned) &(npz->npx));
  168.     else {
  169.         do_fninit();
  170.         npz->p_flags |= PF_MATH_USED;
  171.     }
  172.  
  173.     return 0;
  174. }
  175.  
  176. /* real mode spawn prototype */
  177. int spawnvpe(int mode, char *name, char **argv, char **env);
  178.  
  179. /*
  180. ** call a real mode program, must be far!
  181. */
  182. static int far do_spawnve(char *name, char **argp, char **envp)
  183. {
  184.     return spawnvpe(P_WAIT, name, argp, envp);
  185. }
  186.  
  187. /*
  188. ** execute a real-mode program
  189. */
  190. int realmode_prg(char *filename, char **argv, char **env)
  191. {
  192.     int stack;
  193.  
  194.     tr.ds = tr.es = tr.ss = tr.fs = tr.gs = ds16real;
  195.     tr.cs = cs16real;
  196.     tr.flags = FLAGS;
  197.     tr.ip = (WORD) (DWORD) do_spawnve;
  198.     tr.reserved = 0;
  199.     tr.sp = (WORD) & stack - 40;
  200.  
  201.     CallRMprocFar(0, 3, &tr, filename, argv, env);
  202.  
  203.     if ((int) tr.eax == -1)    /* error real mode prg */
  204.     return errno;
  205.     else {
  206.     EAX = tr.eax & 0xff;    /* return value */
  207.     current_pid++;
  208.     return 0;
  209.     }
  210. }
  211.  
  212. /*
  213. ** load, init and switch to another 32bit program
  214. */
  215. int exec32(unsigned mode, char *name, int argc, char **argp, int envc, char **envp)
  216. {
  217.     NEWPROCESS *child;
  218.     int ret;
  219.  
  220.     /* if no wait, free last process */
  221.     sys_wait(&ret);
  222.  
  223.     /* look for a empty slot */
  224.     child = find_empty_process();
  225.     if (child == NULL)
  226.     return EAGAIN;
  227.  
  228.     /* try load a a.out program */
  229.     if ((ret = load_protected_program(name, child)) != 0)
  230.     return ret;
  231.  
  232.     /* copy arguments,environment */
  233.     argvenv(argc, argp, envc, envp, child);
  234.  
  235.     /* setup new process table */
  236.     child->pid = current_pid++;
  237.     child->pptr = npz;
  238.     if (mode == P_DEBUG)
  239.     child->p_flags |= PF_DEBUG;
  240.     /* start values */
  241.     child->regs.eip = child->entry;
  242.     child->regs.esporg = child->stackp32;
  243.     child->regs.esp = child->stackp32 - 12L;    /* iret frame */
  244.     child->regs.eax = (DWORD) dosmem_sel << 16;    /* for DJGPP: first MB */
  245.     child->regs.ebx = 0;
  246.     child->regs.ecx = 0;
  247.     child->regs.edx = 0;
  248.     child->regs.esi = 0;
  249.     child->regs.edi = 0;
  250.     child->regs.ebp = 0;
  251.     child->regs.cs = child->code32sel;
  252.     child->regs.ds = child->data32sel;
  253.     child->regs.es = child->data32sel;
  254.     child->regs.ss = child->data32sel + sel_incr;
  255.     child->regs.fs = child->data32sel;
  256.     child->regs.gs = dosmem_sel;
  257.     child->regs.eflags = 0x3202;
  258.     child->time_tic = time_tic;
  259.  
  260.     /* if stack-down-segment lacks ebp, make ss = ds */
  261.     if (opt_stack)
  262.         child->regs.ss -= sel_incr;
  263.  
  264.     npz->cptr = child;
  265.  
  266.     /* if current prg extender, switch to first emx-porgram */
  267.     if (npz->p_flags & PF_EXTENDER) {
  268.     switch_to_process(child);
  269.     npz->p_status = PS_RUN;
  270.     back_from_syscall();
  271.     }
  272.     /* else change running prz or wait for debug */
  273.  
  274.     if (mode == P_WAIT || mode == P_NOWAIT) {
  275.     MarkPageDemand(npz->memaddress, npz->membytes);
  276.     npz->p_status = PS_SYS_SPAWN;
  277.     switch_to_process(child);
  278.     npz->p_status = PS_RUN;
  279.     if (mode == P_NOWAIT)
  280.         npz->p_flags |= PF_SPAWN_ASYNC;
  281.     } else if (mode == P_DEBUG) {
  282.     EAX = child->pid;    /* return process no */
  283.     child->p_status = PS_STOP;
  284.     } else if (mode == P_OVERLAY) {
  285.     NEWPROCESS *this = npz;
  286.     npz->p_flags &= ~PF_MATH_USED;    /* don't save mathe state */
  287.     switch_to_process(npz->pptr);    /* switch to parent */
  288.     free_process(this);    /* free process memory */
  289.     clean_processtable(this);    /* free process table */
  290.     npz->cptr = child;    /* new child */
  291.     child->pptr = npz;    /* new parent */
  292.     switch_to_process(child);    /* switch to new child */
  293.     npz->p_status = PS_RUN;
  294.     } else
  295.     return EINVAL;
  296.  
  297.     return 0;
  298. }
  299.  
  300. /*
  301. ** fork current process
  302. */
  303. int sys_fork(void)
  304. {
  305.     NEWPROCESS *child;
  306.     WORD child_stack32sel;
  307.  
  308.     child = find_empty_process();
  309.     if (child == NULL)
  310.     return EAGAIN;
  311.  
  312.     memcpy(child, npz, sizeof(NEWPROCESS));
  313.     child->p_status = PS_EMPTY;    /* if error, leave empty */
  314.  
  315.     /* MEMORY per DPMI besorgen */
  316.     if (AllocMem(npz->membytes, &(child->memhandle), &(child->memaddress)))
  317.     return ENOMEM;
  318.     if (AllocLDT(3, &(child->code32sel)))
  319.     return EIO;
  320.     child->data32sel = child->code32sel + sel_incr;
  321.     child_stack32sel = child->data32sel + sel_incr;
  322.  
  323.     SetBaseAddress(child->code32sel, child->memaddress);
  324.     SetBaseAddress(child->data32sel, child->memaddress);
  325.     SetBaseAddress(child_stack32sel, child->memaddress);
  326.     SetAccess(child->code32sel, APP_CODE_SEL, DEFAULT_BIT | GRANULAR_BIT);
  327.     SetAccess(child->data32sel, APP_DATA_SEL, DEFAULT_BIT | GRANULAR_BIT);
  328.     SetAccess(child_stack32sel, APP_DATA_SEL | EXPAND_BIT, BIG_BIT | GRANULAR_BIT);
  329.     SetLimit(child->code32sel, lsl32(npz->code32sel));
  330.     SetLimit(child->data32sel, lsl32(npz->data32sel));
  331.     SetLimit(child_stack32sel, lsl32(npz->data32sel + sel_incr));
  332.  
  333.     child->regs.cs = child->code32sel;
  334.     child->regs.ds = child->data32sel;
  335.     child->regs.es = child->data32sel;
  336.     child->regs.ss = child_stack32sel;
  337.     child->regs.fs = child->data32sel;
  338.     child->regs.gs = dosmem_sel;/* first Megabyte DOS */
  339.     child->pid = current_pid++;
  340.     child->pptr = npz;
  341.     child->cptr = NULL;
  342.     child->p_status = PS_STOP;
  343.     child->time_alarm = 0;
  344.     child->time_tic = time_tic;
  345.     npz->cptr = child;
  346.  
  347.     /* cpy32_32(npz->data32sel, 0, child->data32sel, 0, npz->membytes); */
  348.  
  349.     /* text segment */
  350.     cpy32_32(npz->data32sel, npz->text_start,
  351.          child->data32sel, child->text_start,
  352.          npz->text_end - npz->text_start);
  353.  
  354.     /* data/bss segment */
  355.     cpy32_32(npz->data32sel, npz->data_start,
  356.          child->data32sel, child->data_start,
  357.          npz->data_end - npz->data_start);
  358.  
  359.     /* heap segment */
  360.     cpy32_32(npz->data32sel, npz->init_brk,
  361.          child->data32sel, child->init_brk,
  362.          npz->brk_value - npz->init_brk);
  363.  
  364.     /* stack segment */
  365.     cpy32_32(npz->data32sel, ESP,
  366.          child->data32sel, ESP,
  367.          npz->stack_top - ESP);
  368.  
  369.     MarkPageDemand(npz->memaddress, npz->membytes);
  370.     return 0;
  371. }
  372.  
  373. /*
  374. ** global clean-up for extender
  375. */
  376. void shut_down(int exit_code)
  377. {
  378.     NEWPROCESS *p;
  379.  
  380.     /* free memory,selectors */
  381.     for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
  382.     free_process(p);
  383.  
  384.     /* clean_up ints,exceptions,... */
  385.     clean_up();
  386.  
  387.     /* leave protected mode */
  388.     protected_to_real(exit_code);
  389. }
  390.  
  391. /*
  392. ** get more memory from DPMI-Server
  393. */
  394. DWORD getmem(DWORD bytes, NEWPROCESS * p)
  395. {                /* ret: old break value */
  396.     DWORD retv, pagealign;
  397.     DWORD newaddress, newhandle;
  398.  
  399.     if (bytes <= p->pagefree) {
  400.     retv = p->brk_value;
  401.     p->brk_value += bytes;
  402.     p->pagefree -= bytes;
  403.     } else {
  404.     pagealign = (bytes + 0xFFF) & 0xFFFFF000L;
  405.     if (ResizeMem(p->membytes + pagealign, p->memhandle,
  406.               &newhandle, &newaddress))
  407.         return -1L;
  408.     p->membytes += pagealign;
  409.     retv = p->brk_value;
  410.     p->brk_value += bytes;
  411.     p->pagefree = pagealign - bytes;
  412.     if (!opt_memaccess)
  413.         SetLimit(p->data32sel, p->membytes - 1);
  414.     if (p->memhandle != newhandle) {
  415.         p->memhandle = newhandle;
  416.     }
  417.     if (p->memaddress != newaddress) {
  418.         p->memaddress = newaddress;
  419.         SetBaseAddress(p->code32sel, p->memaddress);
  420.         SetBaseAddress(p->data32sel, p->memaddress);
  421.         SetBaseAddress(p->data32sel + sel_incr, p->memaddress);
  422.     }
  423.  
  424.     /* dammed! djgpp (gcc.exe) cause gp-fault, if not */
  425.     /* if (p->p_flags & PF_DJGPP_FILE) */
  426.     bzero32(p->data32sel, retv, pagealign);
  427.     }
  428.     return retv;
  429. }
  430.  
  431. char *sigtext[] =
  432. {
  433.     NULL,
  434.     "SIGHUP",
  435.     "SIGINT",
  436.     "SIGQUIT",
  437.     "SIGILL",
  438.     "SIGTRAP",
  439.     "SIGABRT",
  440.     "SIGEMT",
  441.     "SIGFPE",
  442.     "SIGKILL",
  443.     "SIGBUS",
  444.     "SIGSEGV",
  445.     "SIGSYS",
  446.     "SIGPIPE",
  447.     "SIGALRM",
  448.     "SIGTERM",
  449.     "16"
  450.     "17"
  451.     "SIGCLD",
  452.     "19"
  453.     "20"
  454.     "SIGBREAK"};
  455.  
  456. /*
  457. ** exit child and switch to father
  458. */
  459. int do_exit4c(int bysig)
  460. {
  461.     NEWPROCESS *father;
  462.     WORD ret;
  463.  
  464.     /* get parent */
  465.     father = npz->pptr;
  466.  
  467.     if (bysig)
  468.     printf("\nProgram terminate by signal %d , %s\n"
  469.            ,bysig, sigtext[bysig]);
  470.  
  471.     /* if father process is Extender */
  472.     if (father->p_flags & PF_EXTENDER)
  473.     shut_down(AX);
  474.  
  475.     if (bysig) {
  476.     ret = 3;        /* return spawn */
  477.     npz->wait_return = bysig;    /* wait: term by sig */
  478.     } else {            /* process terminate */
  479.     if ((npz->p_flags & PF_DEBUG) || (npz->p_flags & PF_SPAWN_ASYNC))
  480.         ret = npz->pid;
  481.     else
  482.         ret = AX & 0xff;
  483.     npz->wait_return = (AX & 0xFF) << 8;
  484.     }
  485.  
  486.     npz->p_status = PS_ZOMBIE;
  487.     npz->p_flags |= PF_WAIT_WAIT;    /* allow wait() for father */
  488.     npz->p_flags &= ~PF_MATH_USED;    /* don't save mathe state */
  489.  
  490.     free_process(npz);
  491.     switch_to_process(father);
  492.  
  493.     if (npz->p_flags & PF_DJGPP_FILE)
  494.     if (npz->p_flags & PF_COMPRESS)
  495.         (void)uncompress_memory();
  496.  
  497.     if (npz->p_status == PS_SYS_SPAWN) {
  498.     EFLAGS &= ~1L;        /* clear carry, spawn,exec ok */
  499.     EAX = (DWORD) ret;    /* return value to caller */
  500.     } else if (npz->p_status == PS_SYS_PTRACE) {
  501.     EAX = ECX = 0;
  502.     } else if (npz->p_status == PS_SYS_KILL) {
  503.     EAX = ECX = 0;
  504.     }
  505.     npz->p_status = PS_RUN;
  506.  
  507.     send_signal(npz, SIGCLD);
  508.     return CARRY_OFF;
  509. }
  510.