source: rtems/cpukit/score/src/threadqops.c @ 8c25e04

Last change on this file since 8c25e04 was 8c25e04, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 2, 2015 at 1:02:27 PM

score: Optimize thread queue first operation

In case the thread queue heads exist, then the queue is not empty. See
_Thread_queue_First_locked().

  • Property mode set to 100644
File size: 5.9 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#include <rtems/score/threadimpl.h>
20#include <rtems/score/assert.h>
21#include <rtems/score/chainimpl.h>
22#include <rtems/score/rbtreeimpl.h>
23
24static void _Thread_queue_Do_nothing_priority_change(
25  Thread_Control     *the_thread,
26  Priority_Control    new_priority,
27  Thread_queue_Queue *queue
28)
29{
30  /* Do nothing */
31}
32
33static void _Thread_queue_Do_nothing_extract(
34  Thread_queue_Queue *queue,
35  Thread_Control    *the_thread
36)
37{
38  /* Do nothing */
39}
40
41static void _Thread_queue_Queue_enqueue(
42  Thread_queue_Queue *queue,
43  Thread_Control     *the_thread,
44  void             ( *initialize )( Thread_queue_Heads * ),
45  void             ( *enqueue )( Thread_queue_Heads *, Thread_Control * )
46)
47{
48  Thread_queue_Heads *heads = queue->heads;
49  Thread_queue_Heads *spare_heads = the_thread->Wait.spare_heads;
50
51  the_thread->Wait.spare_heads = NULL;
52
53  if ( heads == NULL ) {
54    _Assert( spare_heads != NULL );
55    _Assert( _Chain_Is_empty( &spare_heads->Free_chain ) );
56    heads = spare_heads;
57    queue->heads = heads;
58    ( *initialize )( heads );
59  }
60
61  _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
62
63  ( *enqueue )( heads, the_thread );
64}
65
66static void _Thread_queue_Queue_extract(
67  Thread_queue_Queue *queue,
68  Thread_Control     *the_thread,
69  void             ( *extract )( Thread_queue_Heads *, Thread_Control * )
70)
71{
72  Thread_queue_Heads *heads = queue->heads;
73
74  _Assert( heads != NULL );
75
76  the_thread->Wait.spare_heads = RTEMS_CONTAINER_OF(
77    _Chain_Get_first_unprotected( &heads->Free_chain ),
78    Thread_queue_Heads,
79    Free_node
80  );
81
82  if ( _Chain_Is_empty( &heads->Free_chain ) ) {
83    queue->heads = NULL;
84  }
85
86  ( *extract )( heads, the_thread );
87}
88
89static void _Thread_queue_FIFO_do_initialize(
90  Thread_queue_Heads *heads
91)
92{
93  _Chain_Initialize_empty( &heads->Heads.Fifo );
94}
95
96static void _Thread_queue_FIFO_do_enqueue(
97  Thread_queue_Heads *heads,
98  Thread_Control     *the_thread
99)
100{
101  _Chain_Append_unprotected(
102    &heads->Heads.Fifo,
103    &the_thread->Wait.Node.Chain
104  );
105}
106
107static void _Thread_queue_FIFO_do_extract(
108  Thread_queue_Heads *heads,
109  Thread_Control     *the_thread
110)
111{
112  _Chain_Extract_unprotected( &the_thread->Wait.Node.Chain );
113}
114
115static void _Thread_queue_FIFO_enqueue(
116  Thread_queue_Queue *queue,
117  Thread_Control     *the_thread
118)
119{
120  _Thread_queue_Queue_enqueue(
121    queue,
122    the_thread,
123    _Thread_queue_FIFO_do_initialize,
124    _Thread_queue_FIFO_do_enqueue
125  );
126}
127
128static void _Thread_queue_FIFO_extract(
129  Thread_queue_Queue *queue,
130  Thread_Control     *the_thread
131)
132{
133  _Thread_queue_Queue_extract(
134    queue,
135    the_thread,
136    _Thread_queue_FIFO_do_extract
137  );
138}
139
140static Thread_Control *_Thread_queue_FIFO_first(
141  Thread_queue_Heads *heads
142)
143{
144  Chain_Control *fifo = &heads->Heads.Fifo;
145  Chain_Node    *first;
146
147  _Assert( !_Chain_Is_empty( fifo ) );
148  first = _Chain_First( fifo );
149
150  return THREAD_CHAIN_NODE_TO_THREAD( first );
151}
152
153static void _Thread_queue_Priority_priority_change(
154  Thread_Control     *the_thread,
155  Priority_Control    new_priority,
156  Thread_queue_Queue *queue
157)
158{
159  Thread_queue_Heads *heads = queue->heads;
160
161  _Assert( heads != NULL );
162
163  _RBTree_Extract(
164    &heads->Heads.Priority,
165    &the_thread->Wait.Node.RBTree
166  );
167  _RBTree_Insert(
168    &heads->Heads.Priority,
169    &the_thread->Wait.Node.RBTree,
170    _Thread_queue_Compare_priority,
171    false
172  );
173}
174
175static void _Thread_queue_Priority_do_initialize(
176  Thread_queue_Heads *heads
177)
178{
179  _RBTree_Initialize_empty( &heads->Heads.Priority );
180}
181
182static void _Thread_queue_Priority_do_enqueue(
183  Thread_queue_Heads *heads,
184  Thread_Control     *the_thread
185)
186{
187  _RBTree_Insert(
188    &heads->Heads.Priority,
189    &the_thread->Wait.Node.RBTree,
190    _Thread_queue_Compare_priority,
191    false
192  );
193}
194
195static void _Thread_queue_Priority_do_extract(
196  Thread_queue_Heads *heads,
197  Thread_Control     *the_thread
198)
199{
200  _RBTree_Extract(
201    &heads->Heads.Priority,
202    &the_thread->Wait.Node.RBTree
203  );
204}
205
206static void _Thread_queue_Priority_enqueue(
207  Thread_queue_Queue *queue,
208  Thread_Control     *the_thread
209)
210{
211  _Thread_queue_Queue_enqueue(
212    queue,
213    the_thread,
214    _Thread_queue_Priority_do_initialize,
215    _Thread_queue_Priority_do_enqueue
216  );
217}
218
219static void _Thread_queue_Priority_extract(
220  Thread_queue_Queue *queue,
221  Thread_Control     *the_thread
222)
223{
224  _Thread_queue_Queue_extract(
225    queue,
226    the_thread,
227    _Thread_queue_Priority_do_extract
228  );
229}
230
231static Thread_Control *_Thread_queue_Priority_first(
232  Thread_queue_Heads *heads
233)
234{
235  RBTree_Control *priority_queue = &heads->Heads.Priority;
236  RBTree_Node    *first;
237
238  _Assert( !_RBTree_Is_empty( priority_queue ) );
239  first = _RBTree_Minimum( priority_queue );
240
241  return THREAD_RBTREE_NODE_TO_THREAD( first );
242}
243
244const Thread_queue_Operations _Thread_queue_Operations_default = {
245  .priority_change = _Thread_queue_Do_nothing_priority_change,
246  .extract = _Thread_queue_Do_nothing_extract
247  /*
248   * The default operations are only used in _Thread_Change_priority() and
249   * _Thread_Timeout() and don't have a thread queue associated with them, so
250   * the enqueue and first operations are superfluous.
251   */
252};
253
254const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
255  .priority_change = _Thread_queue_Do_nothing_priority_change,
256  .enqueue = _Thread_queue_FIFO_enqueue,
257  .extract = _Thread_queue_FIFO_extract,
258  .first = _Thread_queue_FIFO_first
259};
260
261const Thread_queue_Operations _Thread_queue_Operations_priority = {
262  .priority_change = _Thread_queue_Priority_priority_change,
263  .enqueue = _Thread_queue_Priority_enqueue,
264  .extract = _Thread_queue_Priority_extract,
265  .first = _Thread_queue_Priority_first
266};
Note: See TracBrowser for help on using the repository browser.