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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [exec/] [posix/] [src/] [killinfo.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
2
 *  kill() support routine
3
 *
4
 *  COPYRIGHT (c) 1989-1999.
5
 *  On-Line Applications Research Corporation (OAR).
6
 *
7
 *  The license and distribution terms for this file may be
8
 *  found in the file LICENSE in this distribution or at
9
 *  http://www.OARcorp.com/rtems/license.html.
10
 *
11 208 chris
 *  $Id: killinfo.c,v 1.2 2001-09-27 11:59:17 chris Exp $
12 158 chris
 */
13
 
14
 
15
#include <pthread.h>
16
#include <signal.h>
17
#include <errno.h>
18
#include <assert.h>
19
 
20
#include <rtems/system.h>
21
#include <rtems/posix/pthread.h>
22
#include <rtems/posix/psignal.h>
23
#include <rtems/posix/seterr.h>
24
#include <rtems/score/isr.h>
25
 
26
/*PAGE
27
 *
28
 *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
29
 *
30
 *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
31
 */
32
 
33
#define _POSIX_signals_Is_interested( _api, _mask ) \
34
  ( ~(_api)->signals_blocked & (_mask) )
35
 
36
int killinfo(
37
  pid_t               pid,
38
  int                 sig,
39
  const union sigval *value
40
)
41
{
42
  sigset_t                     mask;
43
  POSIX_API_Control           *api;
44
  unsigned32                   the_class;
45
  unsigned32                   index;
46
  unsigned32                   maximum;
47
  Objects_Information         *the_info;
48
  Objects_Control            **object_table;
49
  Thread_Control              *the_thread;
50
  Thread_Control              *interested_thread;
51
  Priority_Control             interested_priority;
52
  Chain_Control               *the_chain;
53
  Chain_Node                  *the_node;
54
  siginfo_t                    siginfo_struct;
55
  siginfo_t                   *siginfo;
56
  POSIX_signals_Siginfo_node  *psiginfo;
57
 
58
  /*
59
   *  Only supported for the "calling process" (i.e. this node).
60
   */
61
 
62
  if ( pid != getpid() )
63
    set_errno_and_return_minus_one( ESRCH );
64
 
65
  /*
66
   *  Validate the signal passed if not 0.
67
   */
68
 
69
  if ( sig && !is_valid_signo(sig) ) {
70
    set_errno_and_return_minus_one( EINVAL );
71
  }
72
 
73
  /*
74
   *  If the signal is being ignored, then we are out of here.
75
   */
76
 
77
  if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
78
    return 0;
79
  }
80
 
81
  /*
82
   *  P1003.1c/Draft 10, p. 33 says that certain signals should always
83
   *  be directed to the executing thread such as those caused by hardware
84
   *  faults.
85
   */
86
 
87
  switch ( sig ) {
88
    case SIGFPE:
89
    case SIGILL:
90
    case SIGSEGV:
91
      return pthread_kill( pthread_self(), sig );
92
    default:
93
      break;
94
  }
95
 
96
  mask = signo_to_mask( sig );
97
 
98
  /*
99
   *  Build up a siginfo structure
100
   */
101
 
102
  siginfo = &siginfo_struct;
103
  siginfo->si_signo = sig;
104
  siginfo->si_code = SI_USER;
105
  if ( !value ) {
106
    siginfo->si_value.sival_int = 0;
107
  } else {
108
    siginfo->si_value = *value;
109
  }
110
 
111
  _Thread_Disable_dispatch();
112
 
113
  /*
114
   *  Is the currently executing thread interested?  If so then it will
115
   *  get it an execute it as soon as the dispatcher executes.
116
   */
117
 
118
  the_thread = _Thread_Executing;
119
 
120
  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
121
  if ( _POSIX_signals_Is_interested( api, mask ) ) {
122
    goto process_it;
123
  }
124
 
125
  /*
126
   *  Is an interested thread waiting for this signal (sigwait())?
127
   */
128
 
129
  /* XXX violation of visibility -- need to define thread queue support */
130
 
131
  for( index=0 ;
132
       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
133
       index++ ) {
134
 
135
    the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];
136
 
137
    for ( the_node = the_chain->first ;
138
          !_Chain_Is_tail( the_chain, the_node ) ;
139
          the_node = the_node->next ) {
140
 
141
      the_thread = (Thread_Control *)the_node;
142
      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
143
 
144
      if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {
145
        goto process_it;
146
      }
147
 
148
    }
149
  }
150
 
151
  /*
152
   *  Is any other thread interested?  The highest priority interested
153
   *  thread is selected.  In the event of a tie, then the following
154
   *  additional criteria is used:
155
   *
156
   *    + ready thread over blocked
157
   *    + blocked on call interruptible by signal (can return EINTR)
158
   *    + blocked on call not interruptible by signal
159
   *
160
   *  This looks at every thread in the system regardless of the creating API.
161
   *
162
   *  NOTES:
163
   *
164
   *    + rtems internal threads do not receive signals.
165
   */
166
 
167
  interested_thread = NULL;
168
  interested_priority = PRIORITY_MAXIMUM + 1;
169
 
170
  for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
171
        the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
172
        the_class++ ) {
173
 
174
    if ( the_class == OBJECTS_INTERNAL_THREADS )
175
      continue;
176
 
177
    the_info = _Objects_Information_table[ the_class ];
178
 
179
    if ( !the_info )                        /* manager not installed */
180
      continue;
181
 
182
    maximum = the_info->maximum;
183
    object_table = the_info->local_table;
184
 
185
    assert( object_table );                 /* always at least 1 entry */
186
 
187
    for ( index = 1 ; index <= maximum ; index++ ) {
188
      the_thread = (Thread_Control *) object_table[ index ];
189
 
190
      if ( !the_thread )
191
        continue;
192
 
193
      /*
194
       *  If this thread is of lower priority than the interested thread,
195
       *  go on to the next thread.
196
       */
197
 
198
      if ( the_thread->current_priority > interested_priority )
199
        continue;
200
 
201
      /*
202
       *  If this thread is not interested, then go on to the next thread.
203
       */
204
 
205
      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
206
 
207
      if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
208
        continue;
209
 
210
      /*
211
       *  Now we know the thread under connsideration is interested.
212
       *  If the thread under consideration is of higher priority, then
213
       *  it becomes the interested thread.
214
       */
215
 
216
      if ( the_thread->current_priority < interested_priority ) {
217
        interested_thread   = the_thread;
218
        interested_priority = the_thread->current_priority;
219
        continue;
220
      }
221
 
222
      /*
223
       *  Now the thread and the interested thread have the same priority.
224
       *  If the interested thread is ready, then we don't need to send it
225
       *  to a blocked thread.
226
       */
227
 
228
      if ( _States_Is_ready( interested_thread->current_state ) )
229
        continue;
230
 
231
      /*
232
       *  Now the interested thread is blocked.
233
       *  If the thread we are considering is not, the it becomes the
234
       *  interested thread.
235
       */
236
 
237
      if ( _States_Is_ready( the_thread->current_state ) ) {
238
        interested_thread   = the_thread;
239
        interested_priority = the_thread->current_priority;
240
        continue;
241
      }
242
 
243
      /*
244
       *  Now we know both threads are blocked.
245
       *  If the interested thread is interruptible, then just use it.
246
       */
247
 
248
      /* XXX need a new states macro */
249
      if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
250
        continue;
251
 
252
      /*
253
       *  Now both threads are blocked and the interested thread is not
254
       *  interruptible.
255
       *  If the thread under consideration is interruptible by a signal,
256
       *  then it becomes the interested thread.
257
       */
258
 
259
      /* XXX need a new states macro */
260
      if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
261
        interested_thread   = the_thread;
262
        interested_priority = the_thread->current_priority;
263
      }
264
    }
265
  }
266
 
267
  if ( interested_thread ) {
268
    the_thread = interested_thread;
269
    goto process_it;
270
  }
271
 
272
  /*
273
   *  OK so no threads were interested right now.  It will be left on the
274
   *  global pending until a thread receives it.  The global set of threads
275
   *  can change interest in this signal in one of the following ways:
276
   *
277
   *    + a thread is created with the signal unblocked,
278
   *    + pthread_sigmask() unblocks the signal,
279
   *    + sigprocmask() unblocks the signal, OR
280
   *    + sigaction() which changes the handler to SIG_IGN.
281
   */
282
 
283
  the_thread = NULL;
284
  goto post_process_signal;
285
 
286
  /*
287
   *  We found a thread which was interested, so now we mark that this
288
   *  thread needs to do the post context switch extension so it can
289
   *  evaluate the signals pending.
290
   */
291
 
292
process_it:
293
 
294
  the_thread->do_post_task_switch_extension = TRUE;
295
 
296
  /*
297
   *  Returns TRUE if the signal was synchronously given to a thread
298
   *  blocked waiting for the signal.
299
   */
300
 
301
  if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
302
    _Thread_Enable_dispatch();
303
    return 0;
304
  }
305
 
306
post_process_signal:
307
 
308
  /*
309
   *  We may have woken up a thread but we definitely need to post the
310
   *  signal to the process wide information set.
311
   */
312
 
313
  _POSIX_signals_Set_process_signals( mask );
314
 
315
  if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
316
 
317
    psiginfo = (POSIX_signals_Siginfo_node *)
318
               _Chain_Get( &_POSIX_signals_Inactive_siginfo );
319
    if ( !psiginfo ) {
320
      set_errno_and_return_minus_one( EAGAIN );
321
    }
322
 
323
    psiginfo->Info = *siginfo;
324
 
325
    _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
326
  }
327
 
328
  _Thread_Enable_dispatch();
329
  return 0;
330
}

powered by: WebSVN 2.1.0

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