source: rtems/cpukit/rtems/src/sem.c @ 7f6a24ab

4.104.114.84.95
Last change on this file since 7f6a24ab was 7f6a24ab, checked in by Joel Sherrill <joel.sherrill@…>, on 08/28/95 at 15:30:29

Added unused priority ceiling parameter to rtems_semaphore_create.

Rearranged code to created thread handler routines to initialize,
start, restart, and "close/delete" a thread.

Made internal threads their own object class. This now uses the
thread support routines for starting and initializing a thread.

Insured deleted tasks are freed to the Inactive pool associated with the
correct Information block.

Added an RTEMS API specific data area to the thread control block.

Beginnings of removing the word "rtems" from the core.

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 *  Semaphore Manager
3 *
4 *  DESCRIPTION:
5 *
6 *  This package is the implementation of the Semaphore Manager.
7 *  This manager utilizes standard Dijkstra counting semaphores to provide
8 *  synchronization and mutual exclusion capabilities.
9 *
10 *  Directives provided are:
11 *
12 *     + create a semaphore
13 *     + get an ID of a semaphore
14 *     + delete a semaphore
15 *     + acquire a semaphore
16 *     + release a semaphore
17 *
18 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
19 *  On-Line Applications Research Corporation (OAR).
20 *  All rights assigned to U.S. Government, 1994.
21 *
22 *  This material may be reproduced by or for the U.S. Government pursuant
23 *  to the copyright license under the clause at DFARS 252.227-7013.  This
24 *  notice must appear in all copies of this file and its derivatives.
25 *
26 *  $Id$
27 */
28
29#include <rtems/system.h>
30#include <rtems/support.h>
31#include <rtems/attr.h>
32#include <rtems/config.h>
33#include <rtems/isr.h>
34#include <rtems/object.h>
35#include <rtems/options.h>
36#include <rtems/sem.h>
37#include <rtems/states.h>
38#include <rtems/thread.h>
39#include <rtems/threadq.h>
40#include <rtems/mpci.h>
41
42/*PAGE
43 *
44 *  _Semaphore_Manager_initialization
45 *
46 *  This routine initializes all semaphore manager related data structures.
47 *
48 *  Input parameters:
49 *    maximum_semaphores - maximum configured semaphores
50 *
51 *  Output parameters:  NONE
52 */
53
54void _Semaphore_Manager_initialization(
55  unsigned32 maximum_semaphores
56)
57{
58  _Objects_Initialize_information(
59    &_Semaphore_Information,
60    OBJECTS_RTEMS_SEMAPHORES,
61    TRUE,
62    maximum_semaphores,
63    sizeof( Semaphore_Control ),
64    FALSE,
65    RTEMS_MAXIMUM_NAME_LENGTH,
66    FALSE
67  );
68}
69
70/*PAGE
71 *
72 *  rtems_semaphore_create
73 *
74 *  This directive creates a semaphore and sets the initial value based
75 *  on the given count.  A semaphore id is returned.
76 *
77 *  Input parameters:
78 *    name          - user defined semaphore name
79 *    count         - initial count of semaphore
80 *    attribute_set - semaphore attributes
81 *    id            - pointer to semaphore id
82 *
83 *  Output parameters:
84 *    id       - semaphore id
85 *    RTEMS_SUCCESSFUL - if successful
86 *    error code - if unsuccessful
87 */
88
89rtems_status_code rtems_semaphore_create(
90  rtems_name            name,
91  unsigned32            count,
92  rtems_attribute       attribute_set,
93  rtems_task_priority   priority_ceiling,
94  Objects_Id           *id
95)
96{
97  register Semaphore_Control *the_semaphore;
98
99  if ( !rtems_is_name_valid( name ) )
100    return ( RTEMS_INVALID_NAME );
101
102  if ( _Attributes_Is_global( attribute_set ) ) {
103
104    if ( !_Configuration_Is_multiprocessing() )
105      return( RTEMS_MP_NOT_CONFIGURED );
106
107    if ( _Attributes_Is_inherit_priority( attribute_set ) )
108      return( RTEMS_NOT_DEFINED );
109
110  } else if ( _Attributes_Is_inherit_priority( attribute_set ) ) {
111
112    if ( ! ( _Attributes_Is_binary_semaphore( attribute_set ) &&
113             _Attributes_Is_priority( attribute_set ) ) )
114      return( RTEMS_NOT_DEFINED );
115
116  }
117
118  if ( _Attributes_Is_binary_semaphore( attribute_set ) && ( count > 1 ) )
119    return( RTEMS_INVALID_NUMBER );
120
121  _Thread_Disable_dispatch();             /* prevents deletion */
122
123  the_semaphore = _Semaphore_Allocate();
124
125  if ( !the_semaphore ) {
126    _Thread_Enable_dispatch();
127    return( RTEMS_TOO_MANY );
128  }
129
130  if ( _Attributes_Is_global( attribute_set ) &&
131       !( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
132                            the_semaphore->Object.id, FALSE ) ) ) {
133    _Semaphore_Free( the_semaphore );
134    _Thread_Enable_dispatch();
135    return( RTEMS_TOO_MANY );
136  }
137
138  the_semaphore->attribute_set = attribute_set;
139  the_semaphore->count         = count;
140
141  if ( _Attributes_Is_binary_semaphore( attribute_set ) && count == 0 ) {
142    the_semaphore->nest_count = 1;
143    the_semaphore->holder     = _Thread_Executing;
144    the_semaphore->holder_id  = _Thread_Executing->Object.id;
145    _Thread_Executing->resource_count++;
146  } else {
147    the_semaphore->nest_count = 0;
148    the_semaphore->holder     = NULL;
149    the_semaphore->holder_id  = 0;
150  }
151
152  _Thread_queue_Initialize(
153    &the_semaphore->Wait_queue,
154    OBJECTS_RTEMS_SEMAPHORES,
155    _Attributes_Is_priority( attribute_set ) ?
156       THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
157    STATES_WAITING_FOR_SEMAPHORE,
158    _Semaphore_MP_Send_extract_proxy
159  );
160
161  _Objects_Open( &_Semaphore_Information, &the_semaphore->Object, &name );
162
163  *id = the_semaphore->Object.id;
164
165  if ( _Attributes_Is_global( attribute_set ) )
166    _Semaphore_MP_Send_process_packet(
167      SEMAPHORE_MP_ANNOUNCE_CREATE,
168      the_semaphore->Object.id,
169      name,
170      0                          /* Not used */
171    );
172  _Thread_Enable_dispatch();
173  return( RTEMS_SUCCESSFUL );
174}
175
176/*PAGE
177 *
178 *  rtems_semaphore_ident
179 *
180 *  This directive returns the system ID associated with
181 *  the semaphore name.
182 *
183 *  Input parameters:
184 *    name - user defined semaphore name
185 *    node - node(s) to be searched
186 *    id   - pointer to semaphore id
187 *
188 *  Output parameters:
189 *    *id      - semaphore id
190 *    RTEMS_SUCCESSFUL - if successful
191 *    error code - if unsuccessful
192 */
193
194rtems_status_code rtems_semaphore_ident(
195  rtems_name    name,
196  unsigned32    node,
197  Objects_Id   *id
198)
199{
200  return( _Objects_Name_to_id( &_Semaphore_Information, &name, node, id ) );
201}
202
203/*PAGE
204 *
205 *  rtems_semaphore_delete
206 *
207 *  This directive allows a thread to delete a semaphore specified by
208 *  the semaphore id.  The semaphore is freed back to the inactive
209 *  semaphore chain.
210 *
211 *  Input parameters:
212 *    id - semaphore id
213 *
214 *  Output parameters:
215 *    RTEMS_SUCCESSFUL - if successful
216 *    error code        - if unsuccessful
217 */
218
219rtems_status_code rtems_semaphore_delete(
220  Objects_Id id
221)
222{
223  register Semaphore_Control *the_semaphore;
224  Objects_Locations           location;
225
226  the_semaphore = _Semaphore_Get( id, &location );
227  switch ( location ) {
228    case OBJECTS_ERROR:
229      return( RTEMS_INVALID_ID );
230    case OBJECTS_REMOTE:
231      _Thread_Dispatch();
232      return( RTEMS_ILLEGAL_ON_REMOTE_OBJECT );
233    case OBJECTS_LOCAL:
234      if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set) &&
235                       ( the_semaphore->count == 0 ) ) {
236        _Thread_Enable_dispatch();
237        return( RTEMS_RESOURCE_IN_USE );
238      }
239
240      _Objects_Close( &_Semaphore_Information, &the_semaphore->Object );
241
242      _Thread_queue_Flush(
243        &the_semaphore->Wait_queue,
244        _Semaphore_MP_Send_object_was_deleted
245      );
246
247      _Semaphore_Free( the_semaphore );
248
249      if ( _Attributes_Is_global( the_semaphore->attribute_set ) ) {
250
251        _Objects_MP_Close( &_Semaphore_Information, the_semaphore->Object.id );
252
253        _Semaphore_MP_Send_process_packet(
254          SEMAPHORE_MP_ANNOUNCE_DELETE,
255          the_semaphore->Object.id,
256          0,                         /* Not used */
257          0                          /* Not used */
258        );
259      }
260      _Thread_Enable_dispatch();
261      return( RTEMS_SUCCESSFUL );
262  }
263
264  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
265}
266
267/*PAGE
268 *
269 *  rtems_semaphore_obtain
270 *
271 *  This directive allows a thread to acquire a semaphore.
272 *
273 *  Input parameters:
274 *    id         - semaphore id
275 *    option_set - wait option
276 *    timeout    - number of ticks to wait (0 means wait forever)
277 *
278 *  Output parameters:
279 *    RTEMS_SUCCESSFUL - if successful
280 *    error code        - if unsuccessful
281 */
282
283rtems_status_code rtems_semaphore_obtain(
284  Objects_Id        id,
285  unsigned32        option_set,
286  rtems_interval timeout
287)
288{
289  register Semaphore_Control *the_semaphore;
290  Objects_Locations           location;
291
292  the_semaphore = _Semaphore_Get( id, &location );
293  switch ( location ) {
294    case OBJECTS_ERROR:
295      return( RTEMS_INVALID_ID );
296    case OBJECTS_REMOTE:
297      return _Semaphore_MP_Send_request_packet(
298          SEMAPHORE_MP_OBTAIN_REQUEST,
299          id,
300          option_set,
301          timeout
302      );
303    case OBJECTS_LOCAL:
304      if ( !_Semaphore_Seize( the_semaphore, option_set ) ) {
305        if ( _Attributes_Is_inherit_priority( the_semaphore->attribute_set ) &&
306             the_semaphore->holder->current_priority >
307               _Thread_Executing->current_priority ) {
308            _Thread_Change_priority(
309              the_semaphore->holder, _Thread_Executing->current_priority );
310         }
311        _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
312      }
313      _Thread_Enable_dispatch();
314      return( _Thread_Executing->Wait.return_code );
315  }
316
317  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
318}
319
320/*PAGE
321 *
322 *  rtems_semaphore_release
323 *
324 *  This directive allows a thread to release a semaphore.
325 *
326 *  Input parameters:
327 *    id - semaphore id
328 *
329 *  Output parameters:
330 *    RTEMS_SUCCESSFUL - if successful
331 *    error code        - if unsuccessful
332 */
333
334rtems_status_code rtems_semaphore_release(
335  Objects_Id id
336)
337{
338  register Semaphore_Control *the_semaphore;
339  Objects_Locations           location;
340  Thread_Control             *the_thread;
341
342  the_semaphore = _Semaphore_Get( id, &location );
343  switch ( location ) {
344    case OBJECTS_ERROR:
345      return( RTEMS_INVALID_ID );
346    case OBJECTS_REMOTE:
347      return(
348        _Semaphore_MP_Send_request_packet(
349          SEMAPHORE_MP_RELEASE_REQUEST,
350          id,
351          0,                               /* Not used */
352          MPCI_DEFAULT_TIMEOUT
353        )
354      );
355    case OBJECTS_LOCAL:
356      if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set)) {
357
358        if ( !_Objects_Are_ids_equal(
359               _Thread_Executing->Object.id, the_semaphore->holder_id ) ) {
360          _Thread_Enable_dispatch();
361          return( RTEMS_NOT_OWNER_OF_RESOURCE );
362        }
363
364        the_semaphore->nest_count--;
365
366        if ( the_semaphore->nest_count != 0 ) {
367          _Thread_Enable_dispatch();
368          return( RTEMS_SUCCESSFUL );
369        }
370
371        _Thread_Executing->resource_count--;
372        the_semaphore->holder    = NULL;
373        the_semaphore->holder_id = 0;
374
375        /*
376         *  Whether or not someone is waiting for the semaphore, an
377         *  inherited priority must be lowered if this is the last
378         *  semaphore (i.e. resource) this task has.
379         */
380
381        if ( _Attributes_Is_inherit_priority(the_semaphore->attribute_set) &&
382             _Thread_Executing->resource_count == 0 &&
383             _Thread_Executing->real_priority !=
384                _Thread_Executing->current_priority ) {
385           _Thread_Change_priority(
386              _Thread_Executing, _Thread_Executing->real_priority );
387        }
388
389      }
390
391      if ( (the_thread = _Thread_queue_Dequeue(&the_semaphore->Wait_queue)) ) {
392
393        if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
394          the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
395
396          if ( _Attributes_Is_binary_semaphore(the_semaphore->attribute_set) ) {
397            the_semaphore->holder    = NULL;
398            the_semaphore->holder_id = the_thread->Object.id;
399            the_semaphore->nest_count = 1;
400          }
401
402          _Semaphore_MP_Send_response_packet(
403            SEMAPHORE_MP_OBTAIN_RESPONSE,
404            id,
405            the_thread
406          );
407        } else {
408
409          if ( _Attributes_Is_binary_semaphore(the_semaphore->attribute_set) ) {
410            the_semaphore->holder    = the_thread;
411            the_semaphore->holder_id = the_thread->Object.id;
412            the_thread->resource_count++;
413            the_semaphore->nest_count = 1;
414          }
415
416          /*
417           *  No special action for priority inheritance because the_thread
418           *  is guaranteed to be the highest priority thread waiting for
419           *  the semaphore.
420           */
421        }
422      } else
423        the_semaphore->count += 1;
424
425      _Thread_Enable_dispatch();
426      return( RTEMS_SUCCESSFUL );
427  }
428
429  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
430}
431
432/*PAGE
433 *
434 *  _Semaphore_Seize
435 *
436 *  This routine attempts to allocate a semaphore to the calling thread.
437 *
438 *  Input parameters:
439 *    the_semaphore - pointer to semaphore control block
440 *    option_set    - acquire semaphore options
441 *
442 *  Output parameters:
443 *    TRUE  - if semaphore allocated
444 *    FALSE - if semaphore NOT allocated
445 *
446 *  INTERRUPT LATENCY:
447 *    available
448 *    wait
449 */
450
451boolean _Semaphore_Seize(
452  Semaphore_Control *the_semaphore,
453  rtems_option    option_set
454)
455{
456  Thread_Control *executing;
457  ISR_Level       level;
458
459  executing = _Thread_Executing;
460  executing->Wait.return_code = RTEMS_SUCCESSFUL;
461  _ISR_Disable( level );
462  if ( the_semaphore->count != 0 ) {
463    the_semaphore->count -= 1;
464    if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
465      the_semaphore->holder     = executing;
466      the_semaphore->holder_id  = executing->Object.id;
467      the_semaphore->nest_count = 1;
468      executing->resource_count++;
469    }
470    _ISR_Enable( level );
471    return( TRUE );
472  }
473
474  if ( _Options_Is_no_wait( option_set ) ) {
475    _ISR_Enable( level );
476    executing->Wait.return_code = RTEMS_UNSATISFIED;
477    return( TRUE );
478  }
479
480  if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
481    if ( _Objects_Are_ids_equal(
482            _Thread_Executing->Object.id, the_semaphore->holder_id ) ) {
483      the_semaphore->nest_count++;
484      _ISR_Enable( level );
485      return( TRUE );
486    }
487  }
488
489  the_semaphore->Wait_queue.sync = TRUE;
490  executing->Wait.queue      = &the_semaphore->Wait_queue;
491  executing->Wait.id         = the_semaphore->Object.id;
492  executing->Wait.option_set = option_set;
493  _ISR_Enable( level );
494  return( FALSE );
495}
Note: See TracBrowser for help on using the repository browser.