home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet MPEG Audio Archive
/
IMAA.mdf
/
util
/
dos
/
l3v100n
/
rsx
/
source
/
process.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-19
|
13KB
|
510 lines
/* This file is PROCESS.C
**
** contains :
**
** - process handling
**
** Copyright (c) Rainer Schnitker '92 '93
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "DPMI.H"
#include "PROCESS.H"
#include "SIGNALS.H"
#include "START32.H"
#include "CDOSX32.H"
#include "ADOSX32.H"
#include "EXCEP32.H"
#include "COPY32.H"
#include "RSX.H"
#include "LOADPRG.H"
#include "FPU.H"
/* Global Var */
NEWPROCESS process[N_PRZ + 1]; /* 4 processes ; 0=extender/emu387 */
NEWPROCESS *npz; /* current running process */
unsigned int current_pid = 1;
/*
** set signal for one process
*/
int send_signal(NEWPROCESS * p, int signal)
{
if (!p || signal < 0 || signal >= MAX_SIGNALS)
return EINVAL;
p->sig_raised |= 1L << signal;
return 0;
}
/*
** find empty processtable
*/
static NEWPROCESS *find_empty_process(void)
{
NEWPROCESS *p;
for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
if (p->p_status == PS_EMPTY)
return p;
return NULL;
}
/*
** init processes called from extender 16bit prg
*/
void init_this_process()
{
NEWPROCESS *p;
for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
p->p_status = PS_EMPTY;
npz = &RSX_PROCESS;
npz->pid = current_pid++;
npz->p_status = PS_RUN;
npz->p_flags = PF_EXTENDER;
}
/*
** check illegal arguments
*/
int verify_illegal(NEWPROCESS * p, DWORD where, DWORD lenght)
{
if (where < 0x1000L || where + lenght >= p->membytes)
return 1;
else
return 0;
}
/*
** find processtable
*/
NEWPROCESS *find_process(unsigned pid)
{
NEWPROCESS *p;
for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
if (p->pid == pid)
return p;
return (NEWPROCESS *) 0;
}
/*
** get wait_status
*/
unsigned sys_wait(unsigned *status)
{
NEWPROCESS *p;
int pid = -1;
for (p = &LAST_PROCESS; p >= &FIRST_PROCESS; p--)
if (p->pptr == npz && (p->p_flags & PF_WAIT_WAIT)) {
*status = p->wait_return;
pid = p->pid;
p->p_flags &= ~PF_WAIT_WAIT;
if (p->p_status == PS_ZOMBIE)
clean_processtable(p);
break;
}
return pid;
}
/*
** free process memory and selectors from DPMI-Server
*/
void free_process(NEWPROCESS * p)
{
if (p->code32sel == 0) /* already cleaned ? */
return;
FreeMem(p->memhandle);
FreeLDT(p->code32sel);
FreeLDT(p->data32sel);
FreeLDT(p->data32sel + sel_incr);
p->code32sel = 0;
}
/*
** clean processtable
*/
void clean_processtable(NEWPROCESS * p)
{
memset(p, 0, sizeof(NEWPROCESS));
}
/*
** switch to next program, save mathe state, set npz
*/
int switch_to_process(NEWPROCESS * nextp)
{
/* if math used, save 387 regs */
if (npz->p_flags & PF_MATH_USED) {
if (copro == 3)
cpy32_16(emu_sel, copro_struct, &(npz->npx),
(DWORD) sizeof(union i387_union));
else if (copro == 1)
do_fnsave((unsigned) &(npz->npx));
}
/* change process table */
npz = nextp;
cbrkcall = 0;
/* load 387 regs (init 387) */
if (copro == 3) {
if (npz->npx.soft.cwd) /* emulation done ? */
npz->p_flags |= PF_MATH_USED;
cpy16_32(emu_sel, copro_struct, &(npz->npx),
(DWORD) sizeof(union i387_union));
if (npz->p_flags & PF_MATH_USED)
emu_switch(MATH_USED, npz->p_flags & PF_DEBUG);
else
emu_switch(MATH_NEW, npz->p_flags & PF_DEBUG);
} else if (copro == 1)
if (npz->p_flags & PF_MATH_USED)
do_frstor((unsigned) &(npz->npx));
else {
do_fninit();
npz->p_flags |= PF_MATH_USED;
}
return 0;
}
/* real mode spawn prototype */
int spawnvpe(int mode, char *name, char **argv, char **env);
/*
** call a real mode program, must be far!
*/
static int far do_spawnve(char *name, char **argp, char **envp)
{
return spawnvpe(P_WAIT, name, argp, envp);
}
/*
** execute a real-mode program
*/
int realmode_prg(char *filename, char **argv, char **env)
{
int stack;
tr.ds = tr.es = tr.ss = tr.fs = tr.gs = ds16real;
tr.cs = cs16real;
tr.flags = FLAGS;
tr.ip = (WORD) (DWORD) do_spawnve;
tr.reserved = 0;
tr.sp = (WORD) & stack - 40;
CallRMprocFar(0, 3, &tr, filename, argv, env);
if ((int) tr.eax == -1) /* error real mode prg */
return errno;
else {
EAX = tr.eax & 0xff; /* return value */
current_pid++;
return 0;
}
}
/*
** load, init and switch to another 32bit program
*/
int exec32(unsigned mode, char *name, int argc, char **argp, int envc, char **envp)
{
NEWPROCESS *child;
int ret;
/* if no wait, free last process */
sys_wait(&ret);
/* look for a empty slot */
child = find_empty_process();
if (child == NULL)
return EAGAIN;
/* try load a a.out program */
if ((ret = load_protected_program(name, child)) != 0)
return ret;
/* copy arguments,environment */
argvenv(argc, argp, envc, envp, child);
/* setup new process table */
child->pid = current_pid++;
child->pptr = npz;
if (mode == P_DEBUG)
child->p_flags |= PF_DEBUG;
/* start values */
child->regs.eip = child->entry;
child->regs.esporg = child->stackp32;
child->regs.esp = child->stackp32 - 12L; /* iret frame */
child->regs.eax = (DWORD) dosmem_sel << 16; /* for DJGPP: first MB */
child->regs.ebx = 0;
child->regs.ecx = 0;
child->regs.edx = 0;
child->regs.esi = 0;
child->regs.edi = 0;
child->regs.ebp = 0;
child->regs.cs = child->code32sel;
child->regs.ds = child->data32sel;
child->regs.es = child->data32sel;
child->regs.ss = child->data32sel + sel_incr;
child->regs.fs = child->data32sel;
child->regs.gs = dosmem_sel;
child->regs.eflags = 0x3202;
child->time_tic = time_tic;
/* if stack-down-segment lacks ebp, make ss = ds */
if (opt_stack)
child->regs.ss -= sel_incr;
npz->cptr = child;
/* if current prg extender, switch to first emx-porgram */
if (npz->p_flags & PF_EXTENDER) {
switch_to_process(child);
npz->p_status = PS_RUN;
back_from_syscall();
}
/* else change running prz or wait for debug */
if (mode == P_WAIT || mode == P_NOWAIT) {
MarkPageDemand(npz->memaddress, npz->membytes);
npz->p_status = PS_SYS_SPAWN;
switch_to_process(child);
npz->p_status = PS_RUN;
if (mode == P_NOWAIT)
npz->p_flags |= PF_SPAWN_ASYNC;
} else if (mode == P_DEBUG) {
EAX = child->pid; /* return process no */
child->p_status = PS_STOP;
} else if (mode == P_OVERLAY) {
NEWPROCESS *this = npz;
npz->p_flags &= ~PF_MATH_USED; /* don't save mathe state */
switch_to_process(npz->pptr); /* switch to parent */
free_process(this); /* free process memory */
clean_processtable(this); /* free process table */
npz->cptr = child; /* new child */
child->pptr = npz; /* new parent */
switch_to_process(child); /* switch to new child */
npz->p_status = PS_RUN;
} else
return EINVAL;
return 0;
}
/*
** fork current process
*/
int sys_fork(void)
{
NEWPROCESS *child;
WORD child_stack32sel;
child = find_empty_process();
if (child == NULL)
return EAGAIN;
memcpy(child, npz, sizeof(NEWPROCESS));
child->p_status = PS_EMPTY; /* if error, leave empty */
/* MEMORY per DPMI besorgen */
if (AllocMem(npz->membytes, &(child->memhandle), &(child->memaddress)))
return ENOMEM;
if (AllocLDT(3, &(child->code32sel)))
return EIO;
child->data32sel = child->code32sel + sel_incr;
child_stack32sel = child->data32sel + sel_incr;
SetBaseAddress(child->code32sel, child->memaddress);
SetBaseAddress(child->data32sel, child->memaddress);
SetBaseAddress(child_stack32sel, child->memaddress);
SetAccess(child->code32sel, APP_CODE_SEL, DEFAULT_BIT | GRANULAR_BIT);
SetAccess(child->data32sel, APP_DATA_SEL, DEFAULT_BIT | GRANULAR_BIT);
SetAccess(child_stack32sel, APP_DATA_SEL | EXPAND_BIT, BIG_BIT | GRANULAR_BIT);
SetLimit(child->code32sel, lsl32(npz->code32sel));
SetLimit(child->data32sel, lsl32(npz->data32sel));
SetLimit(child_stack32sel, lsl32(npz->data32sel + sel_incr));
child->regs.cs = child->code32sel;
child->regs.ds = child->data32sel;
child->regs.es = child->data32sel;
child->regs.ss = child_stack32sel;
child->regs.fs = child->data32sel;
child->regs.gs = dosmem_sel;/* first Megabyte DOS */
child->pid = current_pid++;
child->pptr = npz;
child->cptr = NULL;
child->p_status = PS_STOP;
child->time_alarm = 0;
child->time_tic = time_tic;
npz->cptr = child;
/* cpy32_32(npz->data32sel, 0, child->data32sel, 0, npz->membytes); */
/* text segment */
cpy32_32(npz->data32sel, npz->text_start,
child->data32sel, child->text_start,
npz->text_end - npz->text_start);
/* data/bss segment */
cpy32_32(npz->data32sel, npz->data_start,
child->data32sel, child->data_start,
npz->data_end - npz->data_start);
/* heap segment */
cpy32_32(npz->data32sel, npz->init_brk,
child->data32sel, child->init_brk,
npz->brk_value - npz->init_brk);
/* stack segment */
cpy32_32(npz->data32sel, ESP,
child->data32sel, ESP,
npz->stack_top - ESP);
MarkPageDemand(npz->memaddress, npz->membytes);
return 0;
}
/*
** global clean-up for extender
*/
void shut_down(int exit_code)
{
NEWPROCESS *p;
/* free memory,selectors */
for (p = &FIRST_PROCESS; p <= &LAST_PROCESS; p++)
free_process(p);
/* clean_up ints,exceptions,... */
clean_up();
/* leave protected mode */
protected_to_real(exit_code);
}
/*
** get more memory from DPMI-Server
*/
DWORD getmem(DWORD bytes, NEWPROCESS * p)
{ /* ret: old break value */
DWORD retv, pagealign;
DWORD newaddress, newhandle;
if (bytes <= p->pagefree) {
retv = p->brk_value;
p->brk_value += bytes;
p->pagefree -= bytes;
} else {
pagealign = (bytes + 0xFFF) & 0xFFFFF000L;
if (ResizeMem(p->membytes + pagealign, p->memhandle,
&newhandle, &newaddress))
return -1L;
p->membytes += pagealign;
retv = p->brk_value;
p->brk_value += bytes;
p->pagefree = pagealign - bytes;
if (!opt_memaccess)
SetLimit(p->data32sel, p->membytes - 1);
if (p->memhandle != newhandle) {
p->memhandle = newhandle;
}
if (p->memaddress != newaddress) {
p->memaddress = newaddress;
SetBaseAddress(p->code32sel, p->memaddress);
SetBaseAddress(p->data32sel, p->memaddress);
SetBaseAddress(p->data32sel + sel_incr, p->memaddress);
}
/* dammed! djgpp (gcc.exe) cause gp-fault, if not */
/* if (p->p_flags & PF_DJGPP_FILE) */
bzero32(p->data32sel, retv, pagealign);
}
return retv;
}
char *sigtext[] =
{
NULL,
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGABRT",
"SIGEMT",
"SIGFPE",
"SIGKILL",
"SIGBUS",
"SIGSEGV",
"SIGSYS",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"16"
"17"
"SIGCLD",
"19"
"20"
"SIGBREAK"};
/*
** exit child and switch to father
*/
int do_exit4c(int bysig)
{
NEWPROCESS *father;
WORD ret;
/* get parent */
father = npz->pptr;
if (bysig)
printf("\nProgram terminate by signal %d , %s\n"
,bysig, sigtext[bysig]);
/* if father process is Extender */
if (father->p_flags & PF_EXTENDER)
shut_down(AX);
if (bysig) {
ret = 3; /* return spawn */
npz->wait_return = bysig; /* wait: term by sig */
} else { /* process terminate */
if ((npz->p_flags & PF_DEBUG) || (npz->p_flags & PF_SPAWN_ASYNC))
ret = npz->pid;
else
ret = AX & 0xff;
npz->wait_return = (AX & 0xFF) << 8;
}
npz->p_status = PS_ZOMBIE;
npz->p_flags |= PF_WAIT_WAIT; /* allow wait() for father */
npz->p_flags &= ~PF_MATH_USED; /* don't save mathe state */
free_process(npz);
switch_to_process(father);
if (npz->p_flags & PF_DJGPP_FILE)
if (npz->p_flags & PF_COMPRESS)
(void)uncompress_memory();
if (npz->p_status == PS_SYS_SPAWN) {
EFLAGS &= ~1L; /* clear carry, spawn,exec ok */
EAX = (DWORD) ret; /* return value to caller */
} else if (npz->p_status == PS_SYS_PTRACE) {
EAX = ECX = 0;
} else if (npz->p_status == PS_SYS_KILL) {
EAX = ECX = 0;
}
npz->p_status = PS_RUN;
send_signal(npz, SIGCLD);
return CARRY_OFF;
}