source: rtems/cpukit/score/src/semaphore.c @ bbd6d27a

5
Last change on this file since bbd6d27a was 8f96581, checked in by Sebastian Huber <sebastian.huber@…>, on 04/01/16 at 09:38:47

score: Rework MP thread queue callout support

The thread queue implementation was heavily reworked to support SMP.
This broke the multiprocessing support of the thread queues. This is
fixed by this patch.

A thread proxy is unblocked due to three reasons

1) timeout,
2) request satisfaction, and
3) extraction.

In case 1) no MPCI message must be sent. This is ensured via the
_Thread_queue_MP_callout_do_nothing() callout set during
_Thread_MP_Allocate_proxy().

In case 2) and 3) an MPCI message must be sent. In case we interrupt
the blocking operation during _Thread_queue_Enqueue_critical(), then
this message must be sent by the blocking thread. For this the new
fields Thread_Proxy_control::thread_queue_callout and
Thread_Proxy_control::thread_queue_id are used.

Delete the individual API MP callout types and use
Thread_queue_MP_callout throughout. This type is only defined in
multiprocessing configurations. Prefix the multiprocessing parameters
with mp_ to ease code review. Multiprocessing specific parameters are
optional due to use of a similar macro pattern. There is no overhead
for non-multiprocessing configurations.

  • Property mode set to 100644
File size: 3.1 KB
Line 
1/*
2 * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#if HAVE_STRUCT__THREAD_QUEUE_QUEUE
20
21#include <sys/lock.h>
22
23#include <rtems/score/assert.h>
24#include <rtems/score/threadimpl.h>
25#include <rtems/score/threadqimpl.h>
26
27#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority
28
29typedef struct {
30  Thread_queue_Syslock_queue Queue;
31  unsigned int count;
32} Semaphore_Control;
33
34RTEMS_STATIC_ASSERT(
35  offsetof( Semaphore_Control, Queue )
36    == offsetof( struct _Semaphore_Control, _Queue ),
37  SEMAPHORE_CONTROL_QUEUE
38);
39
40RTEMS_STATIC_ASSERT(
41  offsetof( Semaphore_Control, count )
42    == offsetof( struct _Semaphore_Control, _count ),
43  SEMAPHORE_CONTROL_COUNT
44);
45
46RTEMS_STATIC_ASSERT(
47  sizeof( Semaphore_Control ) == sizeof( struct _Semaphore_Control ),
48  SEMAPHORE_CONTROL_SIZE
49);
50
51static Semaphore_Control *_Semaphore_Get(
52  struct _Semaphore_Control *_sem
53)
54{
55  return (Semaphore_Control *) _sem;
56}
57
58static Thread_Control *_Semaphore_Queue_acquire(
59  Semaphore_Control *sem,
60  ISR_lock_Context  *lock_context
61)
62{
63  Thread_Control *executing;
64
65  _ISR_lock_ISR_disable( lock_context );
66  executing = _Thread_Executing;
67  _Thread_queue_Queue_acquire_critical(
68    &sem->Queue.Queue,
69    &executing->Potpourri_stats,
70    lock_context
71  );
72
73  return executing;
74}
75
76static void _Semaphore_Queue_release(
77  Semaphore_Control *sem,
78  ISR_lock_Context  *lock_context
79)
80{
81  _Thread_queue_Queue_release( &sem->Queue.Queue, lock_context );
82}
83
84void _Semaphore_Wait( struct _Semaphore_Control *_sem )
85{
86  Semaphore_Control *sem ;
87  ISR_lock_Context   lock_context;
88  Thread_Control    *executing;
89  unsigned int       count;
90
91  sem = _Semaphore_Get( _sem );
92  executing = _Semaphore_Queue_acquire( sem, &lock_context );
93
94  count = sem->count;
95  if ( count > 0 ) {
96    sem->count = count - 1;
97    _Semaphore_Queue_release( sem, &lock_context );
98  } else {
99    _Thread_queue_Enqueue_critical(
100      &sem->Queue.Queue,
101      SEMAPHORE_TQ_OPERATIONS,
102      executing,
103      STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE,
104      0,
105      0,
106      &lock_context
107    );
108  }
109}
110
111void _Semaphore_Post( struct _Semaphore_Control *_sem )
112{
113  Semaphore_Control  *sem;
114  ISR_lock_Context    lock_context;
115  Thread_queue_Heads *heads;
116
117  sem = _Semaphore_Get( _sem );
118  _Semaphore_Queue_acquire( sem, &lock_context );
119
120  heads = sem->Queue.Queue.heads;
121  if ( heads == NULL ) {
122    _Assert( sem->count < UINT_MAX );
123    ++sem->count;
124    _Semaphore_Queue_release( sem, &lock_context );
125  } else {
126    const Thread_queue_Operations *operations;
127    Thread_Control *first;
128
129    operations = SEMAPHORE_TQ_OPERATIONS;
130    first = ( *operations->first )( heads );
131
132    _Thread_queue_Extract_critical(
133      &sem->Queue.Queue,
134      operations,
135      first,
136      NULL,
137      0,
138      &lock_context
139    );
140  }
141}
142
143#endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */
Note: See TracBrowser for help on using the repository browser.