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

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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