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

📄 cpu.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  UNIX Simulator Dependent Source * *  COPYRIGHT (c) 1994,95 by Division Incorporated * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * *  $Id: cpu.c,v 1.46.2.1 2003/09/04 18:47:42 joel Exp $ */#include <rtems/system.h>#include <rtems/score/isr.h>#include <rtems/score/interr.h>#if defined(__linux__)#define _XOPEN_SOURCE#define MALLOC_0_RETURNS_NULL#endif#include <sys/types.h>#include <sys/times.h>#include <stdio.h>#include <stdlib.h>#include <setjmp.h>#include <signal.h>#include <time.h>#include <sys/time.h>#include <errno.h>#include <unistd.h>#if defined(RTEMS_MULTIPROCESSING)#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#endif#include <string.h>   /* memset */#ifndef SA_RESTART#define SA_RESTART 0#endiftypedef struct {  jmp_buf   regs;  int       isr_level;} Context_Control_overlay;void  _CPU_Signal_initialize(void);void  _CPU_Stray_signal(int);void  _CPU_ISR_Handler(int);static sigset_t _CPU_Signal_mask;static Context_Control_overlay _CPU_Context_Default_with_ISRs_enabled;static Context_Control_overlay _CPU_Context_Default_with_ISRs_disabled;/* * Sync IO support, an entry for each fd that can be set */void  _CPU_Sync_io_Init();static rtems_sync_io_handler _CPU_Sync_io_handlers[FD_SETSIZE];static int sync_io_nfds;static fd_set sync_io_readfds;static fd_set sync_io_writefds;static fd_set sync_io_exceptfds;/* * Which cpu are we? Used by libcpu and libbsp. */int cpu_number;/*PAGE * *  _CPU_Initialize_vectors() * *  Support routine to initialize the RTEMS vector table after it is allocated. * *  UNIX Specific Information: * *  Complete initialization since the table is now allocated. */ sigset_t  posix_empty_mask;void _CPU_Initialize_vectors(void){  unsigned32        i;  proc_ptr          old_handler;  /*   * Generate an empty mask to be used by disable_support   */  sigemptyset(&posix_empty_mask);  /*   * Block all the signals except SIGTRAP for the debugger   * and fatal error signals.   */  (void) sigfillset(&_CPU_Signal_mask);  (void) sigdelset(&_CPU_Signal_mask, SIGTRAP);  (void) sigdelset(&_CPU_Signal_mask, SIGABRT);#if !defined(__CYGWIN__)  (void) sigdelset(&_CPU_Signal_mask, SIGIOT);#endif  (void) sigdelset(&_CPU_Signal_mask, SIGCONT);  (void) sigdelset(&_CPU_Signal_mask, SIGSEGV);  (void) sigdelset(&_CPU_Signal_mask, SIGBUS);  (void) sigdelset(&_CPU_Signal_mask, SIGFPE);  _CPU_ISR_Enable(1);  /*   * Set the handler for all signals to be signal_handler   * which will then vector out to the correct handler   * for whichever signal actually happened. Initially   * set the vectors to the stray signal handler.   */  for (i = 0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)      (void)_CPU_ISR_install_vector(i, _CPU_Stray_signal, &old_handler);  _CPU_Signal_initialize();}void _CPU_Signal_initialize( void ){  struct sigaction  act;  sigset_t          mask;  /* mark them all active except for TraceTrap  and Abort */  mask = _CPU_Signal_mask;  sigprocmask(SIG_UNBLOCK, &mask, 0);  act.sa_handler = _CPU_ISR_Handler;  act.sa_mask = mask;  act.sa_flags = SA_RESTART;  sigaction(SIGHUP, &act, 0);  sigaction(SIGINT, &act, 0);  sigaction(SIGQUIT, &act, 0);  sigaction(SIGILL, &act, 0);#ifdef SIGEMT  sigaction(SIGEMT, &act, 0);#endif  sigaction(SIGFPE, &act, 0);  sigaction(SIGKILL, &act, 0);  sigaction(SIGBUS, &act, 0);  sigaction(SIGSEGV, &act, 0);#ifdef SIGSYS  sigaction(SIGSYS, &act, 0);#endif  sigaction(SIGPIPE, &act, 0);  sigaction(SIGALRM, &act, 0);  sigaction(SIGTERM, &act, 0);  sigaction(SIGUSR1, &act, 0);  sigaction(SIGUSR2, &act, 0);  sigaction(SIGCHLD, &act, 0);#ifdef SIGCLD  sigaction(SIGCLD, &act, 0);#endif#ifdef SIGPWR  sigaction(SIGPWR, &act, 0);#endif  sigaction(SIGVTALRM, &act, 0);  sigaction(SIGPROF, &act, 0);  sigaction(SIGIO, &act, 0);  sigaction(SIGWINCH, &act, 0);  sigaction(SIGSTOP, &act, 0);  sigaction(SIGTTIN, &act, 0);  sigaction(SIGTTOU, &act, 0);  sigaction(SIGURG, &act, 0);#ifdef SIGLOST    sigaction(SIGLOST, &act, 0);#endif}/*PAGE * *  _CPU_Context_From_CPU_Init */void _CPU_Context_From_CPU_Init(){#if defined(__hppa__) && defined(RTEMS_UNIXLIB_SETJMP)    /*     * HACK - set the _SYSTEM_ID to 0x20c so that setjmp/longjmp     * will handle the full 32 floating point registers.     */    {      extern unsigned32 _SYSTEM_ID;      _SYSTEM_ID = 0x20c;    }#endif  /*   *  get default values to use in _CPU_Context_Initialize()   */  if ( sizeof(Context_Control_overlay) > sizeof(Context_Control) )    _CPU_Fatal_halt( 0xdeadf00d );    (void) memset(    &_CPU_Context_Default_with_ISRs_enabled,    0,    sizeof(Context_Control_overlay)  );  (void) memset(    &_CPU_Context_Default_with_ISRs_disabled,    0,    sizeof(Context_Control_overlay)  );  _CPU_ISR_Set_level( 0 );  _CPU_Context_switch(    (Context_Control *) &_CPU_Context_Default_with_ISRs_enabled,    (Context_Control *) &_CPU_Context_Default_with_ISRs_enabled  );  _CPU_ISR_Set_level( 1 );  _CPU_Context_switch(    (Context_Control *) &_CPU_Context_Default_with_ISRs_disabled,    (Context_Control *) &_CPU_Context_Default_with_ISRs_disabled  );}/*PAGE * *  _CPU_Sync_io_Init */void _CPU_Sync_io_Init(){  int fd;  for (fd = 0; fd < FD_SETSIZE; fd++)    _CPU_Sync_io_handlers[fd] = NULL;  sync_io_nfds = 0;  FD_ZERO(&sync_io_readfds);  FD_ZERO(&sync_io_writefds);  FD_ZERO(&sync_io_exceptfds);}/*PAGE * *  _CPU_ISR_Get_level */unsigned32 _CPU_ISR_Get_level( void ){  sigset_t old_mask;  sigemptyset( &old_mask );  sigprocmask(SIG_BLOCK, 0, &old_mask);  if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))      return 1;  return 0;}/*  _CPU_Initialize * *  This routine performs processor dependent initialization. * *  INPUT PARAMETERS: *    cpu_table       - CPU table to initialize *    thread_dispatch - address of disptaching routine */void _CPU_Initialize(  rtems_cpu_table  *cpu_table,  void            (*thread_dispatch)      /* ignored on this CPU */){  /*   *  If something happened where the public Context_Control is not   *  at least as large as the private Context_Control_overlay, then   *  we are in trouble.   */  if ( sizeof(Context_Control_overlay) > sizeof(Context_Control) )    _CPU_Fatal_error(0x100 + 1);  /*   *  The thread_dispatch argument is the address of the entry point   *  for the routine called at the end of an ISR once it has been   *  decided a context switch is necessary.  On some compilation   *  systems it is difficult to call a high-level language routine   *  from assembly.  This allows us to trick these systems.   *   *  If you encounter this problem save the entry point in a CPU   *  dependent variable.   */  _CPU_Thread_dispatch_pointer = thread_dispatch;  /*   * XXX; If there is not an easy way to initialize the FP context   *      during Context_Initialize, then it is usually easier to   *      save an "uninitialized" FP context here and copy it to   *      the task's during Context_Initialize.   */  /* XXX: FP context initialization support */  _CPU_Table = *cpu_table;  _CPU_Sync_io_Init();  _CPU_Context_From_CPU_Init();}/*PAGE * *  _CPU_ISR_install_raw_handler */void _CPU_ISR_install_raw_handler(  unsigned32  vector,  proc_ptr    new_handler,  proc_ptr   *old_handler){  _CPU_Fatal_halt( 0xdeaddead );}/*PAGE * *  _CPU_ISR_install_vector * *  This kernel routine installs the RTEMS handler for the *  specified vector. * *  Input parameters: *    vector      - interrupt vector number *    old_handler - former ISR for this vector number *    new_handler - replacement ISR for this vector number * *  Output parameters:  NONE * */void _CPU_ISR_install_vector(  unsigned32  vector,  proc_ptr    new_handler,  proc_ptr   *old_handler){   *old_handler = _ISR_Vector_table[ vector ];   /*    *  If the interrupt vector table is a table of pointer to isr entry    *  points, then we need to install the appropriate RTEMS interrupt    *  handler for this vector number.    */   /*    *  We put the actual user ISR address in '_ISR_vector_table'.  This will    *  be used by the _CPU_ISR_Handler so the user gets control.    */    _ISR_Vector_table[ vector ] = new_handler;}/*PAGE * *  _CPU_Install_interrupt_stack */void _CPU_Install_interrupt_stack( void ){}/*PAGE * *  _CPU_Thread_Idle_body * *  Stop until we get a signal which is the logically the same thing *  entering low-power or sleep mode on a real processor and waiting for *  an interrupt.  This significantly reduces the consumption of host *  CPU cycles which is again similar to low power mode. */void _CPU_Thread_Idle_body( void ){#if CPU_SYNC_IO  extern void _Thread_Dispatch(void);  int fd;#endif  while (1) {#ifdef RTEMS_DEBUG    /* interrupts had better be enabled at this point! */    if (_CPU_ISR_Get_level() != 0)       abort();#endif    /*     *  Block on a select statement, the CPU interface added allow the     *  user to add new descriptors which are to be blocked on     */#if CPU_SYNC_IO    if (sync_io_nfds) {      int result;      fd_set readfds, writefds, exceptfds;      readfds = sync_io_readfds;      writefds = sync_io_writefds;      exceptfds = sync_io_exceptfds;      result = select(sync_io_nfds,                 &readfds,                 &writefds,                 &exceptfds,                 NULL);      if (result < 0) {	if (errno != EINTR)	  _CPU_Fatal_error(0x200);       /* FIXME : what number should go here !! */	_Thread_Dispatch();	continue;      }      for (fd = 0; fd < sync_io_nfds; fd++) {        boolean read = FD_ISSET(fd, &readfds);        boolean write = FD_ISSET(fd, &writefds);        boolean except = FD_ISSET(fd, &exceptfds);        if (_CPU_Sync_io_handlers[fd] && (read || write || except))          _CPU_Sync_io_handlers[fd](fd, read, write, except);      }      _Thread_Dispatch();    } else      pause();#else    pause();#endif  }}/*PAGE * *  _CPU_Context_Initialize */void _CPU_Context_Initialize(  Context_Control  *_the_context,  unsigned32       *_stack_base,  unsigned32        _size,  unsigned32        _new_level,  void             *_entry_point,  boolean           _is_fp){  unsigned32  *addr;  unsigned32   jmp_addr;  unsigned32   _stack_low;   /* lowest "stack aligned" address */  unsigned32   _stack_high;  /* highest "stack aligned" address */  unsigned32   _the_size;  jmp_addr = (unsigned32) _entry_point;  /*   *  On CPUs with stacks which grow down, we build the stack   *  based on the _stack_high address.  On CPUs with stacks which   *  grow up, we build the stack based on the _stack_low address.   */  _stack_low = (unsigned32)(_stack_base) + CPU_STACK_ALIGNMENT - 1;  _stack_low &= ~(CPU_STACK_ALIGNMENT - 1);  _stack_high = (unsigned32)(_stack_base) + _size;  _stack_high &= ~(CPU_STACK_ALIGNMENT - 1);  if (_stack_high > _stack_low)    _the_size = _stack_high - _stack_low;  else    _the_size = _stack_low - _stack_high;  /*   * Slam our jmp_buf template into the context we are creating   */  if ( _new_level == 0 )      *(Context_Control_overlay *)_the_context =                         _CPU_Context_Default_with_ISRs_enabled;  else      *(Context_Control_overlay *)_the_context =                          _CPU_Context_Default_with_ISRs_disabled;  addr = (unsigned32 *)_the_context;#if defined(__hppa__)  *(addr + RP_OFF) = jmp_addr;  *(addr + SP_OFF) = (unsigned32)(_stack_low + CPU_FRAME_SIZE);  /*   * See if we are using shared libraries by checking   * bit 30 in 24 off of newp. If bit 30 is set then   * we are using shared libraries and the jump address   * points to the pointer, so we put that into rp instead.   */  if (jmp_addr & 0x40000000) {    jmp_addr &= 0xfffffffc;     *(addr + RP_OFF) = *(unsigned32 *)jmp_addr;  }#elif defined(__sparc__)  /*   *  See /usr/include/sys/stack.h in Solaris 2.3 for a nice   *  diagram of the stack.   */  asm ("ta  0x03");            /* flush registers */  *(addr + RP_OFF) = jmp_addr + ADDR_ADJ_OFFSET;  *(addr + SP_OFF) = (unsigned32)(_stack_high - CPU_FRAME_SIZE);  *(addr + FP_OFF) = (unsigned32)(_stack_high);#elif defined(__i386__)    /*     *  This information was gathered by disassembling setjmp().     */    {      unsigned32 stack_ptr;      stack_ptr = _stack_high - CPU_FRAME_SIZE;      *(addr + EBX_OFF) = 0xFEEDFEED;      *(addr + ESI_OFF) = 0xDEADDEAD;      *(addr + EDI_OFF) = 0xDEAFDEAF;      *(addr + EBP_OFF) = stack_ptr;      *(addr + ESP_OFF) = stack_ptr;      *(addr + RET_OFF) = jmp_addr;      addr = (unsigned32 *) stack_ptr;      addr[ 0 ] = jmp_addr;      addr[ 1 ] = (unsigned32) stack_ptr;      addr[ 2 ] = (unsigned32) stack_ptr;    }#else#error "UNKNOWN CPU!!!"#endif}/*PAGE * *  _CPU_Context_restore

⌨️ 快捷键说明

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