source: rtems/cpukit/include/rtems/posix/muteximpl.h @ 21275b58

5
Last change on this file since 21275b58 was 2afb22b, checked in by Chris Johns <chrisj@…>, on 12/23/17 at 07:18:56

Remove make preinstall

A speciality of the RTEMS build system was the make preinstall step. It
copied header files from arbitrary locations into the build tree. The
header files were included via the -Bsome/build/tree/path GCC command
line option.

This has at least seven problems:

  • The make preinstall step itself needs time and disk space.
  • Errors in header files show up in the build tree copy. This makes it hard for editors to open the right file to fix the error.
  • There is no clear relationship between source and build tree header files. This makes an audit of the build process difficult.
  • The visibility of all header files in the build tree makes it difficult to enforce API barriers. For example it is discouraged to use BSP-specifics in the cpukit.
  • An introduction of a new build system is difficult.
  • Include paths specified by the -B option are system headers. This may suppress warnings.
  • The parallel build had sporadic failures on some hosts.

This patch removes the make preinstall step. All installed header
files are moved to dedicated include directories in the source tree.
Let @RTEMS_CPU@ be the target architecture, e.g. arm, powerpc, sparc,
etc. Let @RTEMS_BSP_FAMILIY@ be a BSP family base directory, e.g.
erc32, imx, qoriq, etc.

The new cpukit include directories are:

  • cpukit/include
  • cpukit/score/cpu/@RTEMS_CPU@/include
  • cpukit/libnetworking

The new BSP include directories are:

  • bsps/include
  • bsps/@RTEMS_CPU@/include
  • bsps/@RTEMS_CPU@/@RTEMS_BSP_FAMILIY@/include

There are build tree include directories for generated files.

The include directory order favours the most general header file, e.g.
it is not possible to override general header files via the include path
order.

The "bootstrap -p" option was removed. The new "bootstrap -H" option
should be used to regenerate the "headers.am" files.

Update #3254.

  • Property mode set to 100644
File size: 11.9 KB
Line 
1/**
2 * @file
3 *
4 * @brief Private Inlined Routines for POSIX Mutex's.
5 *
6 * This include file contains the static inline implementation of the private
7 * inlined routines for POSIX mutex's.
8 */
9
10/*  COPYRIGHT (c) 1989-2013.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#ifndef _RTEMS_POSIX_MUTEXIMPL_H
19#define _RTEMS_POSIX_MUTEXIMPL_H
20
21#include <errno.h>
22#include <pthread.h>
23
24#include <rtems/score/percpu.h>
25#include <rtems/score/muteximpl.h>
26#include <rtems/score/threadimpl.h>
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32typedef struct {
33  unsigned long flags;
34  Mutex_recursive_Control Recursive;
35  Priority_Node Priority_ceiling;
36  const Scheduler_Control *scheduler;
37} POSIX_Mutex_Control;
38
39#define POSIX_MUTEX_PROTOCOL_MASK 0x3UL
40
41#define POSIX_MUTEX_RECURSIVE 0x4UL
42
43#define POSIX_MUTEX_FLAGS_MASK 0x7UL
44
45#define POSIX_MUTEX_MAGIC 0x961c13b8UL
46
47#define POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
48
49#define POSIX_MUTEX_PRIORITY_INHERIT_TQ_OPERATIONS \
50  &_Thread_queue_Operations_priority_inherit
51
52#define POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS \
53  &_Thread_queue_Operations_priority
54
55/**
56 * @brief Supported POSIX mutex protocols.
57 *
58 * Must be in synchronization with POSIX_Mutex_Control::protocol.
59 */
60typedef enum {
61  POSIX_MUTEX_NO_PROTOCOL,
62  POSIX_MUTEX_PRIORITY_INHERIT,
63  POSIX_MUTEX_PRIORITY_CEILING
64} POSIX_Mutex_Protocol;
65
66/**
67 *  The default mutex attributes structure.
68 */
69extern const pthread_mutexattr_t _POSIX_Mutex_Default_attributes;
70
71RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Mutex_Acquire(
72  POSIX_Mutex_Control  *the_mutex,
73  Thread_queue_Context *queue_context
74)
75{
76  ISR_Level       level;
77  Thread_Control *executing;
78
79  _Thread_queue_Context_initialize( queue_context );
80  _Thread_queue_Context_ISR_disable( queue_context, level );
81  _Thread_queue_Context_set_ISR_level( queue_context, level );
82  executing = _Thread_Executing;
83  _Thread_queue_Queue_acquire_critical(
84    &the_mutex->Recursive.Mutex.Queue.Queue,
85    &executing->Potpourri_stats,
86    &queue_context->Lock_context.Lock_context
87  );
88
89  return executing;
90}
91
92RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Release(
93  POSIX_Mutex_Control  *the_mutex,
94  Thread_queue_Context *queue_context
95)
96{
97  _Thread_queue_Queue_release(
98    &the_mutex->Recursive.Mutex.Queue.Queue,
99    &queue_context->Lock_context.Lock_context
100  );
101}
102
103RTEMS_INLINE_ROUTINE POSIX_Mutex_Protocol _POSIX_Mutex_Get_protocol(
104  unsigned long flags
105)
106{
107  return flags & POSIX_MUTEX_PROTOCOL_MASK;
108}
109
110RTEMS_INLINE_ROUTINE bool _POSIX_Mutex_Is_recursive(
111  unsigned long flags
112)
113{
114  return ( flags & POSIX_MUTEX_RECURSIVE ) != 0;
115}
116
117RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Mutex_Get_owner(
118  const POSIX_Mutex_Control *the_mutex
119)
120{
121  return the_mutex->Recursive.Mutex.Queue.Queue.owner;
122}
123
124RTEMS_INLINE_ROUTINE bool _POSIX_Mutex_Is_locked(
125  const POSIX_Mutex_Control *the_mutex
126)
127{
128  return _POSIX_Mutex_Get_owner( the_mutex ) != NULL;
129}
130
131Status_Control _POSIX_Mutex_Seize_slow(
132  POSIX_Mutex_Control           *the_mutex,
133  const Thread_queue_Operations *operations,
134  Thread_Control                *executing,
135  const struct timespec         *abstime,
136  Thread_queue_Context          *queue_context
137);
138
139RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Set_owner(
140  POSIX_Mutex_Control *the_mutex,
141  Thread_Control      *owner
142)
143{
144  the_mutex->Recursive.Mutex.Queue.Queue.owner = owner;
145}
146
147RTEMS_INLINE_ROUTINE bool _POSIX_Mutex_Is_owner(
148  const POSIX_Mutex_Control *the_mutex,
149  const Thread_Control      *the_thread
150)
151{
152  return _POSIX_Mutex_Get_owner( the_mutex ) == the_thread;
153}
154
155static Status_Control _POSIX_Mutex_Lock_nested(
156  POSIX_Mutex_Control *the_mutex,
157  unsigned long        flags
158)
159{
160
161  if ( _POSIX_Mutex_Is_recursive( flags ) ) {
162    ++the_mutex->Recursive.nest_level;
163    return STATUS_SUCCESSFUL;
164  } else {
165    return STATUS_NESTING_NOT_ALLOWED;
166  }
167}
168
169RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Seize(
170  POSIX_Mutex_Control           *the_mutex,
171  unsigned long                  flags,
172  const Thread_queue_Operations *operations,
173  Thread_Control                *executing,
174  const struct timespec         *abstime,
175  Thread_queue_Context          *queue_context
176)
177{
178  Thread_Control *owner;
179
180  owner = _POSIX_Mutex_Get_owner( the_mutex );
181
182  if ( owner == NULL ) {
183    _POSIX_Mutex_Set_owner( the_mutex, executing );
184    _Thread_Resource_count_increment( executing );
185    _POSIX_Mutex_Release( the_mutex, queue_context );
186    return STATUS_SUCCESSFUL;
187  }
188
189  if ( owner == executing ) {
190    Status_Control status;
191
192    status = _POSIX_Mutex_Lock_nested( the_mutex, flags );
193    _POSIX_Mutex_Release( the_mutex, queue_context );
194    return status;
195  }
196
197  return _POSIX_Mutex_Seize_slow(
198    the_mutex,
199    operations,
200    executing,
201    abstime,
202    queue_context
203  );
204}
205
206RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Surrender(
207  POSIX_Mutex_Control           *the_mutex,
208  const Thread_queue_Operations *operations,
209  Thread_Control                *executing,
210  Thread_queue_Context          *queue_context
211)
212{
213  unsigned int        nest_level;
214  Thread_queue_Heads *heads;
215
216  if ( !_POSIX_Mutex_Is_owner( the_mutex, executing ) ) {
217    _POSIX_Mutex_Release( the_mutex, queue_context );
218    return STATUS_NOT_OWNER;
219  }
220
221  nest_level = the_mutex->Recursive.nest_level;
222
223  if ( nest_level > 0 ) {
224    the_mutex->Recursive.nest_level = nest_level - 1;
225    _POSIX_Mutex_Release( the_mutex, queue_context );
226    return STATUS_SUCCESSFUL;
227  }
228
229  _Thread_Resource_count_decrement( executing );
230  _POSIX_Mutex_Set_owner( the_mutex, NULL );
231
232  heads = the_mutex->Recursive.Mutex.Queue.Queue.heads;
233
234  if ( heads == NULL ) {
235    _POSIX_Mutex_Release( the_mutex, queue_context );
236    return STATUS_SUCCESSFUL;
237  }
238
239  _Thread_queue_Surrender(
240    &the_mutex->Recursive.Mutex.Queue.Queue,
241    heads,
242    executing,
243    queue_context,
244    operations
245  );
246  return STATUS_SUCCESSFUL;
247}
248
249RTEMS_INLINE_ROUTINE const Scheduler_Control *_POSIX_Mutex_Get_scheduler(
250  const POSIX_Mutex_Control *the_mutex
251)
252{
253#if defined(RTEMS_SMP)
254  return the_mutex->scheduler;
255#else
256  return &_Scheduler_Table[ 0 ];
257#endif
258}
259
260RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Set_priority(
261  POSIX_Mutex_Control  *the_mutex,
262  Priority_Control      priority_ceiling,
263  Thread_queue_Context *queue_context
264)
265{
266  Thread_Control *owner;
267
268  owner = _POSIX_Mutex_Get_owner( the_mutex );
269
270  if ( owner != NULL ) {
271    _Thread_Wait_acquire( owner, queue_context );
272    _Thread_Priority_change(
273      owner,
274      &the_mutex->Priority_ceiling,
275      priority_ceiling,
276      false,
277      queue_context
278    );
279    _Thread_Wait_release( owner, queue_context );
280  } else {
281    the_mutex->Priority_ceiling.priority = priority_ceiling;
282  }
283}
284
285RTEMS_INLINE_ROUTINE Priority_Control _POSIX_Mutex_Get_priority(
286  const POSIX_Mutex_Control *the_mutex
287)
288{
289  return the_mutex->Priority_ceiling.priority;
290}
291
292RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_set_owner(
293  POSIX_Mutex_Control  *the_mutex,
294  Thread_Control       *owner,
295  Thread_queue_Context *queue_context
296)
297{
298  ISR_lock_Context  lock_context;
299  Scheduler_Node   *scheduler_node;
300  Per_CPU_Control  *cpu_self;
301
302  _Thread_Wait_acquire_default_critical( owner, &lock_context );
303
304  scheduler_node = _Thread_Scheduler_get_home_node( owner );
305
306  if (
307    _Priority_Get_priority( &scheduler_node->Wait.Priority )
308      < the_mutex->Priority_ceiling.priority
309  ) {
310    _Thread_Wait_release_default_critical( owner, &lock_context );
311    _POSIX_Mutex_Release( the_mutex, queue_context );
312    return STATUS_MUTEX_CEILING_VIOLATED;
313  }
314
315  _POSIX_Mutex_Set_owner( the_mutex, owner );
316  _Thread_Resource_count_increment( owner );
317  _Thread_Priority_add(
318    owner,
319    &the_mutex->Priority_ceiling,
320    queue_context
321  );
322  _Thread_Wait_release_default_critical( owner, &lock_context );
323
324  cpu_self = _Thread_queue_Dispatch_disable( queue_context );
325  _POSIX_Mutex_Release( the_mutex, queue_context );
326  _Thread_Priority_update( queue_context );
327  _Thread_Dispatch_enable( cpu_self );
328  return STATUS_SUCCESSFUL;
329}
330
331RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_seize(
332  POSIX_Mutex_Control   *the_mutex,
333  unsigned long          flags,
334  Thread_Control        *executing,
335  const struct timespec *abstime,
336  Thread_queue_Context  *queue_context
337)
338{
339  Thread_Control *owner;
340
341  owner = _POSIX_Mutex_Get_owner( the_mutex );
342
343  if ( owner == NULL ) {
344#if defined(RTEMS_SMP)
345    if (
346      _Thread_Scheduler_get_home( executing )
347        != _POSIX_Mutex_Get_scheduler( the_mutex )
348    ) {
349      _POSIX_Mutex_Release( the_mutex, queue_context );
350      return STATUS_NOT_DEFINED;
351    }
352#endif
353
354    _Thread_queue_Context_clear_priority_updates( queue_context );
355    return _POSIX_Mutex_Ceiling_set_owner(
356      the_mutex,
357      executing,
358      queue_context
359    );
360  }
361
362  if ( owner == executing ) {
363    Status_Control status;
364
365    status = _POSIX_Mutex_Lock_nested( the_mutex, flags );
366    _POSIX_Mutex_Release( the_mutex, queue_context );
367    return status;
368  }
369
370  return _POSIX_Mutex_Seize_slow(
371    the_mutex,
372    POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS,
373    executing,
374    abstime,
375    queue_context
376  );
377}
378
379RTEMS_INLINE_ROUTINE Status_Control _POSIX_Mutex_Ceiling_surrender(
380  POSIX_Mutex_Control  *the_mutex,
381  Thread_Control       *executing,
382  Thread_queue_Context *queue_context
383)
384{
385  unsigned int        nest_level;
386  ISR_lock_Context    lock_context;
387  Per_CPU_Control    *cpu_self;
388  Thread_queue_Heads *heads;
389
390  if ( !_POSIX_Mutex_Is_owner( the_mutex, executing ) ) {
391    _POSIX_Mutex_Release( the_mutex, queue_context );
392    return STATUS_NOT_OWNER;
393  }
394
395  nest_level = the_mutex->Recursive.nest_level;
396
397  if ( nest_level > 0 ) {
398    the_mutex->Recursive.nest_level = nest_level - 1;
399    _POSIX_Mutex_Release( the_mutex, queue_context );
400    return STATUS_SUCCESSFUL;
401  }
402
403  _Thread_Resource_count_decrement( executing );
404
405  _Thread_queue_Context_clear_priority_updates( queue_context );
406  _Thread_Wait_acquire_default_critical( executing, &lock_context );
407  _Thread_Priority_remove(
408    executing,
409    &the_mutex->Priority_ceiling,
410    queue_context
411  );
412  _Thread_Wait_release_default_critical( executing, &lock_context );
413
414  cpu_self = _Thread_queue_Dispatch_disable( queue_context );
415
416  heads = the_mutex->Recursive.Mutex.Queue.Queue.heads;
417
418  if ( heads != NULL ) {
419    const Thread_queue_Operations *operations;
420    Thread_Control                *new_owner;
421
422    operations = POSIX_MUTEX_PRIORITY_CEILING_TQ_OPERATIONS;
423    new_owner = ( *operations->first )( heads );
424    _POSIX_Mutex_Set_owner( the_mutex, new_owner );
425    _Thread_Resource_count_increment( new_owner );
426    _Thread_Priority_add(
427      new_owner,
428      &the_mutex->Priority_ceiling,
429      queue_context
430    );
431    _Thread_queue_Extract_critical(
432      &the_mutex->Recursive.Mutex.Queue.Queue,
433      operations,
434      new_owner,
435      queue_context
436    );
437  } else {
438    _POSIX_Mutex_Set_owner( the_mutex, NULL );
439    _POSIX_Mutex_Release( the_mutex, queue_context );
440  }
441
442  _Thread_Priority_update( queue_context );
443  _Thread_Dispatch_enable( cpu_self );
444  return STATUS_SUCCESSFUL;
445}
446
447#define POSIX_MUTEX_ABSTIME_TRY_LOCK ((uintptr_t) 1)
448
449int _POSIX_Mutex_Lock_support(
450  pthread_mutex_t              *mutex,
451  const struct timespec        *abstime,
452  Thread_queue_Enqueue_callout  enqueue_callout
453);
454
455static inline POSIX_Mutex_Control *_POSIX_Mutex_Get(
456  pthread_mutex_t *mutex
457)
458{
459  return (POSIX_Mutex_Control *) mutex;
460}
461
462bool _POSIX_Mutex_Auto_initialization( POSIX_Mutex_Control *the_mutex );
463
464#define POSIX_MUTEX_VALIDATE_OBJECT( the_mutex, flags ) \
465  do { \
466    if ( ( the_mutex ) == NULL ) { \
467      return EINVAL; \
468    } \
469    flags = ( the_mutex )->flags; \
470    if ( \
471      ( ( (uintptr_t) ( the_mutex ) ^ POSIX_MUTEX_MAGIC ) \
472          & ~POSIX_MUTEX_FLAGS_MASK ) \
473        != ( flags & ~POSIX_MUTEX_FLAGS_MASK ) \
474    ) { \
475      if ( !_POSIX_Mutex_Auto_initialization( the_mutex ) ) { \
476        return EINVAL; \
477      } \
478    } \
479  } while ( 0 )
480
481#ifdef __cplusplus
482}
483#endif
484
485#endif
486/*  end of include file */
487
Note: See TracBrowser for help on using the repository browser.