source: rtems/cpukit/score/src/threadqenqueuepriority.c @ e6f7f81

4.115
Last change on this file since e6f7f81 was 6e93dc4a, checked in by Sebastian Huber <sebastian.huber@…>, on 07/22/13 at 08:49:19

score: Create chain implementation header

Move implementation specific parts of chain.h and chain.inl into new
header file chainimpl.h. The chain.h contains now only the application
visible API.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Thread Queue Enqueue Priority
5 *  @ingroup ScoreThreadQ
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2009.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/chainimpl.h>
23#include <rtems/score/isr.h>
24#include <rtems/score/object.h>
25#include <rtems/score/states.h>
26#include <rtems/score/thread.h>
27#include <rtems/score/threadq.h>
28#include <rtems/score/tqdata.h>
29
30/*
31 *  Support the user forcing the unrolling to be disabled.
32 */
33#if __RTEMS_DO_NOT_UNROLL_THREADQ_ENQUEUE_PRIORITY__
34  #undef CPU_UNROLL_ENQUEUE_PRIORITY
35  #define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
36#endif
37
38Thread_blocking_operation_States _Thread_queue_Enqueue_priority (
39  Thread_queue_Control *the_thread_queue,
40  Thread_Control       *the_thread,
41  ISR_Level            *level_p
42)
43{
44  Priority_Control     search_priority;
45  Thread_Control      *search_thread;
46  ISR_Level            level;
47  Chain_Control       *header;
48  uint32_t             header_index;
49  Chain_Node          *the_node;
50  Chain_Node          *next_node;
51  Chain_Node          *previous_node;
52  Chain_Node          *search_node;
53  Priority_Control     priority;
54  States_Control       block_state;
55
56  _Chain_Initialize_empty( &the_thread->Wait.Block2n );
57
58  priority     = the_thread->current_priority;
59  header_index = _Thread_queue_Header_number( priority );
60  header       = &the_thread_queue->Queues.Priority[ header_index ];
61  block_state  = the_thread_queue->state;
62
63  if ( _Thread_queue_Is_reverse_search( priority ) )
64    goto restart_reverse_search;
65
66restart_forward_search:
67  search_priority = PRIORITY_MINIMUM - 1;
68  _ISR_Disable( level );
69  search_thread = (Thread_Control *) _Chain_First( header );
70  while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
71    search_priority = search_thread->current_priority;
72    if ( priority <= search_priority )
73      break;
74
75#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
76    search_thread = (Thread_Control *) search_thread->Object.Node.next;
77    if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
78      break;
79    search_priority = search_thread->current_priority;
80    if ( priority <= search_priority )
81      break;
82#endif
83    _ISR_Flash( level );
84    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
85      _ISR_Enable( level );
86      goto restart_forward_search;
87    }
88    search_thread =
89       (Thread_Control *)search_thread->Object.Node.next;
90  }
91
92  if ( the_thread_queue->sync_state !=
93       THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
94    goto synchronize;
95
96  the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
97
98  if ( priority == search_priority )
99    goto equal_priority;
100
101  search_node   = (Chain_Node *) search_thread;
102  previous_node = search_node->previous;
103  the_node      = (Chain_Node *) the_thread;
104
105  the_node->next         = search_node;
106  the_node->previous     = previous_node;
107  previous_node->next    = the_node;
108  search_node->previous  = the_node;
109  the_thread->Wait.queue = the_thread_queue;
110  _ISR_Enable( level );
111  return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
112
113restart_reverse_search:
114  search_priority     = PRIORITY_MAXIMUM + 1;
115
116  _ISR_Disable( level );
117  search_thread = (Thread_Control *) _Chain_Last( header );
118  while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
119    search_priority = search_thread->current_priority;
120    if ( priority >= search_priority )
121      break;
122#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
123    search_thread = (Thread_Control *) search_thread->Object.Node.previous;
124    if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
125      break;
126    search_priority = search_thread->current_priority;
127    if ( priority >= search_priority )
128      break;
129#endif
130    _ISR_Flash( level );
131    if ( !_States_Are_set( search_thread->current_state, block_state) ) {
132      _ISR_Enable( level );
133      goto restart_reverse_search;
134    }
135    search_thread = (Thread_Control *)
136                         search_thread->Object.Node.previous;
137  }
138
139  if ( the_thread_queue->sync_state !=
140       THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
141    goto synchronize;
142
143  the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
144
145  if ( priority == search_priority )
146    goto equal_priority;
147
148  search_node = (Chain_Node *) search_thread;
149  next_node   = search_node->next;
150  the_node    = (Chain_Node *) the_thread;
151
152  the_node->next          = next_node;
153  the_node->previous      = search_node;
154  search_node->next       = the_node;
155  next_node->previous    = the_node;
156  the_thread->Wait.queue = the_thread_queue;
157  _ISR_Enable( level );
158  return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
159
160equal_priority:               /* add at end of priority group */
161  search_node   = _Chain_Tail( &search_thread->Wait.Block2n );
162  previous_node = search_node->previous;
163  the_node      = (Chain_Node *) the_thread;
164
165  the_node->next         = search_node;
166  the_node->previous     = previous_node;
167  previous_node->next    = the_node;
168  search_node->previous  = the_node;
169  the_thread->Wait.queue = the_thread_queue;
170  _ISR_Enable( level );
171  return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
172
173synchronize:
174  /*
175   *  An interrupt completed the thread's blocking request.
176   *  For example, the blocking thread could have been given
177   *  the mutex by an ISR or timed out.
178   *
179   *  WARNING! Returning with interrupts disabled!
180   */
181  *level_p = level;
182  return the_thread_queue->sync_state;
183}
Note: See TracBrowser for help on using the repository browser.