diff options
Diffstat (limited to 'cpukit/score/src')
-rw-r--r-- | cpukit/score/src/coremsgsubmit.c | 4 | ||||
-rw-r--r-- | cpukit/score/src/coremutexsurrender.c | 11 | ||||
-rw-r--r-- | cpukit/score/src/threadchangepriority.c | 57 | ||||
-rw-r--r-- | cpukit/score/src/threadclearstate.c | 6 | ||||
-rw-r--r-- | cpukit/score/src/threadhandler.c | 1 | ||||
-rw-r--r-- | cpukit/score/src/threadinitialize.c | 3 | ||||
-rw-r--r-- | cpukit/score/src/threadqdequeuefifo.c | 3 | ||||
-rw-r--r-- | cpukit/score/src/threadqdequeuepriority.c | 3 | ||||
-rw-r--r-- | cpukit/score/src/threadqenqueue.c | 13 | ||||
-rw-r--r-- | cpukit/score/src/threadqenqueuefifo.c | 3 | ||||
-rw-r--r-- | cpukit/score/src/threadqenqueuepriority.c | 29 | ||||
-rw-r--r-- | cpukit/score/src/threadqextractfifo.c | 4 | ||||
-rw-r--r-- | cpukit/score/src/threadqextractpriority.c | 97 | ||||
-rw-r--r-- | cpukit/score/src/threadqrequeue.c | 63 | ||||
-rw-r--r-- | cpukit/score/src/threadsetstate.c | 4 |
15 files changed, 215 insertions, 86 deletions
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; |