📄 process.c
字号:
/*****************************************************************************
* FILE: process.c *
* *
* DESC: *
* - process handling *
* - kernel stacks, schedule, process switch *
* - syscalls: fork(), spawnve(), wait(), exit() *
* - execute real mode programs *
* - shut down rsx *
* *
* Copyright (C) 1993,1994 *
* Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld *
* email: rainer@mathematik.uni-bielefeld.de *
* *
*****************************************************************************/
#include <string.h>
#include "PRINTF.H"
#include "DPMI.H"
#include "DPMI10.H"
#include "RMLIB.H"
#include "PROCESS.H"
#include "SIGNALS.H"
#include "START32.H"
#include "CDOSX32.H"
#include "ADOSX32.H"
#include "EXCEP32.H"
#include "COPY32.H"
#include "FS.H"
#include "RSX.H"
#include "LOADPRG.H"
#include "FPU.H"
#include "DOSERRNO.H"
#include "SYSDEP.H"
#include "DJIO.H"
#include "KDEB.H"
/* local functions */
static NEWPROCESS * find_empty_process(void);
static unsigned long alloc_kernel_stack(void);
static void free_kernel_stack(unsigned long);
static int switch_to_process(NEWPROCESS *);
static int mk_cmdline(char **, char *);
static void copy_filedescriptors(NEWPROCESS *, NEWPROCESS *);
static void set_go32_info_block(void);
/* globals */
NEWPROCESS process[N_PRZ + 1]; /* N_PRZ processes, 0 = extender/emu387 */
NEWPROCESS *npz; /* current running process */
unsigned int current_pid = 1;
/* locals */
static char stack_used[N_PRZ];
static unsigned long kstk[N_PRZ];
#define KERNEL_STACK 2048L
/*
* kernel stack:
*
* N_PRZ * KERNEL_STACK + init_stack <= RSX stack size
* 8 2KB 0xFFF 0xA000 - 0xFFFF = 0x6000
*/
static unsigned long alloc_kernel_stack(void)
{
static int inited;
int i;
/* swapper needs also stack */
DWORD stack = (stackp16 - 0x400) & ~0xFFL;
if (!inited) {
inited = 1;
for (i=0; i<N_PRZ; i++)
kstk[i] = (unsigned long) stack - i * KERNEL_STACK;
}
for (i=0; i<N_PRZ; i++)
if (!stack_used[i]) {
stack_used[i] = 1;
return kstk[i];
}
return 0;
}
static void free_kernel_stack(unsigned long address)
{
int i;
for (i=0; i<N_PRZ; i++)
if (address == kstk[i]) {
stack_used[i] = 0;
break;
}
}
#ifndef __GNUC__
void save_all(unsigned *stack);
void restore_all(unsigned *stack);
void new_stack_return(unsigned *stack);
#ifdef __WATCOMC__
#pragma aux ASM "_*" \
parm caller [] \
value struct float struct routine [ax];
#pragma aux (ASM) save_all;
#pragma aux (ASM) restore_all;
#pragma aux (ASM) new_stack_return;
#endif
#endif
/*
** switch to other process, save current kernel stack
*/
void switch_context(NEWPROCESS *p)
{
#ifdef __GNUC__
if (npz->p_status != PS_ZOMBIE) /* kernel stack needed */
__asm__("pusha ; pushl %0 ; movl %%esp, %0" : "=m" (npz->kstack));
switch_to_process(p);
if (npz->regs.eip == npz->entry) { /* not run before */
__asm__("movl %0, %%esp" : :"m" (npz->kstack));
back_from_syscall();
}
else
__asm__("movl %0, %%esp ; popl %0 ; popa ; nop " : :"m" (npz->kstack));
#else /* **not gnu** */
if (npz->p_status != PS_ZOMBIE) /* no kernel stack */
save_all((unsigned *)& npz->kstack);
switch_to_process(p);
if (npz->regs.eip == npz->entry) /* not run before */
new_stack_return((unsigned *)& npz->kstack);
else
restore_all((unsigned *)& npz->kstack);
#endif
}
/*
** small scheduler (called by from read/write)
*/
int schedule(void)
{
static NEWPROCESS *last = &FIRST_PROCESS;
NEWPROCESS *p;
int found = 0;
if (!opt_schedule)
return 0;
if (opt_printall) {
puts("schedule:");
for (p=&FIRST_PROCESS; p<=&LAST_PROCESS; p++)
if (p->pid>0)
printf("pid = %d status = %d stack %lX\n",
p->pid, p->p_status, p->kstack);
}
p = last;
do {
if (p->p_status == PS_RUN && p != npz) {
found = 1;
break;
}
if (++p > &LAST_PROCESS)
p = &FIRST_PROCESS;
} while (p != last);
if (found) {
last = p;
switch_context(p);
return 1;
} else {
if (opt_printall)
printf("schedule: no other process found\n");
return 0;
}
}
/*
** init processes
*/
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;
npz->kstack = stackp16;
init_rsx_filetab();
npz->filp[0] = & rsx_filetab[0];
npz->filp[1] = & rsx_filetab[1];
npz->filp[2] = & rsx_filetab[2];
}
/*
** 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;
}
/*
** check illegal arguments
*/
int verify_illegal(NEWPROCESS * p, DWORD where, DWORD lenght)
{
if (p->p_flags & PF_DJGPP_FILE) { /* 1.12 use first page ?!? */
if (where < 0x00A8L || where + lenght >= p->membytes)
return 1;
}
else { /* EMX */
if (where < 0x1000L || where + lenght >= p->membytes)
return 1;
}
return 0;
}
/*
** check illegal arguments (write access)
*/
int verify_illegal_write(NEWPROCESS * p, DWORD where, DWORD lenght)
{
DWORD end = where + lenght;
if (where >= p->data_start || end < p->data_end)
return 0;
if (where >= p->stack_down || end < p->stack_top)
return 0;
if (where >= p->init_brk || end < p->brk_value)
return 0;
return 1;
}
/*
** 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;
#ifdef CONFIG_KDEB
if (opt_kdeb && npz->pid == 2) {
if (RSX_PROCESS.p_flags & PF_WAIT_WAIT) {
*status = RSX_PROCESS.wait_return;
RSX_PROCESS.p_flags &= ~PF_WAIT_WAIT;
return 1;
}
}
#endif
do {
for (p = &LAST_PROCESS; p >= &FIRST_PROCESS; p--)
if (p->pptr == npz)
if (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;
}
if (pid < 0) {
npz->p_status = PS_WAIT; /* exclude from scheduler */
if (!schedule()) {
npz->p_status = PS_RUN; /* include if no others */
break;
}
}
} while (pid < 0);
return pid;
}
/*
** wait for pid
*/
int sys_waitpid(int pid, unsigned *status)
{
NEWPROCESS *p;
int ret = -1;
if (pid == -1)
return -1;
for (p = &LAST_PROCESS; p >= &FIRST_PROCESS; p--)
if ((int) p->pid == pid)
do {
if ((p->p_flags & PF_WAIT_WAIT)) {
*status = p->wait_return;
ret = p->pid;
p->p_flags &= ~PF_WAIT_WAIT;
if (p->p_status == PS_ZOMBIE)
clean_processtable(p);
break;
}
npz->p_status = PS_WAIT; /* exclude from scheduler */
if (!schedule()) {
npz->p_status = PS_RUN;
break;
}
} while (ret != -1);
return ret;
}
/*
** free process memory and selectors from DPMI-Server
** close open file handles
*/
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;
if (p->p_flags & PF_USEDPMI10)
rm_close((int) p->filehandle);
}
/*
** clean processtable
*/
void clean_processtable(NEWPROCESS * p)
{
memset(p, 0, sizeof(NEWPROCESS));
}
/*
** switch to next program, save mathe state, set npz
*/
static int switch_to_process(NEWPROCESS * nextp)
{
/* if math used, save 387 regs */
if (npz->p_flags & PF_MATH_USED) {
if (copro == 3)
save_emu_state(npz);
else if (copro == 1)
do_fnsave(&(npz->npx));
}
/* change process table */
npz = nextp;
cbrkcall = 0;
/* load 387 regs (init 387) */
if (copro == 3) {
if (npz->npx.soft.cwd) {
/* emulation done ? (check control word) */
npz->p_flags |= PF_MATH_USED;
load_emu_state(npz);
}
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(&(npz->npx));
npz->p_flags |= PF_MATH_USED;
}
else {
do_fninit();
}
}
return 0;
}
static int mk_cmdline(char **argv, char *cmd)
{
int i, j;
char *s;
if (!argv[0]) {
*cmd = 13;
return 0;
}
for (i = 0, j = 0; (s = argv[i]) != NULL; i++) {
while (*s)
cmd[j++] = *s++;
cmd[j++] = ' ';
}
cmd[--j] = 13;
return j;
}
/*
** build exec block for dos
*/
int execute_realmode_prg(char *filename, char **argv, char **env, int *ret_code)
{
struct execb eb;
char cmd_line[128];
int len;
/* build one string from arguments */
len = mk_cmdline(argv + 1, cmd_line + 2);
/* psp fields */
cmd_line[0] = (char) (len + 1);
cmd_line[1] = ' ';
/* fill exec block */
eb.psp_2c = ds16real + ((unsigned) env[0] >> 4);
eb.psp_80_seg = ds16real;
eb.psp_80_off = (UINT) cmd_line;
eb.fcb1_seg = eb.fcb1_off = 0;
eb.fcb2_seg = eb.fcb2_off = 0;
*ret_code = rm_exec(filename, &eb);
if (*ret_code == -1)
return -1;
*ret_code = rm_get_exit_status() & 0xFF;
return 0;
}
/*
** execute a real-mode program
*/
int realmode_prg(char *filename, char **argv, char **env)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -