⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 大量的汇编程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 * 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 + -