summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog19
-rw-r--r--cpukit/score/Makefile.am3
-rw-r--r--cpukit/score/include/rtems/score/coremutex.h12
-rw-r--r--cpukit/score/include/rtems/score/threadq.h31
-rw-r--r--cpukit/score/inline/rtems/score/coremutex.inl37
-rw-r--r--cpukit/score/src/coremsgsubmit.c4
-rw-r--r--cpukit/score/src/coremutexsurrender.c11
-rw-r--r--cpukit/score/src/threadchangepriority.c57
-rw-r--r--cpukit/score/src/threadclearstate.c6
-rw-r--r--cpukit/score/src/threadhandler.c1
-rw-r--r--cpukit/score/src/threadinitialize.c3
-rw-r--r--cpukit/score/src/threadqdequeuefifo.c3
-rw-r--r--cpukit/score/src/threadqdequeuepriority.c3
-rw-r--r--cpukit/score/src/threadqenqueue.c13
-rw-r--r--cpukit/score/src/threadqenqueuefifo.c3
-rw-r--r--cpukit/score/src/threadqenqueuepriority.c29
-rw-r--r--cpukit/score/src/threadqextractfifo.c4
-rw-r--r--cpukit/score/src/threadqextractpriority.c97
-rw-r--r--cpukit/score/src/threadqrequeue.c63
-rw-r--r--cpukit/score/src/threadsetstate.c4
20 files changed, 300 insertions, 103 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index dabfdeb3c6..f9c80cbf00 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,5 +1,24 @@
2007-03-05 Joel Sherrill <joel@OARcorp.com>
+ PR 1222/cpukit
+ * score/Makefile.am, score/include/rtems/score/coremutex.h,
+ score/include/rtems/score/threadq.h,
+ score/inline/rtems/score/coremutex.inl, score/src/coremsgsubmit.c,
+ score/src/coremutexsurrender.c, score/src/threadchangepriority.c,
+ score/src/threadclearstate.c, score/src/threadhandler.c,
+ score/src/threadinitialize.c, score/src/threadqdequeuefifo.c,
+ score/src/threadqdequeuepriority.c, score/src/threadqenqueue.c,
+ score/src/threadqenqueuefifo.c, score/src/threadqenqueuepriority.c,
+ score/src/threadqextractfifo.c, score/src/threadqextractpriority.c,
+ score/src/threadsetstate.c: Enhance so that when the prioirity of a
+ thread that is blocked on a priority based thread queue is changed,
+ that its placement in the queue is reevaluated based upon the new
+ priority. This enhancement includes modifications to the SuperCore as
+ well as new test cases.
+ * score/src/threadqrequeue.c: New file.
+
+2007-03-05 Joel Sherrill <joel@OARcorp.com>
+
* sapi/src/exinit.c: Fix spacing.
2007-03-05 Joel Sherrill <joel@OARcorp.com>
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index a837abe0bd..bf5e15eb1a 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -136,7 +136,8 @@ libscore_a_SOURCES += src/threadq.c src/threadqdequeue.c \
src/threadqenqueuepriority.c src/threadqextract.c \
src/threadqextractfifo.c src/threadqextractpriority.c \
src/threadqextractwithproxy.c src/threadqfirst.c src/threadqfirstfifo.c \
- src/threadqfirstpriority.c src/threadqflush.c src/threadqtimeout.c
+ src/threadqfirstpriority.c src/threadqflush.c src/threadqrequeue.c \
+ src/threadqtimeout.c
## TOD_C_FILES
libscore_a_SOURCES += src/coretod.c src/coretodset.c src/coretodtickle.c \
diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h
index 4015ac97e4..1d2d38db59 100644
--- a/cpukit/score/include/rtems/score/coremutex.h
+++ b/cpukit/score/include/rtems/score/coremutex.h
@@ -249,7 +249,7 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
);
/**
- * @brief Seize Mutex with Blockign
+ * @brief Seize Mutex with Blocking
*
* This routine performs the blocking portion of a mutex obtain.
* It is an actual subroutine and is not implemented as something
@@ -280,6 +280,16 @@ void _CORE_mutex_Seize_interrupt_blocking(
* @note If the mutex is called from an interrupt service routine,
* with context switching disabled, or before multitasking,
* then a fatal error is generated.
+ *
+ *
+ * The logic on this routine is as follows:
+ *
+ * * If incorrect system state
+ * return an error
+ * * If mutex is available without any contention or blocking
+ * obtain it with interrupts disabled and returned
+ * * If the caller is willing to wait
+ * then they are blocked.
*/
#define _CORE_mutex_Seize( \
_the_mutex, _id, _wait, _timeout, _level ) \
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index 8744887344..7b609285eb 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -94,6 +94,20 @@ void _Thread_queue_Enqueue_with_handler(
Thread_queue_Timeout_callout handler
);
+/**
+ * @brief Thread queue Requeue
+ *
+ * This routine is invoked when a thread changes priority and is
+ * blocked on a thread queue. If the queue is priority ordered,
+ * the_thread is removed from the_thread_queue and reinserted using
+ * its new priority. This method has no impact on the state of the_thread
+ * or of any timeouts associated with this blocking.
+ */
+void _Thread_queue_Requeue(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+);
+
/** @brief Thread queue Extract
*
* This routine removes the_thread from the_thread_queue
@@ -169,16 +183,27 @@ void _Thread_queue_Enqueue_priority(
Thread_Control *the_thread
);
-/** @brief Thread queue Extract priority
+/** @brief Thread queue Extract priority Helper
*
* This routine removes the_thread from the_thread_queue
* and cancels any timeouts associated with this blocking.
*/
-void _Thread_queue_Extract_priority(
+void _Thread_queue_Extract_priority_helper(
Thread_queue_Control *the_thread_queue,
- Thread_Control *the_thread
+ Thread_Control *the_thread,
+ boolean requeuing
);
+/**
+ * @brief Thread queue Extract priority
+ *
+ * This macro wraps the underlying call and hides the requeuing argument.
+ */
+
+#define _Thread_queue_Extract_priority( _the_thread_queue, _the_thread ) \
+ _Thread_queue_Extract_priority_helper( _the_thread_queue, _the_thread, FALSE )
+
+
/** @brief Thread queue First priority
*
* This function returns a pointer to the "first" thread
diff --git a/cpukit/score/inline/rtems/score/coremutex.inl b/cpukit/score/inline/rtems/score/coremutex.inl
index 2bde4a888f..342428ccbb 100644
--- a/cpukit/score/inline/rtems/score/coremutex.inl
+++ b/cpukit/score/inline/rtems/score/coremutex.inl
@@ -143,25 +143,29 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
_ISR_Enable( level );
return 0;
- }
- /* else must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING */
+ } /* else must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
+ *
+ * we possibly bump the priority of the current holder -- which
+ * happens to be _Thread_Executing.
+ */
{
- Priority_Control ceiling;
- Priority_Control current;
+ Priority_Control ceiling;
+ Priority_Control current;
+
+ ceiling = the_mutex->Attributes.priority_ceiling;
+ current = executing->current_priority;
+ if ( current == ceiling ) {
+ _ISR_Enable( level );
+ return 0;
+ }
- ceiling = the_mutex->Attributes.priority_ceiling;
- current = executing->current_priority;
- if ( current == ceiling ) {
- _ISR_Enable( level );
- return 0;
- }
- if ( current > ceiling ) {
+ if ( current > ceiling ) {
_Thread_Disable_dispatch();
_ISR_Enable( level );
_Thread_Change_priority(
the_mutex->holder,
the_mutex->Attributes.priority_ceiling,
- FALSE
+ FALSE
);
_Thread_Enable_dispatch();
return 0;
@@ -177,6 +181,11 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
return 0;
}
+ /*
+ * At this point, we know the mutex was not available. If this thread
+ * is the thread that has locked the mutex, let's see if we are allowed
+ * to nest access.
+ */
if ( _Thread_Is_executing( the_mutex->holder ) ) {
switch ( the_mutex->Attributes.lock_nesting_behavior ) {
case CORE_MUTEX_NESTING_ACQUIRES:
@@ -192,6 +201,10 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
}
}
+ /*
+ * The mutex is not available and the caller must deal with the possibility
+ * of blocking.
+ */
return 1;
}
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
index a1ac6d5b87..2f1ea815ca 100644
--- a/cpukit/score/src/coremsgsubmit.c
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -88,7 +88,7 @@ CORE_message_queue_Status _CORE_message_queue_Submit(
the_thread->Wait.return_argument,
size
);
- *(uint32_t *)the_thread->Wait.return_argument_1 = size;
+ *(size_t *)the_thread->Wait.return_argument_1 = size;
the_thread->Wait.count = submit_type;
#if defined(RTEMS_MULTIPROCESSING)
@@ -168,7 +168,7 @@ CORE_message_queue_Status _CORE_message_queue_Submit(
executing->Wait.queue = &the_message_queue->Wait_queue;
executing->Wait.id = id;
executing->Wait.return_argument = buffer;
- executing->Wait.return_argument_1 = (void *)size;
+ executing->Wait.option = size;
executing->Wait.count = submit_type;
_ISR_Enable( level );
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c
index e6f52e229d..839c0af5bf 100644
--- a/cpukit/score/src/coremutexsurrender.c
+++ b/cpukit/score/src/coremutexsurrender.c
@@ -6,7 +6,7 @@
* This package is the implementation of the Mutex Handler.
* This handler provides synchronization and mutual exclusion capabilities.
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -90,6 +90,10 @@ CORE_mutex_Status _CORE_mutex_Surrender(
}
}
+ /*
+ * Formally release the mutex before possibly transferring it to a
+ * blocked thread.
+ */
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
holder->resource_count--;
@@ -101,7 +105,6 @@ CORE_mutex_Status _CORE_mutex_Surrender(
* inherited priority must be lowered if this is the last
* mutex (i.e. resource) this task has.
*/
-
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
if ( holder->resource_count == 0 &&
@@ -110,6 +113,10 @@ CORE_mutex_Status _CORE_mutex_Surrender(
}
}
+ /*
+ * Now we check if another thread was waiting for this mutex. If so,
+ * transfer the mutex to that thread.
+ */
if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
index 89d0d2cd5f..9847f54f80 100644
--- a/cpukit/score/src/threadchangepriority.c
+++ b/cpukit/score/src/threadchangepriority.c
@@ -2,7 +2,7 @@
* Thread Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -55,8 +55,8 @@ void _Thread_Change_priority(
boolean prepend_it
)
{
- ISR_Level level;
- /* boolean do_prepend = FALSE; */
+ ISR_Level level;
+ States_Control state;
/*
* If this is a case where prepending the task to its priority is
@@ -66,13 +66,6 @@ void _Thread_Change_priority(
* change calls (e.g. rtems_task_set_priority) should always do an
* append not a prepend.
*/
-
- /*
- * Techically, the prepend should conditional on the thread lowering
- * its priority but that does allow cxd2004 of the acvc 2.0.1 to
- * pass with rtems 4.0.0. This should change when gnat redoes its
- * priority scheme.
- */
/*
if ( prepend_it &&
_Thread_Is_executing( the_thread ) &&
@@ -80,26 +73,46 @@ void _Thread_Change_priority(
prepend_it = TRUE;
*/
+ /*
+ * Set a transient state for the thread so it is pulled off the Ready chains.
+ * This will prevent it from being scheduled no matter what happens in an
+ * ISR.
+ */
_Thread_Set_transient( the_thread );
- if ( the_thread->current_priority != new_priority )
+ /*
+ * Do not bother recomputing all the priority related information if
+ * we are not REALLY changing priority.
+ */
+ if ( the_thread->current_priority != new_priority )
_Thread_Set_priority( the_thread, new_priority );
_ISR_Disable( level );
- the_thread->current_state =
- _States_Clear( STATES_TRANSIENT, the_thread->current_state );
-
- if ( ! _States_Is_ready( the_thread->current_state ) ) {
- /*
- * XXX If a task is to be reordered while blocked on a priority
- * XXX priority ordered thread queue, then this is where that
- * XXX should occur.
- */
+ /*
+ * If the thread has more than STATES_TRANSIENT set, then it is blocked,
+ * If it is blocked on a thread queue, then we need to requeue it.
+ */
+ state = the_thread->current_state;
+ if ( state != STATES_TRANSIENT ) {
+ if ( _States_Is_waiting_on_thread_queue( state ) ) {
+ _ISR_Enable( level );
+ _Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
+ _ISR_Disable( level ); /* redisable so state is cleared with ISR off */
+ }
+ the_thread->current_state = _States_Clear( STATES_TRANSIENT, state );
_ISR_Enable( level );
return;
}
+ /*
+ * Interrupts are STILL disabled.
+ * We now know the thread will be in the READY state when we remove
+ * the TRANSIENT state. So we have to place it on the appropriate
+ * Ready Queue with interrupts off.
+ */
+ the_thread->current_state = _States_Clear( STATES_TRANSIENT, state );
+
_Priority_Add_to_bit_map( &the_thread->Priority_map );
if ( prepend_it )
_Chain_Prepend_unprotected( the_thread->ready, &the_thread->Object.Node );
@@ -108,6 +121,10 @@ void _Thread_Change_priority(
_ISR_Flash( level );
+ /*
+ * We altered the set of thread priorities. So let's figure out
+ * who is the heir and if we need to switch to them.
+ */
_Thread_Calculate_heir();
if ( !_Thread_Is_executing_also_the_heir() &&
diff --git a/cpukit/score/src/threadclearstate.c b/cpukit/score/src/threadclearstate.c
index bb7deffe06..8a175fd8cd 100644
--- a/cpukit/score/src/threadclearstate.c
+++ b/cpukit/score/src/threadclearstate.c
@@ -73,6 +73,12 @@ void _Thread_Clear_state(
_ISR_Flash( level );
+ /*
+ * If the thread that was unblocked is more important than the heir,
+ * then we have a new heir. In addition, if the current thread
+ * is preemptible or we are waking up one of the "pseudo-ISR" system
+ * threads, then we need to do a context switch.
+ */
if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
_Thread_Heir = the_thread;
if ( _Thread_Executing->is_preemptible ||
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
index c6cf23e660..b7708e2b03 100644
--- a/cpukit/score/src/threadhandler.c
+++ b/cpukit/score/src/threadhandler.c
@@ -98,7 +98,6 @@ void _Thread_Handler( void )
#endif
#endif
-
/*
* Take care that 'begin' extensions get to complete before
* 'switch' extensions can run. This means must keep dispatch
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 0ed4cdfe69..40e786f954 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -2,7 +2,7 @@
* Thread Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -190,6 +190,7 @@ boolean _Thread_Initialize(
the_thread->Start.isr_level = isr_level;
the_thread->current_state = STATES_DORMANT;
+ the_thread->Wait.queue = NULL;
the_thread->resource_count = 0;
the_thread->suspend_count = 0;
the_thread->real_priority = priority;
diff --git a/cpukit/score/src/threadqdequeuefifo.c b/cpukit/score/src/threadqdequeuefifo.c
index ff76bff3d9..787ec41074 100644
--- a/cpukit/score/src/threadqdequeuefifo.c
+++ b/cpukit/score/src/threadqdequeuefifo.c
@@ -2,7 +2,7 @@
* Thread Queue Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -55,6 +55,7 @@ Thread_Control *_Thread_queue_Dequeue_fifo(
the_thread = (Thread_Control *)
_Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
+ the_thread->Wait.queue = NULL;
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
_ISR_Enable( level );
_Thread_Unblock( the_thread );
diff --git a/cpukit/score/src/threadqdequeuepriority.c b/cpukit/score/src/threadqdequeuepriority.c
index 1b02a71158..4da18165d9 100644
--- a/cpukit/score/src/threadqdequeuepriority.c
+++ b/cpukit/score/src/threadqdequeuepriority.c
@@ -2,7 +2,7 @@
* Thread Queue Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -81,6 +81,7 @@ Thread_Control *_Thread_queue_Dequeue_priority(
}
dequeue:
+ the_thread->Wait.queue = NULL;
new_first_node = the_thread->Wait.Block2n.first;
new_first_thread = (Thread_Control *) new_first_node;
next_node = the_thread->Object.Node.next;
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 3cbf76800b..2cc1141993 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -2,7 +2,7 @@
* Thread Queue Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -60,8 +60,14 @@ void _Thread_queue_Enqueue_with_handler(
the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
else
#endif
- _Thread_Set_state( the_thread, the_thread_queue->state );
+ /*
+ * Set the blocking state for this thread queue in the thread.
+ */
+ _Thread_Set_state( the_thread, the_thread_queue->state );
+ /*
+ * If the thread wants to timeout, then schedule its timer.
+ */
if ( timeout ) {
_Watchdog_Initialize(
&the_thread->Timer,
@@ -73,6 +79,9 @@ void _Thread_queue_Enqueue_with_handler(
_Watchdog_Insert_ticks( &the_thread->Timer, timeout );
}
+ /*
+ * Now enqueue the thread per the discipline for this thread queue.
+ */
switch( the_thread_queue->discipline ) {
case THREAD_QUEUE_DISCIPLINE_FIFO:
_Thread_queue_Enqueue_fifo( the_thread_queue, the_thread );
diff --git a/cpukit/score/src/threadqenqueuefifo.c b/cpukit/score/src/threadqenqueuefifo.c
index b4cba6a532..c7260807ed 100644
--- a/cpukit/score/src/threadqenqueuefifo.c
+++ b/cpukit/score/src/threadqenqueuefifo.c
@@ -67,17 +67,20 @@ void _Thread_queue_Enqueue_fifo (
&the_thread_queue->Queues.Fifo,
&the_thread->Object.Node
);
+ the_thread->Wait.queue = the_thread_queue;
_ISR_Enable( level );
return;
case THREAD_QUEUE_TIMEOUT:
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ the_thread->Wait.queue = NULL;
_ISR_Enable( level );
break;
case THREAD_QUEUE_SATISFIED:
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
_Watchdog_Deactivate( &the_thread->Timer );
+ the_thread->Wait.queue = NULL;
_ISR_Enable( level );
(void) _Watchdog_Remove( &the_thread->Timer );
} else
diff --git a/cpukit/score/src/threadqenqueuepriority.c b/cpukit/score/src/threadqenqueuepriority.c
index 5c49a4c6d8..9974a3a674 100644
--- a/cpukit/score/src/threadqenqueuepriority.c
+++ b/cpukit/score/src/threadqenqueuepriority.c
@@ -108,10 +108,11 @@ restart_forward_search:
previous_node = search_node->previous;
the_node = (Chain_Node *) the_thread;
- the_node->next = search_node;
- the_node->previous = previous_node;
- previous_node->next = the_node;
- search_node->previous = the_node;
+ the_node->next = search_node;
+ the_node->previous = previous_node;
+ previous_node->next = the_node;
+ search_node->previous = the_node;
+ the_thread->Wait.queue = the_thread_queue;
_ISR_Enable( level );
return;
@@ -153,10 +154,11 @@ restart_reverse_search:
next_node = search_node->next;
the_node = (Chain_Node *) the_thread;
- the_node->next = next_node;
- the_node->previous = search_node;
- search_node->next = the_node;
- next_node->previous = the_node;
+ the_node->next = next_node;
+ the_node->previous = search_node;
+ search_node->next = the_node;
+ next_node->previous = the_node;
+ the_thread->Wait.queue = the_thread_queue;
_ISR_Enable( level );
return;
@@ -165,10 +167,11 @@ equal_priority: /* add at end of priority group */
previous_node = search_node->previous;
the_node = (Chain_Node *) the_thread;
- the_node->next = search_node;
- the_node->previous = previous_node;
- previous_node->next = the_node;
- search_node->previous = the_node;
+ the_node->next = search_node;
+ the_node->previous = previous_node;
+ previous_node->next = the_node;
+ search_node->previous = the_node;
+ the_thread->Wait.queue = the_thread_queue;
_ISR_Enable( level );
return;
@@ -193,12 +196,14 @@ synchronize:
case THREAD_QUEUE_TIMEOUT:
the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ the_thread->Wait.queue = NULL;
_ISR_Enable( level );
break;
case THREAD_QUEUE_SATISFIED:
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
_Watchdog_Deactivate( &the_thread->Timer );
+ the_thread->Wait.queue = NULL;
_ISR_Enable( level );
(void) _Watchdog_Remove( &the_thread->Timer );
} else
diff --git a/cpukit/score/src/threadqextractfifo.c b/cpukit/score/src/threadqextractfifo.c
index 145bf314a3..f7ecf3e270 100644
--- a/cpukit/score/src/threadqextractfifo.c
+++ b/cpukit/score/src/threadqextractfifo.c
@@ -2,7 +2,7 @@
* Thread Queue Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -58,6 +58,8 @@ void _Thread_queue_Extract_fifo(
_Chain_Extract_unprotected( &the_thread->Object.Node );
+ the_thread->Wait.queue = NULL;
+
if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
_ISR_Enable( level );
} else {
diff --git a/cpukit/score/src/threadqextractpriority.c b/cpukit/score/src/threadqextractpriority.c
index dfadc25425..ef45fb4423 100644
--- a/cpukit/score/src/threadqextractpriority.c
+++ b/cpukit/score/src/threadqextractpriority.c
@@ -2,7 +2,7 @@
* Thread Queue Handler
*
*
- * COPYRIGHT (c) 1989-1999.
+ * COPYRIGHT (c) 1989-2006.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -35,6 +35,7 @@
* Input parameters:
* the_thread_queue - pointer to a threadq header
* the_thread - pointer to a thread control block
+ * requeuing - TRUE if requeuing and should not alter timeout or state
*
* Output parameters: NONE
*
@@ -42,12 +43,13 @@
* EXTRACT_PRIORITY
*/
-void _Thread_queue_Extract_priority(
+void _Thread_queue_Extract_priority_helper(
Thread_queue_Control *the_thread_queue,
- Thread_Control *the_thread
+ Thread_Control *the_thread,
+ boolean requeuing
)
{
- ISR_Level level;
+ ISR_Level level;
Chain_Node *the_node;
Chain_Node *next_node;
Chain_Node *previous_node;
@@ -58,50 +60,63 @@ void _Thread_queue_Extract_priority(
the_node = (Chain_Node *) the_thread;
_ISR_Disable( level );
- if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
- next_node = the_node->next;
- previous_node = the_node->previous;
+ if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
+ _ISR_Enable( level );
+ return;
+ }
- if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
- new_first_node = the_thread->Wait.Block2n.first;
- new_first_thread = (Thread_Control *) new_first_node;
- last_node = the_thread->Wait.Block2n.last;
- new_second_node = new_first_node->next;
+ /*
+ * The thread was actually waiting on a thread queue so let's remove it.
+ */
- previous_node->next = new_first_node;
- next_node->previous = new_first_node;
- new_first_node->next = next_node;
- new_first_node->previous = previous_node;
+ next_node = the_node->next;
+ previous_node = the_node->previous;
- if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
- /* > two threads on 2-n */
- new_second_node->previous =
- _Chain_Head( &new_first_thread->Wait.Block2n );
- new_first_thread->Wait.Block2n.first = new_second_node;
+ if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
+ new_first_node = the_thread->Wait.Block2n.first;
+ new_first_thread = (Thread_Control *) new_first_node;
+ last_node = the_thread->Wait.Block2n.last;
+ new_second_node = new_first_node->next;
- new_first_thread->Wait.Block2n.last = last_node;
- last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
- }
- } else {
- previous_node->next = next_node;
- next_node->previous = previous_node;
- }
+ previous_node->next = new_first_node;
+ next_node->previous = new_first_node;
+ new_first_node->next = next_node;
+ new_first_node->previous = previous_node;
+
+ if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
+ /* > two threads on 2-n */
+ new_second_node->previous =
+ _Chain_Head( &new_first_thread->Wait.Block2n );
+ new_first_thread->Wait.Block2n.first = new_second_node;
- if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
- _ISR_Enable( level );
- _Thread_Unblock( the_thread );
- } else {
- _Watchdog_Deactivate( &the_thread->Timer );
- _ISR_Enable( level );
- (void) _Watchdog_Remove( &the_thread->Timer );
- _Thread_Unblock( the_thread );
+ new_first_thread->Wait.Block2n.last = last_node;
+ last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
}
+ } else {
+ previous_node->next = next_node;
+ next_node->previous = previous_node;
+ }
-#if defined(RTEMS_MULTIPROCESSING)
- if ( !_Objects_Is_local_id( the_thread->Object.id ) )
- _Thread_MP_Free_proxy( the_thread );
-#endif
+ /*
+ * If we are not supposed to touch timers or the thread's state, return.
+ */
+
+ if ( requeuing ) {
+ _ISR_Enable( level );
+ return;
}
- else
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
_ISR_Enable( level );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
}
diff --git a/cpukit/score/src/threadqrequeue.c b/cpukit/score/src/threadqrequeue.c
new file mode 100644
index 0000000000..96434639ef
--- /dev/null
+++ b/cpukit/score/src/threadqrequeue.c
@@ -0,0 +1,63 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Requeue
+ *
+ * This routine is invoked when a thread changes priority and should be
+ * moved to a different position on the thread queue.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to a thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY: NONE
+ */
+
+void _Thread_queue_Requeue(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+)
+{
+ /* just in case the thread really wasn't blocked here */
+ if ( !the_thread_queue )
+ return;
+
+ switch ( the_thread_queue->discipline ) {
+ case THREAD_QUEUE_DISCIPLINE_FIFO:
+ /* queueing by FIFO -- nothing to do */
+ break;
+ case THREAD_QUEUE_DISCIPLINE_PRIORITY: {
+ Thread_queue_Control *tq = the_thread_queue;
+
+ _Thread_queue_Enter_critical_section( tq );
+ _Thread_queue_Extract_priority_helper( tq, the_thread, TRUE );
+ _Thread_queue_Enqueue_priority( tq, the_thread );
+ }
+ break;
+ }
+}
+
diff --git a/cpukit/score/src/threadsetstate.c b/cpukit/score/src/threadsetstate.c
index f1cc469f1c..9538ffaa27 100644
--- a/cpukit/score/src/threadsetstate.c
+++ b/cpukit/score/src/threadsetstate.c
@@ -50,10 +50,10 @@
void _Thread_Set_state(
Thread_Control *the_thread,
- States_Control state
+ States_Control state
)
{
- ISR_Level level;
+ ISR_Level level;
Chain_Control *ready;
ready = the_thread->ready;