OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [exec/] [score/] [cpu/] [unix/] [cpu.c] - Blame information for rev 778

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.