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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [score/] [cpu/] [unix/] [cpu.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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