source: rtems/c/src/exec/score/cpu/unix/cpu.c @ 254b4450

4.104.114.84.95
Last change on this file since 254b4450 was 254b4450, checked in by Joel Sherrill <joel.sherrill@…>, on 04/01/97 at 23:07:52

This set of changes is the build of what was required to convert to
GNU autoconf. This is the first large step in allowing an RTEMS
user to perform a one-tree build (per crossgcc FAQ) including RTEMS
in the build process. With this change RTEMS is configured in
built in the same style as the GNU tools, yet retains the basic
structure of its traditional Makefiles (ala Tony Bennett).
Jiri Gaisler (jgais@…) deserves (and received)
a big thank you for doing this.

There are still issues to be resolved but as of this commit, all target
which can be built on a linux host have been using a modified version
of the source Jiri submitted. This source was merged and most targets
built in the tree before this commit.

There are some issues which remain to be resolved but they are primarily
related to host OS dependencies, script issues, the use of gawk
for hack_specs, and the dependence on gcc snapshots. These will
be resolved.

  • Property mode set to 100644
File size: 20.7 KB
Line 
1/*
2 *  UNIX Simulator Dependent Source
3 *
4 *
5 *  To anyone who acknowledges that this file is provided "AS IS"
6 *  without any express or implied warranty:
7 *      permission to use, copy, modify, and distribute this file
8 *      for any purpose is hereby granted without fee, provided that
9 *      the above copyright notice and this notice appears in all
10 *      copies, and that the name of Division Incorporated not be
11 *      used in advertising or publicity pertaining to distribution
12 *      of the software without specific, written prior permission.
13 *      Division Incorporated makes no representations about the
14 *      suitability of this software for any purpose.
15 *
16 *  $Id$
17 */
18
19#include <rtems/system.h>
20#include <rtems/score/isr.h>
21#include <rtems/score/interr.h>
22
23#if defined(solaris2)
24/*
25#undef  _POSIX_C_SOURCE
26#define _POSIX_C_SOURCE 3
27#undef  __STRICT_ANSI__
28#define __STRICT_ANSI__
29*/
30#define __EXTENSIONS__
31#endif
32
33#if defined(linux)
34#define MALLOC_0_RETURNS_NULL
35#endif
36
37#include <sys/types.h>
38#include <sys/times.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <setjmp.h>
42#include <signal.h>
43#include <time.h>
44#include <sys/time.h>
45#include <errno.h>
46#include <unistd.h>
47#include <sys/ipc.h>
48#include <sys/shm.h>
49#include <sys/sem.h>
50#include <string.h>   /* memset */
51
52#ifndef SA_RESTART
53#define SA_RESTART 0
54#endif
55
56typedef struct {
57  jmp_buf   regs;
58  unsigned32  isr_level;
59} Context_Control_overlay;
60
61void  _CPU_Signal_initialize(void);
62void  _CPU_Stray_signal(int);
63void  _CPU_ISR_Handler(int);
64
65static sigset_t         _CPU_Signal_mask;
66static Context_Control_overlay
67          _CPU_Context_Default_with_ISRs_enabled CPU_STRUCTURE_ALIGNMENT;
68static Context_Control_overlay
69          _CPU_Context_Default_with_ISRs_disabled CPU_STRUCTURE_ALIGNMENT;
70
71/*
72 * Which cpu are we? Used by libcpu and libbsp.
73 */
74
75int cpu_number;
76
77/*PAGE
78 *
79 *  _CPU_ISR_From_CPU_Init
80 */
81
82sigset_t  posix_empty_mask;
83
84void _CPU_ISR_From_CPU_Init()
85{
86  unsigned32        i;
87  proc_ptr          old_handler;
88
89  /*
90   * Generate an empty mask to be used by disable_support
91   */
92
93  sigemptyset(&posix_empty_mask);
94
95  /*
96   * Block all the signals except SIGTRAP for the debugger
97   * and fatal error signals.
98   */
99
100  (void) sigfillset(&_CPU_Signal_mask);
101  (void) sigdelset(&_CPU_Signal_mask, SIGTRAP);
102  (void) sigdelset(&_CPU_Signal_mask, SIGABRT);
103  (void) sigdelset(&_CPU_Signal_mask, SIGIOT);
104  (void) sigdelset(&_CPU_Signal_mask, SIGCONT);
105  (void) sigdelset(&_CPU_Signal_mask, SIGSEGV);
106  (void) sigdelset(&_CPU_Signal_mask, SIGBUS);
107  (void) sigdelset(&_CPU_Signal_mask, SIGFPE);
108
109  _CPU_ISR_Enable(1);
110
111  /*
112   * Set the handler for all signals to be signal_handler
113   * which will then vector out to the correct handler
114   * for whichever signal actually happened. Initially
115   * set the vectors to the stray signal handler.
116   */
117
118  for (i = 0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
119      (void)_CPU_ISR_install_vector(i, _CPU_Stray_signal, &old_handler);
120
121  _CPU_Signal_initialize();
122}
123
124void _CPU_Signal_initialize( void )
125{
126  struct sigaction  act;
127  sigset_t          mask;
128
129  /* mark them all active except for TraceTrap  and Abort */
130
131  mask = _CPU_Signal_mask;
132  sigprocmask(SIG_UNBLOCK, &mask, 0);
133
134  act.sa_handler = _CPU_ISR_Handler;
135  act.sa_mask = mask;
136  act.sa_flags = SA_RESTART;
137
138  sigaction(SIGHUP, &act, 0);
139  sigaction(SIGINT, &act, 0);
140  sigaction(SIGQUIT, &act, 0);
141  sigaction(SIGILL, &act, 0);
142#ifdef SIGEMT
143  sigaction(SIGEMT, &act, 0);
144#endif
145  sigaction(SIGFPE, &act, 0);
146  sigaction(SIGKILL, &act, 0);
147  sigaction(SIGBUS, &act, 0);
148  sigaction(SIGSEGV, &act, 0);
149#ifdef SIGSYS
150  sigaction(SIGSYS, &act, 0);
151#endif
152  sigaction(SIGPIPE, &act, 0);
153  sigaction(SIGALRM, &act, 0);
154  sigaction(SIGTERM, &act, 0);
155  sigaction(SIGUSR1, &act, 0);
156  sigaction(SIGUSR2, &act, 0);
157  sigaction(SIGCHLD, &act, 0);
158  sigaction(SIGCLD, &act, 0);
159  sigaction(SIGPWR, &act, 0);
160  sigaction(SIGVTALRM, &act, 0);
161  sigaction(SIGPROF, &act, 0);
162  sigaction(SIGIO, &act, 0);
163  sigaction(SIGWINCH, &act, 0);
164  sigaction(SIGSTOP, &act, 0);
165  sigaction(SIGTTIN, &act, 0);
166  sigaction(SIGTTOU, &act, 0);
167  sigaction(SIGURG, &act, 0);
168#ifdef SIGLOST
169    sigaction(SIGLOST, &act, 0);
170#endif
171}
172
173/*PAGE
174 *
175 *  _CPU_Context_From_CPU_Init
176 */
177
178void _CPU_Context_From_CPU_Init()
179{
180
181#if defined(hppa1_1) && defined(RTEMS_UNIXLIB_SETJMP)
182    /*
183     * HACK - set the _SYSTEM_ID to 0x20c so that setjmp/longjmp
184     * will handle the full 32 floating point registers.
185     */
186
187    {
188      extern unsigned32 _SYSTEM_ID;
189
190      _SYSTEM_ID = 0x20c;
191    }
192#endif
193
194  /*
195   *  get default values to use in _CPU_Context_Initialize()
196   */
197
198
199  (void) memset(
200    &_CPU_Context_Default_with_ISRs_enabled,
201    0,
202    sizeof(Context_Control)
203  );
204  (void) memset(
205    &_CPU_Context_Default_with_ISRs_disabled,
206    0,
207    sizeof(Context_Control)
208  );
209
210  _CPU_ISR_Set_level( 0 );
211  _CPU_Context_switch(
212    (Context_Control *) &_CPU_Context_Default_with_ISRs_enabled,
213    (Context_Control *) &_CPU_Context_Default_with_ISRs_enabled
214  );
215
216  _CPU_ISR_Set_level( 1 );
217  _CPU_Context_switch(
218    (Context_Control *) &_CPU_Context_Default_with_ISRs_disabled,
219    (Context_Control *) &_CPU_Context_Default_with_ISRs_disabled
220  );
221}
222
223/*PAGE
224 *
225 *  _CPU_ISR_Get_level
226 */
227
228unsigned32 _CPU_ISR_Get_level( void )
229{
230  sigset_t old_mask;
231
232  sigprocmask(SIG_BLOCK, 0, &old_mask);
233
234  if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))
235      return 1;
236
237  return 0;
238}
239
240/*  _CPU_Initialize
241 *
242 *  This routine performs processor dependent initialization.
243 *
244 *  INPUT PARAMETERS:
245 *    cpu_table       - CPU table to initialize
246 *    thread_dispatch - address of disptaching routine
247 */
248
249
250void _CPU_Initialize(
251  rtems_cpu_table  *cpu_table,
252  void            (*thread_dispatch)      /* ignored on this CPU */
253)
254{
255  /*
256   *  The thread_dispatch argument is the address of the entry point
257   *  for the routine called at the end of an ISR once it has been
258   *  decided a context switch is necessary.  On some compilation
259   *  systems it is difficult to call a high-level language routine
260   *  from assembly.  This allows us to trick these systems.
261   *
262   *  If you encounter this problem save the entry point in a CPU
263   *  dependent variable.
264   */
265
266  _CPU_Thread_dispatch_pointer = thread_dispatch;
267
268  /*
269   * XXX; If there is not an easy way to initialize the FP context
270   *      during Context_Initialize, then it is usually easier to
271   *      save an "uninitialized" FP context here and copy it to
272   *      the task's during Context_Initialize.
273   */
274
275  /* XXX: FP context initialization support */
276
277  _CPU_Table = *cpu_table;
278
279  _CPU_ISR_From_CPU_Init();
280
281  _CPU_Context_From_CPU_Init();
282
283}
284
285/*PAGE
286 *
287 *  _CPU_ISR_install_raw_handler
288 */
289
290void _CPU_ISR_install_raw_handler(
291  unsigned32  vector,
292  proc_ptr    new_handler,
293  proc_ptr   *old_handler
294)
295{
296  _CPU_Fatal_halt( 0xdeaddead );
297}
298
299/*PAGE
300 *
301 *  _CPU_ISR_install_vector
302 *
303 *  This kernel routine installs the RTEMS handler for the
304 *  specified vector.
305 *
306 *  Input parameters:
307 *    vector      - interrupt vector number
308 *    old_handler - former ISR for this vector number
309 *    new_handler - replacement ISR for this vector number
310 *
311 *  Output parameters:  NONE
312 *
313 */
314
315
316void _CPU_ISR_install_vector(
317  unsigned32  vector,
318  proc_ptr    new_handler,
319  proc_ptr   *old_handler
320)
321{
322   *old_handler = _ISR_Vector_table[ vector ];
323
324   /*
325    *  If the interrupt vector table is a table of pointer to isr entry
326    *  points, then we need to install the appropriate RTEMS interrupt
327    *  handler for this vector number.
328    */
329
330   /*
331    *  We put the actual user ISR address in '_ISR_vector_table'.  This will
332    *  be used by the _CPU_ISR_Handler so the user gets control.
333    */
334
335    _ISR_Vector_table[ vector ] = new_handler;
336}
337
338/*PAGE
339 *
340 *  _CPU_Install_interrupt_stack
341 */
342
343void _CPU_Install_interrupt_stack( void )
344{
345}
346
347/*PAGE
348 *
349 *  _CPU_Thread_Idle_body
350 *
351 *  Stop until we get a signal which is the logically the same thing
352 *  entering low-power or sleep mode on a real processor and waiting for
353 *  an interrupt.  This significantly reduces the consumption of host
354 *  CPU cycles which is again similar to low power mode.
355 */
356
357void _CPU_Thread_Idle_body( void )
358{
359  while (1) {
360#ifdef RTEMS_DEBUG
361    /* interrupts had better be enabled at this point! */
362    if (_CPU_ISR_Get_level() != 0)
363       abort();
364#endif
365    pause();
366  }
367
368}
369
370/*PAGE
371 *
372 *  _CPU_Context_Initialize
373 */
374
375void _CPU_Context_Initialize(
376  Context_Control  *_the_context,
377  unsigned32       *_stack_base,
378  unsigned32        _size,
379  unsigned32        _new_level,
380  void             *_entry_point,
381  boolean           _is_fp
382)
383{
384  unsigned32  *addr;
385  unsigned32   jmp_addr;
386  unsigned32   _stack_low;   /* lowest "stack aligned" address */
387  unsigned32   _stack_high;  /* highest "stack aligned" address */
388  unsigned32   _the_size;
389
390  jmp_addr = (unsigned32) _entry_point;
391
392  /*
393   *  On CPUs with stacks which grow down, we build the stack
394   *  based on the _stack_high address.  On CPUs with stacks which
395   *  grow up, we build the stack based on the _stack_low address.
396   */
397
398  _stack_low = (unsigned32)(_stack_base) + CPU_STACK_ALIGNMENT - 1;
399  _stack_low &= ~(CPU_STACK_ALIGNMENT - 1);
400
401  _stack_high = (unsigned32)(_stack_base) + _size;
402  _stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
403
404  if (_stack_high > _stack_low)
405    _the_size = _stack_high - _stack_low;
406  else
407    _the_size = _stack_low - _stack_high;
408
409  /*
410   * Slam our jmp_buf template into the context we are creating
411   */
412
413  if ( _new_level == 0 )
414      *_the_context = *(Context_Control *)
415                         &_CPU_Context_Default_with_ISRs_enabled;
416  else
417      *_the_context = *(Context_Control *)
418                         &_CPU_Context_Default_with_ISRs_disabled;
419
420  addr = (unsigned32 *)_the_context;
421
422#if defined(hppa1_1)
423  *(addr + RP_OFF) = jmp_addr;
424  *(addr + SP_OFF) = (unsigned32)(_stack_low + CPU_FRAME_SIZE);
425
426  /*
427   * See if we are using shared libraries by checking
428   * bit 30 in 24 off of newp. If bit 30 is set then
429   * we are using shared libraries and the jump address
430   * points to the pointer, so we put that into rp instead.
431   */
432
433  if (jmp_addr & 0x40000000) {
434    jmp_addr &= 0xfffffffc;
435     *(addr + RP_OFF) = *(unsigned32 *)jmp_addr;
436  }
437#elif defined(sparc)
438
439  /*
440   *  See /usr/include/sys/stack.h in Solaris 2.3 for a nice
441   *  diagram of the stack.
442   */
443
444  asm ("ta  0x03");            /* flush registers */
445
446  *(addr + RP_OFF) = jmp_addr + ADDR_ADJ_OFFSET;
447  *(addr + SP_OFF) = (unsigned32)(_stack_high - CPU_FRAME_SIZE);
448  *(addr + FP_OFF) = (unsigned32)(_stack_high);
449
450#elif defined(i386) || defined(__i386__)
451
452    /*
453     *  This information was gathered by disassembling setjmp().
454     */
455
456    {
457      unsigned32 stack_ptr;
458
459      stack_ptr = _stack_high - CPU_FRAME_SIZE;
460
461      *(addr + EBX_OFF) = 0xFEEDFEED;
462      *(addr + ESI_OFF) = 0xDEADDEAD;
463      *(addr + EDI_OFF) = 0xDEAFDEAF;
464      *(addr + EBP_OFF) = stack_ptr;
465      *(addr + ESP_OFF) = stack_ptr;
466      *(addr + RET_OFF) = jmp_addr;
467
468      addr = (unsigned32 *) stack_ptr;
469
470      addr[ 0 ] = jmp_addr;
471      addr[ 1 ] = (unsigned32) stack_ptr;
472      addr[ 2 ] = (unsigned32) stack_ptr;
473    }
474
475#else
476#error "UNKNOWN CPU!!!"
477#endif
478
479}
480
481/*PAGE
482 *
483 *  _CPU_Context_restore
484 */
485
486void _CPU_Context_restore(
487  Context_Control  *next
488)
489{
490  Context_Control_overlay *nextp = (Context_Control_overlay *)next;
491
492  _CPU_ISR_Enable(nextp->isr_level);
493  longjmp( nextp->regs, 0 );
494}
495
496/*PAGE
497 *
498 *  _CPU_Context_switch
499 */
500
501static void do_jump(
502  Context_Control_overlay *currentp,
503  Context_Control_overlay *nextp
504);
505
506void _CPU_Context_switch(
507  Context_Control  *current,
508  Context_Control  *next
509)
510{
511  Context_Control_overlay *currentp = (Context_Control_overlay *)current;
512  Context_Control_overlay *nextp = (Context_Control_overlay *)next;
513#if 0
514  int status;
515#endif
516
517  currentp->isr_level = _CPU_ISR_Disable_support();
518
519  do_jump( currentp, nextp );
520
521#if 0
522  if (sigsetjmp(currentp->regs, 1) == 0) {    /* Save the current context */
523     siglongjmp(nextp->regs, 0);           /* Switch to the new context */
524     _Internal_error_Occurred(
525         INTERNAL_ERROR_CORE,
526         TRUE,
527         status
528       );
529  }
530#endif
531
532#ifdef RTEMS_DEBUG
533    if (_CPU_ISR_Get_level() == 0)
534       abort();
535#endif
536
537  _CPU_ISR_Enable(currentp->isr_level);
538}
539
540static void do_jump(
541  Context_Control_overlay *currentp,
542  Context_Control_overlay *nextp
543)
544{
545  int status;
546
547  if (setjmp(currentp->regs) == 0) {    /* Save the current context */
548     longjmp(nextp->regs, 0);           /* Switch to the new context */
549     _Internal_error_Occurred(
550         INTERNAL_ERROR_CORE,
551         TRUE,
552         status
553       );
554  }
555}
556
557/*PAGE
558 *
559 *  _CPU_Save_float_context
560 */
561
562void _CPU_Save_float_context(
563  Context_Control_fp *fp_context
564)
565{
566}
567
568/*PAGE
569 *
570 *  _CPU_Restore_float_context
571 */
572
573void _CPU_Restore_float_context(
574  Context_Control_fp *fp_context
575)
576{
577}
578
579/*PAGE
580 *
581 *  _CPU_ISR_Disable_support
582 */
583
584unsigned32 _CPU_ISR_Disable_support(void)
585{
586  int status;
587  sigset_t  old_mask;
588
589  status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, &old_mask);
590  if ( status )
591    _Internal_error_Occurred(
592      INTERNAL_ERROR_CORE,
593      TRUE,
594      status
595    );
596
597  if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))
598    return 1;
599
600  return 0;
601}
602
603/*PAGE
604 *
605 *  _CPU_ISR_Enable
606 */
607
608void _CPU_ISR_Enable(
609  unsigned32 level
610)
611{
612  int status;
613
614  if (level == 0)
615    status = sigprocmask(SIG_UNBLOCK, &_CPU_Signal_mask, 0);
616  else
617    status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, 0);
618
619  if ( status )
620    _Internal_error_Occurred(
621      INTERNAL_ERROR_CORE,
622      TRUE,
623      status
624    );
625}
626
627/*PAGE
628 *
629 *  _CPU_ISR_Handler
630 *
631 *  External interrupt handler.
632 *  This is installed as a UNIX signal handler.
633 *  It vectors out to specific user interrupt handlers.
634 */
635
636void _CPU_ISR_Handler(int vector)
637{
638  extern void        _Thread_Dispatch(void);
639  extern unsigned32  _Thread_Dispatch_disable_level;
640  extern boolean     _Context_Switch_necessary;
641
642  if (_ISR_Nest_level++ == 0) {
643      /* switch to interrupt stack */
644  }
645
646  _Thread_Dispatch_disable_level++;
647
648  if (_ISR_Vector_table[vector]) {
649     _ISR_Vector_table[vector](vector);
650  } else {
651     _CPU_Stray_signal(vector);
652  }
653
654  if (_ISR_Nest_level-- == 0) {
655      /* switch back to original stack */
656  }
657
658  _Thread_Dispatch_disable_level--;
659
660  if (_Thread_Dispatch_disable_level == 0 &&
661      (_Context_Switch_necessary || _ISR_Signals_to_thread_executing)) {
662      _ISR_Signals_to_thread_executing = FALSE;
663      _CPU_ISR_Enable(0);
664      _Thread_Dispatch();
665  }
666}
667
668/*PAGE
669 *
670 *  _CPU_Stray_signal
671 */
672
673void _CPU_Stray_signal(int sig_num)
674{
675  char buffer[ 4 ];
676
677  /*
678   * print "stray" msg about ones which that might mean something
679   * Avoid using the stdio section of the library.
680   * The following is generally safe.
681   */
682
683  switch (sig_num)
684  {
685      case SIGCLD:
686          break;
687
688      default:
689      {
690        /*
691         *  We avoid using the stdio section of the library.
692         *  The following is generally safe
693         */
694
695        int digit;
696        int number = sig_num;
697        int len = 0;
698
699        digit = number / 100;
700        number %= 100;
701        if (digit) buffer[len++] = '0' + digit;
702
703        digit = number / 10;
704        number %= 10;
705        if (digit || len) buffer[len++] = '0' + digit;
706
707        digit = number;
708        buffer[len++] = '0' + digit;
709
710        buffer[ len++ ] = '\n';
711
712        write( 2, "Stray signal ", 13 );
713        write( 2, buffer, len );
714
715      }
716  }
717
718  /*
719   * If it was a "fatal" signal, then exit here
720   * If app code has installed a hander for one of these, then
721   * we won't call _CPU_Stray_signal, so this is ok.
722   */
723
724  switch (sig_num) {
725      case SIGINT:
726      case SIGHUP:
727      case SIGQUIT:
728      case SIGILL:
729#ifdef SIGEMT
730      case SIGEMT:
731#endif
732      case SIGKILL:
733      case SIGBUS:
734      case SIGSEGV:
735      case SIGTERM:
736      case SIGIOT:
737        _CPU_Fatal_error(0x100 + sig_num);
738  }
739}
740
741/*PAGE
742 *
743 *  _CPU_Fatal_error
744 */
745
746void _CPU_Fatal_error(unsigned32 error)
747{
748  setitimer(ITIMER_REAL, 0, 0);
749
750  if ( error ) {
751#ifdef RTEMS_DEBUG
752    abort();
753#endif
754    if (getenv("RTEMS_DEBUG"))
755      abort();
756  }
757
758  _exit(error);
759}
760
761/*
762 *  Special Purpose Routines to hide the use of UNIX system calls.
763 */
764
765int _CPU_Get_clock_vector( void )
766{
767  return SIGALRM;
768}
769
770void _CPU_Start_clock(
771  int microseconds
772)
773{
774  struct itimerval  new;
775
776  new.it_value.tv_sec = 0;
777  new.it_value.tv_usec = microseconds;
778  new.it_interval.tv_sec = 0;
779  new.it_interval.tv_usec = microseconds;
780
781  setitimer(ITIMER_REAL, &new, 0);
782}
783
784void _CPU_Stop_clock( void )
785{
786  struct itimerval  new;
787  struct sigaction  act;
788
789  /*
790   * Set the SIGALRM signal to ignore any last
791   * signals that might come in while we are
792   * disarming the timer and removing the interrupt
793   * vector.
794   */
795
796  (void) memset(&act, 0, sizeof(act));
797  act.sa_handler = SIG_IGN;
798
799  sigaction(SIGALRM, &act, 0);
800
801  (void) memset(&new, 0, sizeof(new));
802  setitimer(ITIMER_REAL, &new, 0);
803}
804
805int  _CPU_SHM_Semid;
806extern       void fix_syscall_errno( void );
807
808void _CPU_SHM_Init(
809  unsigned32   maximum_nodes,
810  boolean      is_master_node,
811  void       **shm_address,
812  unsigned32  *shm_length
813)
814{
815  int          i;
816  int          shmid;
817  char        *shm_addr;
818  key_t        shm_key;
819  key_t        sem_key;
820  int          status;
821  int          shm_size;
822
823  if (getenv("RTEMS_SHM_KEY"))
824    shm_key = strtol(getenv("RTEMS_SHM_KEY"), 0, 0);
825  else
826#ifdef RTEMS_SHM_KEY
827    shm_key = RTEMS_SHM_KEY;
828#else
829    shm_key = 0xa000;
830#endif
831
832    if (getenv("RTEMS_SHM_SIZE"))
833      shm_size = strtol(getenv("RTEMS_SHM_SIZE"), 0, 0);
834    else
835#ifdef RTEMS_SHM_SIZE
836      shm_size = RTEMS_SHM_SIZE;
837#else
838      shm_size = 64 * 1024;
839#endif
840
841    if (getenv("RTEMS_SHM_SEMAPHORE_KEY"))
842      sem_key = strtol(getenv("RTEMS_SHM_SEMAPHORE_KEY"), 0, 0);
843    else
844#ifdef RTEMS_SHM_SEMAPHORE_KEY
845      sem_key = RTEMS_SHM_SEMAPHORE_KEY;
846#else
847      sem_key = 0xa001;
848#endif
849
850    shmid = shmget(shm_key, shm_size, IPC_CREAT | 0660);
851    if ( shmid == -1 ) {
852      fix_syscall_errno(); /* in case of newlib */
853      perror( "shmget" );
854      _CPU_Fatal_halt( 0xdead0001 );
855    }
856
857    shm_addr = shmat(shmid, (char *)0, SHM_RND);
858    if ( shm_addr == (void *)-1 ) {
859      fix_syscall_errno(); /* in case of newlib */
860      perror( "shmat" );
861      _CPU_Fatal_halt( 0xdead0002 );
862    }
863
864    _CPU_SHM_Semid = semget(sem_key, maximum_nodes + 1, IPC_CREAT | 0660);
865    if ( _CPU_SHM_Semid == -1 ) {
866      fix_syscall_errno(); /* in case of newlib */
867      perror( "semget" );
868      _CPU_Fatal_halt( 0xdead0003 );
869    }
870
871    if ( is_master_node ) {
872      for ( i=0 ; i <= maximum_nodes ; i++ ) {
873#if defined(solaris2)
874        union semun {
875          int val;
876          struct semid_ds *buf;
877          ushort *array;
878        } help;
879
880        help.val = 1;
881        status = semctl( _CPU_SHM_Semid, i, SETVAL, help );
882#endif
883#if defined(hpux)
884        status = semctl( _CPU_SHM_Semid, i, SETVAL, 1 );
885#endif
886
887        fix_syscall_errno(); /* in case of newlib */
888        if ( status == -1 ) {
889          _CPU_Fatal_halt( 0xdead0004 );
890        }
891      }
892    }
893
894  *shm_address = shm_addr;
895  *shm_length = shm_size;
896
897}
898
899int _CPU_Get_pid( void )
900{
901  return getpid();
902}
903
904/*
905 * Define this to use signals for MPCI shared memory driver.
906 * If undefined, the shared memory driver will poll from the
907 * clock interrupt.
908 * Ref: ../shmsupp/getcfg.c
909 *
910 * BEWARE:: many UN*X kernels and debuggers become severely confused when
911 *          debugging programs which use signals.  The problem is *much*
912 *          worse when using multiple signals, since ptrace(2) tends to
913 *          drop all signals except 1 in the case of multiples.
914 *          On hpux9, this problem was so bad, we couldn't use interrupts
915 *          with the shared memory driver if we ever hoped to debug
916 *          RTEMS programs.
917 *          Maybe systems that use /proc don't have this problem...
918 */
919
920
921int _CPU_SHM_Get_vector( void )
922{
923#ifdef CPU_USE_SHM_INTERRUPTS
924  return SIGUSR1;
925#else
926  return 0;
927#endif
928}
929
930void _CPU_SHM_Send_interrupt(
931  int pid,
932  int vector
933)
934{
935  kill((pid_t) pid, vector);
936}
937
938void _CPU_SHM_Lock(
939  int semaphore
940)
941{
942  struct sembuf      sb;
943  int                status;
944
945  sb.sem_num = semaphore;
946  sb.sem_op  = -1;
947  sb.sem_flg = 0;
948
949  while (1) {
950    status = semop(_CPU_SHM_Semid, &sb, 1);
951    if ( status >= 0 )
952      break;
953    if ( status == -1 ) {
954       fix_syscall_errno();    /* in case of newlib */
955        if (errno == EINTR)
956            continue;
957        perror("shm lock");
958        _CPU_Fatal_halt( 0xdead0005 );
959    }
960  }
961
962}
963
964void _CPU_SHM_Unlock(
965  int semaphore
966)
967{
968  struct sembuf  sb;
969  int            status;
970
971  sb.sem_num = semaphore;
972  sb.sem_op  = 1;
973  sb.sem_flg = 0;
974
975  while (1) {
976    status = semop(_CPU_SHM_Semid, &sb, 1);
977    if ( status >= 0 )
978      break;
979
980    if ( status == -1 ) {
981      fix_syscall_errno();    /* in case of newlib */
982      if (errno == EINTR)
983          continue;
984      perror("shm unlock");
985      _CPU_Fatal_halt( 0xdead0006 );
986    }
987  }
988
989}
Note: See TracBrowser for help on using the repository browser.