static rtems_task Init(rtems_task_argument ignored) { Freechain_Control fc; test_node *node; TEST_BEGIN(); _Freechain_Initialize(&fc, NULL, 0, sizeof(test_node)); rtems_test_assert(_Chain_Is_empty(&fc.Free)); _Freechain_Initialize(&fc, malloc, 1, SIZE_MAX); rtems_test_assert(_Chain_Is_empty(&fc.Free)); rtems_test_assert(_Freechain_Get(&fc, NULL, 0, sizeof(test_node)) == NULL); rtems_test_assert(_Freechain_Get(&fc, malloc, 1, SIZE_MAX) == NULL); /* check whether freechain put and get works correctly*/ _Freechain_Put(&fc, NULL); puts( "INIT - Get node from freechain - OK" ); node = _Freechain_Get(&fc, malloc, 1, sizeof(test_node)); node->x = 1; puts( "INIT - Put node back to freechain - OK" ); _Freechain_Put(&fc, node); puts( "INIT - Verify freechain node put and get - OK" ); node = _Freechain_Get(&fc, NULL, 0, sizeof(test_node)); rtems_test_assert(node->x == 1); TEST_END(); rtems_test_exit(0); }
void _Watchdog_Adjust( Chain_Control *header, Watchdog_Adjust_directions direction, Watchdog_Interval units ) { ISR_Level level; _ISR_Disable( level ); /* * NOTE: It is safe NOT to make 'header' a pointer * to volatile data (contrast this with watchdoginsert.c) * because we call _Watchdog_Tickle() below and * hence the compiler must not assume *header to remain * unmodified across that call. * * Till Straumann, 7/2003 */ if ( !_Chain_Is_empty( header ) ) { switch ( direction ) { case WATCHDOG_BACKWARD: _Watchdog_First( header )->delta_interval += units; break; case WATCHDOG_FORWARD: while ( units ) { if ( units < _Watchdog_First( header )->delta_interval ) { _Watchdog_First( header )->delta_interval -= units; break; } else { units -= _Watchdog_First( header )->delta_interval; _Watchdog_First( header )->delta_interval = 1; _ISR_Enable( level ); _Watchdog_Tickle( header ); _ISR_Disable( level ); if ( _Chain_Is_empty( header ) ) break; } } break; } } _ISR_Enable( level ); }
Thread_Control *_Thread_queue_Dequeue_fifo( Thread_queue_Control *the_thread_queue ) { ISR_Level level; Thread_Control *the_thread; _ISR_Disable( level ); if ( !_Chain_Is_empty( &the_thread_queue->Queues.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 ); } 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 return the_thread; } _ISR_Enable( level ); return NULL; }
static Thread_queue_Heads *_Thread_queue_Queue_enqueue( Thread_queue_Queue *queue, Thread_Control *the_thread, void ( *initialize )( Thread_queue_Heads *, Thread_Control * ), void ( *enqueue )( Thread_queue_Heads *, Thread_Control * ) ) { Thread_queue_Heads *heads; Thread_queue_Heads *spare_heads; heads = queue->heads; spare_heads = the_thread->Wait.spare_heads; the_thread->Wait.spare_heads = NULL; if ( heads == NULL ) { _Assert( spare_heads != NULL ); _Assert( _Chain_Is_empty( &spare_heads->Free_chain ) ); heads = spare_heads; queue->heads = heads; _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node ); ( *initialize )( heads, the_thread ); } else { _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node ); ( *enqueue )( heads, the_thread ); } return heads; }
void _POSIX_Threads_cancel_run( Thread_Control *the_thread ) { POSIX_Cancel_Handler_control *handler; Chain_Control *handler_stack; POSIX_API_Control *thread_support; ISR_Level level; thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ]; handler_stack = &thread_support->Cancellation_Handlers; thread_support->cancelability_state = PTHREAD_CANCEL_DISABLE; while ( !_Chain_Is_empty( handler_stack ) ) { _ISR_Disable( level ); handler = (POSIX_Cancel_Handler_control *) _Chain_Tail( handler_stack )->previous; _Chain_Extract_unprotected( &handler->Node ); _ISR_Enable( level ); (*handler->routine)( handler->arg ); _Workspace_Free( handler ); } }
void _Watchdog_Report_chain( const char *name, Chain_Control *header ) { ISR_Level level; Chain_Node *node; _ISR_Disable( level ); printk( "Watchdog Chain: %s %p\n", name, header ); if ( !_Chain_Is_empty( header ) ) { for ( node = _Chain_First( header ) ; node != _Chain_Tail(header) ; node = node->next ) { Watchdog_Control *watch = (Watchdog_Control *) node; _Watchdog_Report( NULL, watch ); } printk( "== end of %s \n", name ); } else { printk( "Chain is empty\n" ); } _ISR_Enable( level ); }
static void _Timer_server_Reset_tod_system_watchdog( Timer_server_Control *ts ) { ISR_Level level; _Timer_server_Stop_tod_system_watchdog( ts ); _ISR_Disable( level ); if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) { Watchdog_Interval delta_interval = _Watchdog_First( &ts->TOD_watchdogs.Chain )->delta_interval; _ISR_Enable( level ); /* * The unit is SECONDS here. */ _Watchdog_Insert_seconds( &ts->TOD_watchdogs.System_watchdog, delta_interval ); } else { _ISR_Enable( level ); } }
void *_Freechain_Get( Freechain_Control *freechain, Freechain_Allocator allocator, size_t number_nodes_to_extend, size_t node_size ) { _Assert( node_size >= sizeof( Chain_Node ) ); if ( _Chain_Is_empty( &freechain->Free ) && number_nodes_to_extend > 0 ) { void *starting_address; starting_address = ( *allocator )( number_nodes_to_extend * node_size ); number_nodes_to_extend *= ( starting_address != NULL ); _Chain_Initialize( &freechain->Free, starting_address, number_nodes_to_extend, node_size ); } return _Chain_Get_unprotected( &freechain->Free ); }
boolean _POSIX_signals_Clear_signals( POSIX_API_Control *api, int signo, siginfo_t *info, boolean is_global, boolean check_blocked ) { sigset_t mask; sigset_t signals_blocked; ISR_Level level; boolean do_callout; POSIX_signals_Siginfo_node *psiginfo; mask = signo_to_mask( signo ); do_callout = FALSE; /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK * insures that no signals are blocked and all are checked. */ if ( check_blocked ) signals_blocked = ~api->signals_blocked; else signals_blocked = SIGNAL_ALL_MASK; /* XXX this is not right for siginfo type signals yet */ /* XXX since they can't be cleared the same way */ _ISR_Disable( level ); if ( is_global ) { if ( mask & (_POSIX_signals_Pending & signals_blocked) ) { if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { psiginfo = (POSIX_signals_Siginfo_node *) _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] ); if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) ) _POSIX_signals_Clear_process_signals( mask ); if ( psiginfo ) { *info = psiginfo->Info; _Chain_Append_unprotected( &_POSIX_signals_Inactive_siginfo, &psiginfo->Node ); } else do_callout = FALSE; } else _POSIX_signals_Clear_process_signals( mask ); do_callout = TRUE; } } else { if ( mask & (api->signals_pending & signals_blocked) ) { api->signals_pending &= ~mask; do_callout = TRUE; } } _ISR_Enable( level ); return do_callout; }
static Thread_Control *_Thread_queue_FIFO_first( Thread_queue_Heads *heads ) { Chain_Control *fifo = &heads->Heads.Fifo; return _Chain_Is_empty( fifo ) ? NULL : THREAD_CHAIN_NODE_TO_THREAD( _Chain_First( fifo ) ); }
Thread_Control *_Thread_queue_First_fifo( Thread_queue_Control *the_thread_queue ) { if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) return (Thread_Control *) _Chain_First( &the_thread_queue->Queues.Fifo ); return NULL; }
Thread_Control *_Thread_queue_Dequeue( Thread_queue_Control *the_thread_queue ) { Thread_Control *the_thread; ISR_lock_Context lock_context; Thread_blocking_operation_States sync_state; the_thread = NULL; _Thread_queue_Acquire( &lock_context ); /* * Invoke the discipline specific dequeue method. */ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) { if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) { the_thread = (Thread_Control *) _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo ); } } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */ RBTree_Node *first; first = _RBTree_Get( &the_thread_queue->Queues.Priority, RBT_LEFT ); if ( first ) { the_thread = THREAD_RBTREE_NODE_TO_THREAD( first ); _Thread_Priority_restore_default_change_handler( the_thread ); _Thread_Lock_restore_default( the_thread ); } } if ( the_thread == NULL ) { /* * We did not find a thread to unblock in the queue. Maybe the executing * thread is about to block on this thread queue. */ sync_state = the_thread_queue->sync_state; if ( (sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) || (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) ) { the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED; the_thread = _Thread_Executing; } else { _Thread_queue_Release( &lock_context ); return NULL; } } /* * We found a thread to unblock. * * NOTE: This is invoked with interrupts still disabled. */ _Thread_blocking_operation_Finalize( the_thread, &lock_context ); return the_thread; }
Chain_Node *_Chain_Get( Chain_Control *the_chain ) { Chain_Node *return_node; return_node = NULL; if ( !_Chain_Is_empty( the_chain ) ) return_node = _Chain_Get_first_unprotected( the_chain ); return return_node; }
static Thread_Control *_Thread_queue_FIFO_first( Thread_queue_Heads *heads ) { Chain_Control *fifo = &heads->Heads.Fifo; Chain_Node *first; _Assert( !_Chain_Is_empty( fifo ) ); first = _Chain_First( fifo ); return THREAD_CHAIN_NODE_TO_THREAD( first ); }
Thread_Control *_Thread_queue_Dequeue( Thread_queue_Control *the_thread_queue ) { Thread_Control *the_thread; ISR_Level level; Thread_blocking_operation_States sync_state; the_thread = NULL; _ISR_Disable( level ); /* * Invoke the discipline specific dequeue method. */ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) { if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) { the_thread = (Thread_Control *) _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo ); } } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */ RBTree_Node *first; first = _RBTree_Get( &the_thread_queue->Queues.Priority, RBT_LEFT ); if ( first ) { the_thread = THREAD_RBTREE_NODE_TO_THREAD( first ); } } /* * We did not find a thread to unblock. */ if ( !the_thread ) { sync_state = the_thread_queue->sync_state; if ( (sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) || (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) ) { the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED; the_thread = _Thread_Executing; } _ISR_Enable( level ); return NULL; } /* * We found a thread to unblock. * * NOTE: This is invoked with interrupts still disabled. */ _Thread_blocking_operation_Finalize( the_thread, level ); return the_thread; }
Chain_Node *_Chain_Get( Chain_Control *the_chain ) { ISR_Level level; Chain_Node *return_node; return_node = NULL; _ISR_Disable( level ); if ( !_Chain_Is_empty( the_chain ) ) return_node = _Chain_Get_first_unprotected( the_chain ); _ISR_Enable( level ); return return_node; }
static Thread_Control *_Thread_queue_FIFO_first( Thread_queue_Heads *heads ) { Chain_Control *fifo; Chain_Node *first; Scheduler_Node *scheduler_node; fifo = &heads->Heads.Fifo; _Assert( !_Chain_Is_empty( fifo ) ); first = _Chain_First( fifo ); scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( first ); return _Scheduler_Node_get_owner( scheduler_node ); }
Thread_Control *_Thread_queue_First_priority ( Thread_queue_Control *the_thread_queue ) { uint32_t index; for( index=0 ; index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; index++ ) { if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) return (Thread_Control *) the_thread_queue->Queues.Priority[ index ].first; } return NULL; }
void pthread_cleanup_pop( int execute ) { POSIX_Cancel_Handler_control *handler; POSIX_Cancel_Handler_control tmp_handler; Chain_Control *handler_stack; POSIX_API_Control *thread_support; ISR_Level level; thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; handler_stack = &thread_support->Cancellation_Handlers; /* * We need interrupts disabled to safely check the chain and pull * the last element off. But we also need dispatching disabled to * ensure that we do not get prempted and deleted while we are holding * memory that needs to be freed. */ _Thread_Disable_dispatch(); _ISR_Disable( level ); if ( _Chain_Is_empty( handler_stack ) ) { _Thread_Enable_dispatch(); _ISR_Enable( level ); return; } handler = (POSIX_Cancel_Handler_control *) _Chain_Tail( handler_stack )->previous; _Chain_Extract_unprotected( &handler->Node ); _ISR_Enable( level ); tmp_handler = *handler; _Workspace_Free( handler ); _Thread_Enable_dispatch(); if ( execute ) (*tmp_handler.routine)( tmp_handler.arg ); }
static void _Timer_server_Get_watchdogs_that_fire_now( Timer_server_Control *ts, Chain_Control *insert_chain, Chain_Control *fire_chain ) { /* * Afterwards all timer inserts are directed to this chain and the interval * and TOD chains will be no more modified by other parties. */ ts->insert_chain = insert_chain; while ( true ) { ISR_Level level; /* * Remove all the watchdogs that need to fire so we can invoke them. */ _Timer_server_Process_interval_watchdogs( &ts->Interval_watchdogs, fire_chain ); _Timer_server_Process_tod_watchdogs( &ts->TOD_watchdogs, fire_chain ); /* * The insertions have to take place here, because they reference the * current time. The previous process methods take a snapshot of the * current time. In case someone inserts a watchdog with an initial value * of zero it will be processed in the next iteration of the timer server * body loop. */ _Timer_server_Process_insertions( ts ); _ISR_Disable( level ); if ( _Chain_Is_empty( insert_chain ) ) { ts->insert_chain = NULL; _ISR_Enable( level ); break; } else { _ISR_Enable( level ); } } }
static Thread_Control *_Thread_queue_Priority_first( Thread_queue_Heads *heads ) { Thread_queue_Priority_queue *priority_queue; RBTree_Node *first; #if defined(RTEMS_SMP) _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) ); priority_queue = (Thread_queue_Priority_queue *) _Chain_First( &heads->Heads.Fifo ); #else priority_queue = &heads->Heads.Priority; #endif _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) ); first = _RBTree_Minimum( &priority_queue->Queue ); return THREAD_RBTREE_NODE_TO_THREAD( first ); }
ER ref_mbx( T_RMBX *pk_rmbx, ID mbxid ) { register ITRON_Mailbox_Control *the_mailbox; Objects_Locations location; Chain_Control *pending; if ( !pk_rmbx ) return E_PAR; the_mailbox = _ITRON_Mailbox_Get( mbxid, &location ); switch ( location ) { #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: return _ITRON_Mailbox_Clarify_get_id_error( mbxid ); case OBJECTS_LOCAL: pending = &the_mailbox->message_queue.Pending_messages; if ( _Chain_Is_empty( pending ) ) pk_rmbx->pk_msg = NULL; else pk_rmbx->pk_msg = (T_MSG *) pending->first; /* * Fill in whether or not there is a waiting task */ if ( !_Thread_queue_First( &the_mailbox->message_queue.Wait_queue ) ) pk_rmbx->wtsk = FALSE; else pk_rmbx->wtsk = TRUE; break; } _ITRON_return_errorno( E_OK ); }
static void _Thread_queue_Queue_extract( Thread_queue_Queue *queue, Thread_queue_Heads *heads, Thread_Control *the_thread, void ( *extract )( Thread_queue_Heads *, Thread_Control * ) ) { _Assert( heads != NULL ); the_thread->Wait.spare_heads = RTEMS_CONTAINER_OF( _Chain_Get_first_unprotected( &heads->Free_chain ), Thread_queue_Heads, Free_node ); if ( _Chain_Is_empty( &heads->Free_chain ) ) { queue->heads = NULL; } ( *extract )( heads, the_thread ); }
void _POSIX_signals_Clear_process_signals( int signo ) { sigset_t mask; bool clear_signal; clear_signal = true; mask = signo_to_mask( signo ); ISR_Level level; _ISR_Disable( level ); if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { if ( !_Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) ) clear_signal = false; } if ( clear_signal ) { _POSIX_signals_Pending &= ~mask; } _ISR_Enable( level ); }
static Thread_Control *_Thread_queue_Priority_first( Thread_queue_Heads *heads ) { Thread_queue_Priority_queue *priority_queue; RBTree_Node *first; Scheduler_Node *scheduler_node; #if defined(RTEMS_SMP) _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) ); priority_queue = (Thread_queue_Priority_queue *) _Chain_First( &heads->Heads.Fifo ); #else priority_queue = &heads->Heads.Priority; #endif _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) ); first = _RBTree_Minimum( &priority_queue->Queue ); scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( first ); return _Scheduler_Node_get_owner( scheduler_node ); }
static void test_chain_iterator( void ) { Chain_Control chain; Chain_Iterator_registry reg; Chain_Iterator fit; Chain_Iterator bit; Chain_Node a; Chain_Node b; Chain_Node c; puts( "INIT - Verify Chain_Iterator" ); rtems_test_assert( _Chain_Is_empty( &static_reg.Iterators )); _Chain_Initialize_empty( &chain ); _Chain_Iterator_registry_initialize( ® ); _Chain_Iterator_initialize( &chain, ®, &fit, CHAIN_ITERATOR_FORWARD ); _Chain_Iterator_initialize( &chain, ®, &bit, CHAIN_ITERATOR_BACKWARD ); rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain )); rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain )); _Chain_Iterator_set_position( &fit, _Chain_Head( &chain ) ); _Chain_Iterator_set_position( &bit, _Chain_Tail( &chain ) ); rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain )); rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain )); _Chain_Append_unprotected( &chain, &a ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &a ); _Chain_Append_unprotected( &chain, &b ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &b ); _Chain_Append_unprotected( &chain, &c ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &b ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); _Chain_Insert_unprotected( &a, &b ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &c ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &b ); _Chain_Append_unprotected( &chain, &c ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &a ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &b ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); _Chain_Prepend_unprotected( &chain, &a ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &a ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &b ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &b ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &c ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &c ); rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain )); rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain )); _Chain_Append_unprotected( &chain, &a ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &a ); _Chain_Append_unprotected( &chain, &b ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &b ); _Chain_Append_unprotected( &chain, &c ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &c ); update_registry_and_extract( ®, &c ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &b ); update_registry_and_extract( ®, &b ); rtems_test_assert( _Chain_Iterator_next( &fit ) == &a ); rtems_test_assert( _Chain_Iterator_next( &bit ) == &a ); update_registry_and_extract( ®, &a ); rtems_test_assert( _Chain_Iterator_next( &fit ) == _Chain_Tail( &chain )); rtems_test_assert( _Chain_Iterator_next( &bit ) == _Chain_Head( &chain )); rtems_test_assert( !_Chain_Is_empty( ®.Iterators )); _Chain_Iterator_destroy( &fit ); rtems_test_assert( !_Chain_Is_empty( ®.Iterators )); _Chain_Iterator_destroy( &bit ); rtems_test_assert( _Chain_Is_empty( ®.Iterators )); }
static void _Timer_server_Insert_timer_and_make_snapshot( Timer_server_Control *ts, Timer_Control *timer ) { Watchdog_Control *first_watchdog; Watchdog_Interval delta_interval; Watchdog_Interval last_snapshot; Watchdog_Interval snapshot; Watchdog_Interval delta; ISR_Level level; /* * We have to update the time snapshots here, because otherwise we may have * problems with the integer range of the delta values. The time delta DT * from the last snapshot to now may be arbitrarily long. The last snapshot * is the reference point for the delta chain. Thus if we do not update the * reference point we have to add DT to the initial delta of the watchdog * being inserted. This could result in an integer overflow. */ _Thread_Disable_dispatch(); if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) { /* * We have to advance the last known ticks value of the server and update * the watchdog chain accordingly. */ _ISR_Disable( level ); snapshot = _Watchdog_Ticks_since_boot; last_snapshot = ts->Interval_watchdogs.last_snapshot; if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) { first_watchdog = _Watchdog_First( &ts->Interval_watchdogs.Chain ); /* * We assume adequate unsigned arithmetic here. */ delta = snapshot - last_snapshot; delta_interval = first_watchdog->delta_interval; if (delta_interval > delta) { delta_interval -= delta; } else { delta_interval = 0; } first_watchdog->delta_interval = delta_interval; } ts->Interval_watchdogs.last_snapshot = snapshot; _ISR_Enable( level ); _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker ); if ( !ts->active ) { _Timer_server_Reset_interval_system_watchdog( ts ); } } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) { /* * We have to advance the last known seconds value of the server and update * the watchdog chain accordingly. */ _ISR_Disable( level ); snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch(); last_snapshot = ts->TOD_watchdogs.last_snapshot; if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) { first_watchdog = _Watchdog_First( &ts->TOD_watchdogs.Chain ); delta_interval = first_watchdog->delta_interval; if ( snapshot > last_snapshot ) { /* * We advanced in time. */ delta = snapshot - last_snapshot; if (delta_interval > delta) { delta_interval -= delta; } else { delta_interval = 0; } } else { /* * Someone put us in the past. */ delta = last_snapshot - snapshot; delta_interval += delta; } first_watchdog->delta_interval = delta_interval; } ts->TOD_watchdogs.last_snapshot = snapshot; _ISR_Enable( level ); _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker ); if ( !ts->active ) { _Timer_server_Reset_tod_system_watchdog( ts ); } } _Thread_Enable_dispatch(); }
/** * @brief Timer server body. * * This is the server for task based timers. This task executes whenever a * task-based timer should fire. It services both "after" and "when" timers. * It is not created automatically but must be created explicitly by the * application before task-based timers may be initiated. The parameter * @a arg points to the corresponding timer server control block. */ static rtems_task _Timer_server_Body( rtems_task_argument arg ) { Timer_server_Control *ts = (Timer_server_Control *) arg; Chain_Control insert_chain; Chain_Control fire_chain; _Chain_Initialize_empty( &insert_chain ); _Chain_Initialize_empty( &fire_chain ); while ( true ) { _Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain ); if ( !_Chain_Is_empty( &fire_chain ) ) { /* * Fire the watchdogs. */ while ( true ) { Watchdog_Control *watchdog; ISR_Level level; /* * It is essential that interrupts are disable here since an interrupt * service routine may remove a watchdog from the chain. */ _ISR_Disable( level ); watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain ); if ( watchdog != NULL ) { watchdog->state = WATCHDOG_INACTIVE; _ISR_Enable( level ); } else { _ISR_Enable( level ); break; } /* * The timer server may block here and wait for resources or time. * The system watchdogs are inactive and will remain inactive since * the active flag of the timer server is true. */ (*watchdog->routine)( watchdog->id, watchdog->user_data ); } } else { ts->active = false; /* * Block until there is something to do. */ _Thread_Disable_dispatch(); _Thread_Set_state( ts->thread, STATES_DELAYING ); _Timer_server_Reset_interval_system_watchdog( ts ); _Timer_server_Reset_tod_system_watchdog( ts ); _Thread_Enable_dispatch(); ts->active = true; /* * Maybe an interrupt did reset the system timers, so we have to stop * them here. Since we are active now, there will be no more resets * until we are inactive again. */ _Timer_server_Stop_interval_system_watchdog( ts ); _Timer_server_Stop_tod_system_watchdog( ts ); } } }
Thread_Control *_Thread_queue_Dequeue_priority( Thread_queue_Control *the_thread_queue ) { uint32_t index; ISR_Level level; Thread_Control *the_thread = NULL; /* just to remove warnings */ Thread_Control *new_first_thread; Chain_Node *head; Chain_Node *tail; Chain_Node *new_first_node; Chain_Node *new_second_node; Chain_Node *last_node; Chain_Node *next_node; Chain_Node *previous_node; _ISR_Disable( level ); for( index=0 ; index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; index++ ) { if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) { the_thread = (Thread_Control *) _Chain_First( &the_thread_queue->Queues.Priority[ index ] ); goto dequeue; } } /* * We did not find a thread to unblock. */ _ISR_Enable( level ); return NULL; dequeue: the_thread->Wait.queue = NULL; new_first_node = _Chain_First( &the_thread->Wait.Block2n ); new_first_thread = (Thread_Control *) new_first_node; next_node = the_thread->Object.Node.next; previous_node = the_thread->Object.Node.previous; if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) { last_node = _Chain_Last( &the_thread->Wait.Block2n ); new_second_node = new_first_node->next; 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 */ head = _Chain_Head( &new_first_thread->Wait.Block2n ); tail = _Chain_Tail( &new_first_thread->Wait.Block2n ); new_second_node->previous = head; head->next = new_second_node; tail->previous = last_node; last_node->next = tail; } } else { previous_node->next = next_node; next_node->previous = previous_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 ); } #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) _Thread_MP_Free_proxy( the_thread ); #endif return( the_thread ); }
void _Watchdog_Tickle( Chain_Control *header ) { ISR_Level level; Watchdog_Control *the_watchdog; Watchdog_States watchdog_state; /* * See the comment in watchdoginsert.c and watchdogadjust.c * about why it's safe not to declare header a pointer to * volatile data - till, 2003/7 */ _ISR_Disable( level ); if ( _Chain_Is_empty( header ) ) goto leave; the_watchdog = _Watchdog_First( header ); /* * For some reason, on rare occasions the_watchdog->delta_interval * of the head of the watchdog chain is 0. Before this test was * added, on these occasions an event (which usually was supposed * to have a timeout of 1 tick would have a delta_interval of 0, which * would be decremented to 0xFFFFFFFF by the unprotected * "the_watchdog->delta_interval--;" operation. * This would mean the event would not timeout, and also the chain would * be blocked, because a timeout with a very high number would be at the * head, rather than at the end. * The test "if (the_watchdog->delta_interval != 0)" * here prevents this from occuring. * * We were not able to categorically identify the situation that causes * this, but proved it to be true empirically. So this check causes * correct behaviour in this circumstance. * * The belief is that a race condition exists whereby an event at the head * of the chain is removed (by a pending ISR or higher priority task) * during the _ISR_Flash( level ); in _Watchdog_Insert, but the watchdog * to be inserted has already had its delta_interval adjusted to 0, and * so is added to the head of the chain with a delta_interval of 0. * * Steven Johnson - 12/2005 (gcc-3.2.3 -O3 on powerpc) */ if (the_watchdog->delta_interval != 0) { the_watchdog->delta_interval--; if ( the_watchdog->delta_interval != 0 ) goto leave; } do { watchdog_state = _Watchdog_Remove( the_watchdog ); _ISR_Enable( level ); switch( watchdog_state ) { case WATCHDOG_ACTIVE: (*the_watchdog->routine)( the_watchdog->id, the_watchdog->user_data ); break; case WATCHDOG_INACTIVE: /* * This state indicates that the watchdog is not on any chain. * Thus, it is NOT on a chain being tickled. This case should * never occur. */ break; case WATCHDOG_BEING_INSERTED: /* * This state indicates that the watchdog is in the process of * BEING inserted on the chain. Thus, it can NOT be on a chain * being tickled. This case should never occur. */ break; case WATCHDOG_REMOVE_IT: break; } _ISR_Disable( level ); the_watchdog = _Watchdog_First( header ); } while ( !_Chain_Is_empty( header ) && (the_watchdog->delta_interval == 0) ); leave: _ISR_Enable(level); }