diff options
Diffstat (limited to '')
-rw-r--r-- | c/src/exec/score/cpu/unix/cpu.c | 304 | ||||
-rw-r--r-- | c/src/exec/score/cpu/unix/cpu.h | 54 | ||||
-rw-r--r-- | c/src/exec/score/tools/unix/gensize.c | 116 |
3 files changed, 455 insertions, 19 deletions
diff --git a/c/src/exec/score/cpu/unix/cpu.c b/c/src/exec/score/cpu/unix/cpu.c index daff56a1de..54d4104ac7 100644 --- a/c/src/exec/score/cpu/unix/cpu.c +++ b/c/src/exec/score/cpu/unix/cpu.c @@ -20,16 +20,39 @@ #include <rtems/score/isr.h> #include <rtems/score/interr.h> +#if defined(solaris2) +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 3 +#undef __STRICT_ANSI__ +#define __STRICT_ANSI__ +#endif + +#if defined(linux) +#define MALLOC_0_RETURNS_NULL +#endif + #include <stdio.h> #include <stdlib.h> +#include <setjmp.h> #include <signal.h> #include <time.h> #include <sys/time.h> +#include <sys/types.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> #ifndef SA_RESTART #define SA_RESTART 0 #endif +typedef struct { + jmp_buf regs; + sigset_t isr_level; +} Context_Control_overlay; + void _CPU_Signal_initialize(void); void _CPU_Stray_signal(int); void _CPU_ISR_Handler(int); @@ -375,9 +398,9 @@ void _CPU_Context_Initialize( */ if ( _new_level == 0 ) - source = _CPU_Context_Default_with_ISRs_enabled.regs; + source = &_CPU_Context_Default_with_ISRs_enabled; else - source = _CPU_Context_Default_with_ISRs_disabled.regs; + source = &_CPU_Context_Default_with_ISRs_disabled; memcpy(_the_context, source, sizeof(Context_Control) ); /* sizeof(jmp_buf)); */ @@ -452,8 +475,10 @@ void _CPU_Context_restore( Context_Control *next ) { - sigprocmask( SIG_SETMASK, &next->isr_level, 0 ); - longjmp( next->regs, 0 ); + Context_Control_overlay *nextp = (Context_Control_overlay *)next; + + sigprocmask( SIG_SETMASK, &nextp->isr_level, 0 ); + longjmp( nextp->regs, 0 ); } /*PAGE @@ -466,13 +491,16 @@ void _CPU_Context_switch( Context_Control *next ) { + Context_Control_overlay *currentp = (Context_Control_overlay *)current; + Context_Control_overlay *nextp = (Context_Control_overlay *)next; + int status; /* * Switch levels in one operation */ - status = sigprocmask( SIG_SETMASK, &next->isr_level, ¤t->isr_level ); + status = sigprocmask( SIG_SETMASK, &nextp->isr_level, ¤tp->isr_level ); if ( status ) _Internal_error_Occurred( INTERNAL_ERROR_CORE, @@ -480,8 +508,8 @@ void _CPU_Context_switch( status ); - if (setjmp(current->regs) == 0) { /* Save the current context */ - longjmp(next->regs, 0); /* Switch to the new context */ + if (setjmp(currentp->regs) == 0) { /* Save the current context */ + longjmp(nextp->regs, 0); /* Switch to the new context */ if ( status ) _Internal_error_Occurred( INTERNAL_ERROR_CORE, @@ -610,18 +638,19 @@ void _CPU_ISR_Handler(int vector) void _CPU_Stray_signal(int sig_num) { - char buffer[ 80 ]; + char buffer[ 4 ]; /* * We avoid using the stdio section of the library. * The following is generally safe. */ - write( - 2, - buffer, - sprintf( buffer, "Stray signal %d\n", sig_num ) - ); + buffer[ 0 ] = (sig_num >> 4) + 0x30; + buffer[ 1 ] = (sig_num & 0xf) + 0x30; + buffer[ 2 ] = '\n'; + + write( 2, "Stray signal 0x", 12 ); + write( 2, buffer, 3 ); /* * If it was a "fatal" signal, then exit here @@ -680,3 +709,252 @@ int _CPU_ffs(unsigned32 value) return output; } + + +/* + * Special Purpose Routines to hide the use of UNIX system calls. + */ + +#if 0 +/* XXX clock had this set of #define's */ + +/* + * In order to get the types and prototypes used in this file under + * Solaris 2.3, it is necessary to pull the following magic. + */ + +#if defined(solaris) +#warning "Ignore the undefining __STDC__ warning" +#undef __STDC__ +#define __STDC__ 0 +#undef _POSIX_C_SOURCE +#endif +#endif + +int _CPU_Get_clock_vector( void ) +{ + return SIGALRM; +} + + +void _CPU_Start_clock( + int microseconds +) +{ + struct itimerval new; + + new.it_value.tv_sec = 0; + new.it_value.tv_usec = microseconds; + new.it_interval.tv_sec = 0; + new.it_interval.tv_usec = microseconds; + + setitimer(ITIMER_REAL, &new, 0); +} + +void _CPU_Stop_clock( void ) +{ + struct itimerval new; + struct sigaction act; + + /* + * Set the SIGALRM signal to ignore any last + * signals that might come in while we are + * disarming the timer and removing the interrupt + * vector. + */ + + act.sa_handler = SIG_IGN; + + sigaction(SIGALRM, &act, 0); + + new.it_value.tv_sec = 0; + new.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &new, 0); +} + +int _CPU_SHM_Semid; +extern void fix_syscall_errno( void ); + +void _CPU_SHM_Init( + unsigned32 maximum_nodes, + boolean is_master_node, + void **shm_address, + unsigned32 *shm_length +) +{ + int i; + int shmid; + char *shm_addr; + key_t shm_key; + key_t sem_key; + int status; + int shm_size; + + if (getenv("RTEMS_SHM_KEY")) + shm_key = strtol(getenv("RTEMS_SHM_KEY"), 0, 0); + else +#ifdef RTEMS_SHM_KEY + shm_key = RTEMS_SHM_KEY; +#else + shm_key = 0xa000; +#endif + + if (getenv("RTEMS_SHM_SIZE")) + shm_size = strtol(getenv("RTEMS_SHM_SIZE"), 0, 0); + else +#ifdef RTEMS_SHM_SIZE + shm_size = RTEMS_SHM_SIZE; +#else + shm_size = 64 * 1024; +#endif + + if (getenv("RTEMS_SHM_SEMAPHORE_KEY")) + sem_key = strtol(getenv("RTEMS_SHM_SEMAPHORE_KEY"), 0, 0); + else +#ifdef RTEMS_SHM_SEMAPHORE_KEY + sem_key = RTEMS_SHM_SEMAPHORE_KEY; +#else + sem_key = 0xa001; +#endif + + shmid = shmget(shm_key, shm_size, IPC_CREAT | 0660); + if ( shmid == -1 ) { + fix_syscall_errno(); /* in case of newlib */ + perror( "shmget" ); + _CPU_Fatal_halt( 0xdead0001 ); + } + + shm_addr = shmat(shmid, (char *)0, SHM_RND); + if ( shm_addr == (void *)-1 ) { + fix_syscall_errno(); /* in case of newlib */ + perror( "shmat" ); + _CPU_Fatal_halt( 0xdead0002 ); + } + + _CPU_SHM_Semid = semget(sem_key, maximum_nodes + 1, IPC_CREAT | 0660); + if ( _CPU_SHM_Semid == -1 ) { + fix_syscall_errno(); /* in case of newlib */ + perror( "semget" ); + _CPU_Fatal_halt( 0xdead0003 ); + } + + if ( is_master_node ) { + for ( i=0 ; i <= maximum_nodes ; i++ ) { +#if defined(solaris2) + union semun { + int val; + struct semid_ds *buf; + ushort *array; + } help; + + help.val = 1; + status = semctl( _CPU_SHM_Semid, i, SETVAL, help ); +#endif +#if defined(hpux) + status = semctl( _CPU_SHM_Semid, i, SETVAL, 1 ); +#endif + + fix_syscall_errno(); /* in case of newlib */ + if ( status == -1 ) { + _CPU_Fatal_halt( 0xdead0004 ); + } + } + } + + *shm_address = shm_addr; + *shm_length = shm_size; + +} + +int _CPU_Get_pid( void ) +{ + return getpid(); +} + +/* + * Define this to use signals for MPCI shared memory driver. + * If undefined, the shared memory driver will poll from the + * clock interrupt. + * Ref: ../shmsupp/getcfg.c + * + * BEWARE:: many UN*X kernels and debuggers become severely confused when + * debugging programs which use signals. The problem is *much* + * worse when using multiple signals, since ptrace(2) tends to + * drop all signals except 1 in the case of multiples. + * On hpux9, this problem was so bad, we couldn't use interrupts + * with the shared memory driver if we ever hoped to debug + * RTEMS programs. + * Maybe systems that use /proc don't have this problem... + */ + + +int _CPU_SHM_Get_vector( void ) +{ +#ifdef CPU_USE_SHM_INTERRUPTS + return SIGUSR1; +#else + return 0; +#endif +} + +void _CPU_SHM_Send_interrupt( + int pid, + int vector +) +{ + kill((pid_t) pid, vector); +} + +void _CPU_SHM_Lock( + int semaphore +) +{ + struct sembuf sb; + int status; + + sb.sem_num = semaphore; + sb.sem_op = -1; + sb.sem_flg = 0; + + while (1) { + status = semop(_CPU_SHM_Semid, &sb, 1); + if ( status >= 0 ) + break; + if ( status == -1 ) { + fix_syscall_errno(); /* in case of newlib */ + if (errno == EINTR) + continue; + perror("shm lock"); + _CPU_Fatal_halt( 0xdead0005 ); + } + } + +} + +void _CPU_SHM_Unlock( + int semaphore +) +{ + struct sembuf sb; + int status; + + sb.sem_num = semaphore; + sb.sem_op = 1; + sb.sem_flg = 0; + + while (1) { + status = semop(_CPU_SHM_Semid, &sb, 1); + if ( status >= 0 ) + break; + + if ( status == -1 ) { + fix_syscall_errno(); /* in case of newlib */ + if (errno == EINTR) + continue; + perror("shm unlock"); + _CPU_Fatal_halt( 0xdead0006 ); + } + } + +} diff --git a/c/src/exec/score/cpu/unix/cpu.h b/c/src/exec/score/cpu/unix/cpu.h index d7ff311af1..b4b34d4eff 100644 --- a/c/src/exec/score/cpu/unix/cpu.h +++ b/c/src/exec/score/cpu/unix/cpu.h @@ -31,6 +31,8 @@ extern "C" { #include <rtems/score/unixtypes.h> #endif +#include <rtems/score/unixsize.h> + #if defined(solaris2) #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 3 @@ -42,10 +44,6 @@ extern "C" { #define MALLOC_0_RETURNS_NULL #endif -#include <unistd.h> -#include <setjmp.h> -#include <signal.h> - /* conditional compilation parameters */ /* @@ -431,9 +429,17 @@ extern "C" { * a debugger such as gdb. But that is another problem. */ +/* + * This is really just the area for the following fields. + * + * jmp_buf regs; + * sigset_t isr_level; + * + * Doing it this way avoids conflicts between the native stuff and the + * RTEMS stuff. + */ typedef struct { - jmp_buf regs; - sigset_t isr_level; + char Area[ CPU_CONTEXT_SIZE_IN_BYTES ]; } Context_Control; typedef struct { @@ -968,6 +974,42 @@ static inline unsigned int CPU_swap_u32( return( swapped ); } +/* + * Special Purpose Routines to hide the use of UNIX system calls. + */ + +int _CPU_Get_clock_vector( void ); + +void _CPU_Start_clock( + int microseconds +); + +void _CPU_Stop_clock( void ); + +void _CPU_SHM_Init( + unsigned32 maximum_nodes, + boolean is_master_node, + void **shm_address, + unsigned32 *shm_length +); + +int _CPU_Get_pid( void ); + +int _CPU_SHM_Get_vector( void ); + +void _CPU_SHM_Send_interrupt( + int pid, + int vector +); + +void _CPU_SHM_Lock( + int semaphore +); + +void _CPU_SHM_Unlock( + int semaphore +); + #ifdef __cplusplus } #endif diff --git a/c/src/exec/score/tools/unix/gensize.c b/c/src/exec/score/tools/unix/gensize.c new file mode 100644 index 0000000000..0466d67b09 --- /dev/null +++ b/c/src/exec/score/tools/unix/gensize.c @@ -0,0 +1,116 @@ +/* + * gensize.c + * + * This file generates the file unixsize.h + * + * NOTE: It only prints the minimal information required. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + * + */ + +/* + * This feels like a very crude way to determine if we are on a Solaris + * host but it does work. + */ + +#if defined(__sun__) && defined(__sparc__) && \ + defined(__unix__) && defined(__svr4__) +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 3 +#undef __STRICT_ANSI__ +#endif + +#include <stdio.h> +#include <unistd.h> +#include <setjmp.h> +#include <signal.h> + +typedef struct { + jmp_buf regs; + sigset_t isr_level; +} Context_Control; + +int main( + int argc, + char **argv +) +{ + Context_Control *cc = 0; + + /* + * Print the file header + */ + +printf( + "/* unixsize.h\n" + " *\n" + " * This include file contans the size of the context control block\n" + " * C data structure. This structure must be defined in such a way\n" + " * that files NOT including the native header files can work.\n" + " *\n" + " * NOTE: THIS FILE IS AUTOMATICALLY GENERATED!!!!\n" + " * DO NOT EDIT THIS BY HAND!!!!\n" + " *\n" + " * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.\n" + " * On-Line Applications Research Corporation (OAR).\n" + " * All rights assigned to U.S. Government, 1994.\n" + " *\n" + " * This material may be reproduced by or for the U.S. Government pursuant\n" + " * to the copyright license under the clause at DFARS 252.227-7013. This\n" + " * notice must appear in all copies of this file and its derivatives.\n" + " */\n" + "\n" + "#ifndef __UNIXSIZE_h\n" + "#define __UNIXSIZE_h\n" + "\n" +); + +#define PRINT_IT( STRING, NUMBER ) \ + printf( "#define\t%s\t0x%x\t\t/* %d */\n", \ + STRING, \ + NUMBER, \ + NUMBER ); + +#define PRINT_SIZE( STRING, NUMBER ) \ + printf( "#define\t%s\t0x%x\t\t/* %d */\n", \ + STRING, \ + NUMBER, \ + NUMBER ); + +#define PRINT_COMMENT( STRING ) \ + printf( \ + "\n" \ + "/*\n" \ + " * " STRING "\n" \ + " */\n" \ + "\n" \ + ); + + PRINT_COMMENT("Context_Control information"); + + PRINT_SIZE("CPU_CONTEXT_SIZE_IN_BYTES", sizeof( Context_Control ) ); + PRINT_SIZE("CPU_CONTEXT_REGISTERS_OFFSET_IN_BYTES", (int) &cc->regs ); + PRINT_SIZE("CPU_CONTEXT_SIGNALS_OFFSET_IN_BYTES", (int) &cc->isr_level ); + + /* + * Print the end of file stuff + */ + + printf( + "\n" + "#endif /* __UNIXSIZE_h */\n" + "\n" + "/* end of include file */\n" + ); + + return 0; +} + |