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

📄 syscall.c

📁 体系机构仿真
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * syscall.c - proxy system call handler routines * * This file is an adaptation of the software in the SimpleScalar tool suite * originally written by Todd M. Austin for the Multiscalar Research Project * at the University of Wisconsin-Madison. * * The modifications were made by Naraig Manjikian at Queen's University, * Kingston, Ontario, Canada. * * The remainder of this header comment is unchanged from the original text. * *.......................................................................... *  * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin * * This source file is distributed "as is" in the hope that it will be * useful.  The tool set comes with no warranty, and no author or * distributor accepts any responsibility for the consequences of its * use.  *  * Everyone is granted permission to copy, modify and redistribute * this tool set under the following conditions: *  *    This source code is distributed for non-commercial use only.  *    Please contact the maintainer for restrictions applying to  *    commercial use. * *    Permission is granted to anyone to make or distribute copies *    of this source code, either as received or modified, in any *    medium, provided that all copyright notices, permission and *    nonwarranty notices are preserved, and that the distributor *    grants the recipient permission for further redistribution as *    permitted by this document. * *    Permission is granted to distribute this file in compiled *    or executable form under the same conditions that apply for *    source code, provided that either: * *    A. it is accompanied by the corresponding machine-readable *       source code, *    B. it is accompanied by a written offer, with no time limit, *       to give anyone a machine-readable copy of the corresponding *       source code in return for reimbursement of the cost of *       distribution.  This written offer must permit verbatim *       duplication by anyone, or *    C. it is distributed by someone who received only the *       executable form, and is accompanied by a copy of the *       written offer of source code that they received concurrently. * * In other words, you are welcome to use, share and improve this * source file.  You are forbidden to forbid anyone else to use, share * and improve what you give them. * * INTERNET: dburger@cs.wisc.edu * US Mail:  1210 W. Dayton Street, Madison, WI 53706 * * $Id: syscall.c,v 1.5 1997/04/16 22:12:17 taustin Exp taustin $ * * $Log: syscall.c,v $ * Revision 1.5  1997/04/16  22:12:17  taustin * added Ultrix host support * * Revision 1.4  1997/03/11  01:37:37  taustin * updated copyright * long/int tweaks made for ALPHA target support * syscall structures are now more portable across platforms * various target supports added * * Revision 1.3  1996/12/27  15:56:09  taustin * updated comments * removed system prototypes * * Revision 1.1  1996/12/05  18:52:32  taustin * Initial revision * * */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/param.h>#include <errno.h>#include <time.h>#include <sys/time.h>#include <sys/resource.h>#include <signal.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/uio.h>#include <setjmp.h>#include <sys/times.h>#include <limits.h>#include <sys/ioctl.h>#if !defined(linux) && !defined(sparc) && !defined(hpux) && !defined(__hpux) && !defined(__CYGWIN32__) && !defined(ultrix)#include <sys/select.h>#endif#ifdef linux#include <bsd/sgtty.h>#endif /* linux */#ifdef __CYGWIN32__#include <sgtty.h>#endif /* __CYGWIN32__ */#if defined(sparc) && defined(__unix__)#if defined(__svr4__) || defined(__USLC__)#include <dirent.h>#else#include <sys/dir.h>#endif/* dorks */#undef NL0#undef NL1#undef CR0#undef CR1#undef CR2#undef CR3#undef TAB0#undef TAB1#undef TAB2#undef XTABS#undef BS0#undef BS1#undef FF0#undef FF1#undef ECHO#undef NOFLSH#undef TOSTOP#undef FLUSHO#undef PENDIN#endif#if defined(hpux) || defined(__hpux)#undef CR0#endif#ifdef __FreeBSD__#include <sys/ioctl_compat.h>#else#include <termio.h>#endif#if defined(hpux) || defined(__hpux)/* et tu, dorks! */#undef HUPCL#undef ECHO#undef B50#undef B75#undef B110#undef B134#undef B150#undef B200#undef B300#undef B600#undef B1200#undef B1800#undef B2400#undef B4800#undef B9600#undef B19200#undef B38400#undef NL0#undef NL1#undef CR0#undef CR1#undef CR2#undef CR3#undef TAB0#undef TAB1#undef BS0#undef BS1#undef FF0#undef FF1#undef EXTA#undef EXTB#undef B900#undef B3600#undef B7200#undef XTABS#include <sgtty.h>#include <utime.h>#endif#include "misc.h"#include "ss.h"#include "regs.h"#include "memory.h"#include "loader.h"#include "sim.h"#include "endian.h"#include "syscall.h"/* open(2) flags translation table for SimpleScalar target */struct {  int ss_flag;  int local_flag;} ss_flag_table[] = {  /* target flag */	/* host flag */  { SS_O_RDONLY,	O_RDONLY },  { SS_O_WRONLY,	O_WRONLY },  { SS_O_RDWR,		O_RDWR },  { SS_O_APPEND,	O_APPEND },  { SS_O_CREAT,		O_CREAT },  { SS_O_TRUNC,		O_TRUNC },  { SS_O_EXCL,		O_EXCL },  { SS_O_NONBLOCK,	O_NONBLOCK },  { SS_O_NOCTTY,	O_NOCTTY },#ifdef O_SYNC  { SS_O_SYNC,		O_SYNC },#endif};#define SS_NFLAGS	(sizeof(ss_flag_table)/sizeof(ss_flag_table[0]))/*--------------------------------------------------------------------*//* the following are additions to support multiprocessing */typedef	struct	_synchqnode{	struct	_synchqnode	*next;	int	pid;	enum	{FREE,		 WAITING_FOR_LOCK,		 HOLDING_LOCK,		 BLOCKED_ON_BARRIER,		 BLOCKED_ON_SEMAPHORE} synch_state;	int	synch_var;	/* which synch var for above state */} SynchQNode;/* amount by which to increase array sizes for synchronization variables */#define LOCK_INCREMENT		1024#define BARRIER_INCREMENT	64#define SEMAPHORE_INCREMENT	64/* a (reasonable?) upper bound on number of synch vars of each type */#define SANITY_LIMIT		65535/* each processor has a node that may appear in exactly _one_ queue   associated with a synchronization variable */SynchQNode	synchq[MAX_PROCS];/* There is a queue pointer for each lock, barrier, or semaphore,   and each of these pointers is actually a pointer to the _tail_   item of the queue, and the 'next' field of the tail item points   to the head item:       |___|       |___|       |___|--------------------------+       |___|                          |       |___|         head             V tail       |___|        +----+  +----+  +----+       |___|     +->|next|->|next|->|next|--+       |___|     |  |    |  |    |  |    |  |       |___|     |  +----+  +----+  +----+  |       |___|     |__________________________+       |   |     array of      pointers     (one array      for each      type of      synch var)  The array of pointers may grow in size as more synchronization variables  of a particular type are needed by the user program.*/       static	SynchQNode	**locks;static	int	num_allocated_locks = 0;static	int	num_used_locks = 0;static	SynchQNode	**barriers;static	int	*barrier_counts;static	int	num_allocated_barriers = 0;static	int	num_used_barriers = 0;static	SynchQNode	**semaphores;static	int	*sema_counts;static	int	num_allocated_semaphores = 0;static	int	num_used_semaphores = 0;#define NEW_THREAD_STACK_BASE	0x6ffffff0	/* arbitrary choice */#define NEW_THREAD_STACK_SIZE	(1 << 20)	/* 1 Megabyte *//* the following array of flags is used in the main simulation loop */int	active[MAX_PROCS];/* the following is made volatile because it is changed with a new process   and it is the upper bound of a 'for' loop nested in the main sim loop */volatile int	num_created_processes;static	int	num_terminated_processes = 0;/*--------------------------------------------------------------------*//* This function is called from ss_syscall() below when the user program   executes the runtime library code for thread creation. The 'wrapper'   function is also in the runtime library code, and is the function that   is actually called when the new thread is created. The 'func_ptr'   refers to the user program function that will then be called from   the wrapper function in the runtime library. Upon return from the   user function, the wrapper function will invoke the 'terminate thread'   system call and thereby support the semantics of the return from the   user function causing thread termination.*/static	void	CreateNewProcess (int pid,				  void (*func_ptr) (void),				  void (*wrapper) (void *)){    int			new_pid;    SS_ADDR_TYPE	stack_top;    new_pid = num_created_processes++;    if (num_created_processes > MAX_PROCS)    {	panic ("too many processes; the limit is %d\n", MAX_PROCS);    }    /* determine new top of stack;       this pointer will be passed on to register initialization */    stack_top = NEW_THREAD_STACK_BASE - (new_pid-1) * NEW_THREAD_STACK_SIZE;    /* the entry point (PC value) for a new thread is the 'wrapper' function */    regs_init (new_pid, stack_top, (SS_ADDR_TYPE) wrapper);    /* _after_ registers have been initialized, set register $a0 ($4)       with the user-supplied function pointer; wrapper will call it */    regs_R[new_pid][4] = (SS_ADDR_TYPE) func_ptr;    /* for synch queue node for this thread, set the pid and state fields */    synchq[new_pid].pid = new_pid;    synchq[new_pid].synch_state = FREE;	/* not waiting, holding, or blocked */    /* mark the new thread/process as active */    active[new_pid] = 1;    /* because the thread is now marked as active, and the total number       of created processes has been incremented, the main simulation loop       will shortly execute the first instruction of the new thread */}/*--------------------------------------------------------------------*//* syscall proxy handler, architect registers and memory are assumed to be   precise when this function is called, register and memory are updated with   the results of the system call */voidss_syscall(mem_access_fn mem_fn,	/* generic memory accessor */	   SS_INST_TYPE inst,		/* system call inst */	   int pid)			/* which processor */{  SS_WORD_TYPE syscode = regs_R[pid][2];  switch (syscode)    {	case SS_SYS_exit:	{	    ++num_terminated_processes;	    active[pid] = 0; /* mark this one as inactive */	    if (num_terminated_processes == num_created_processes)	    {		/* exit jumps to the target set in main() */		longjmp(sim_exit_buf, /* exitcode + fudge */regs_R[pid][4]+1);	    }	    /* else we must wait until last process finishes	       (this one has been marked inactive, so when we return	        to the main simulation loop, no further instructions	        will be fetched for this process) */	}      break;#if 0          case SS_SYS_fork:      break;#endif      #if 0    case SS_SYS_vfork:      break;#endif    case SS_SYS_read:      {	char *buf;	/* allocate same-sized input buffer in host memory */	if (!(buf = (char *)calloc(/*nbytes*/regs_R[pid][6], sizeof(char))))	  fatal("out of memory in SYS_read");	/* read data from file */	/*nread*/regs_R[pid][2] = read(/*fd*/regs_R[pid][4], buf, /*nbytes*/regs_R[pid][6]);	/* check for error condition */	if (regs_R[pid][2] != -1)	  regs_R[pid][7] = 0;	else	  {	    /* got an error, return details */	    regs_R[pid][2] = errno;	    regs_R[pid][7] = 1;	  }	/* copy results back into host memory */	mem_bcopy(mem_fn, Write, /*buf*/regs_R[pid][5], buf, /*nread*/regs_R[pid][2]);	/* done with input buffer */	free(buf);      }      break;    case SS_SYS_write:      {	char *buf;	/* allocate same-sized output buffer in host memory */	if (!(buf = (char *)calloc(/*nbytes*/regs_R[pid][6], sizeof(char))))	  fatal("out of memory in SYS_write");	/* copy inputs into host memory */	mem_bcopy(mem_fn, Read, /*buf*/regs_R[pid][5], buf, /*nbytes*/regs_R[pid][6]);	/* write data to file */	/*nwritten*/regs_R[pid][2] = write(/*fd*/regs_R[pid][4],				      buf, /*nbytes*/regs_R[pid][6]);	/* check for an error condition */	if (regs_R[pid][2] == regs_R[pid][6])	  /*result*/regs_R[pid][7] = 0;	else	  {	    /* got an error, return details */	    regs_R[pid][2] = errno;	    regs_R[pid][7] = 1;	  }	/* done with output buffer */	free(buf);      }      break;    case SS_SYS_open:      {	char buf[MAXBUFSIZE];	unsigned int i;	int ss_flags = regs_R[pid][5], local_flags = 0;	/* translate open(2) flags */	for (i=0; i<SS_NFLAGS; i++)	  {	    if (ss_flags & ss_flag_table[i].ss_flag)	      {		ss_flags &= ~ss_flag_table[i].ss_flag;		local_flags |= ss_flag_table[i].local_flag;	      }	  }	/* any target flags left? */	if (ss_flags != 0)	  fatal("syscall: open: cannot decode flags: 0x%08x", ss_flags);	/* copy filename to host memory */	mem_strcpy(mem_fn, Read, /*fname*/regs_R[pid][4], buf);	/* open the file */	/*fd*/regs_R[pid][2] = open(buf, local_flags, /*mode*/regs_R[pid][6]);		/* check for an error condition */	if (regs_R[pid][2] != -1)	  regs_R[pid][7] = 0;	else	  {	    /* got an error, return details */	    regs_R[pid][2] = errno;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -