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_Action *_Thread_Get_post_switch_action( Thread_Control *executing ) { Chain_Control *chain = &executing->Post_switch_actions.Chain; return (Thread_Action *) _Chain_Get_unprotected( chain ); }
rtems_chain_node *rtems_chain_get( rtems_chain_control *chain ) { rtems_chain_node *node; ISR_Level level; _ISR_lock_ISR_disable_and_acquire( &chain->Lock, level ); node = _Chain_Get_unprotected( &chain->Chain ); _ISR_lock_Release_and_ISR_enable( &chain->Lock, level ); return node; }
rtems_chain_node *rtems_chain_get( rtems_chain_control *chain ) { rtems_chain_node *node; rtems_interrupt_lock_context lock_context; chain_acquire( &lock_context ); node = _Chain_Get_unprotected( chain ); chain_release( &lock_context ); return node; }
void _Thread_Kill_zombies( void ) { ISR_lock_Context lock_context; Thread_Zombie_control *zombies = &_Thread_Zombies; Thread_Control *the_thread; _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context ); the_thread = (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain ); while ( the_thread != NULL ) { _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context ); _Thread_Wait_for_execution_stop( the_thread ); _Thread_Free( the_thread ); _ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context ); the_thread = (Thread_Control *) _Chain_Get_unprotected( &zombies->Chain ); } _ISR_lock_Release_and_ISR_enable( &zombies->Lock, &lock_context ); }
bool _POSIX_signals_Clear_signals( POSIX_API_Control *api, int signo, siginfo_t *info, bool is_global, bool check_blocked ) { sigset_t mask; sigset_t signals_blocked; ISR_Level level; bool 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 is this right for siginfo type signals? */ /* XXX are we sure they can 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 ] ); _POSIX_signals_Clear_process_signals( signo ); /* * It may be impossible to get here with an empty chain * BUT until that is proven we need to be defensive and * protect against it. */ if ( psiginfo ) { *info = psiginfo->Info; _Chain_Append_unprotected( &_POSIX_signals_Inactive_siginfo, &psiginfo->Node ); } else do_callout = false; } _POSIX_signals_Clear_process_signals( signo ); do_callout = true; } } else { if ( mask & (api->signals_pending & signals_blocked) ) { api->signals_pending &= ~mask; do_callout = true; } } _ISR_Enable( level ); return do_callout; }
/** * @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_MP_Allocate_proxy ( States_Control the_state ) { Thread_Proxy_control *the_proxy; ISR_lock_Context lock_context; _Thread_MP_Proxies_acquire( &lock_context ); the_proxy = (Thread_Proxy_control *) _Chain_Get_unprotected( &_Thread_MP_Inactive_proxies ); if ( the_proxy != NULL ) { Thread_Control *executing; MP_packet_Prefix *receive_packet; Objects_Id source_tid; executing = _Thread_Executing; receive_packet = _MPCI_Receive_server_tcb->receive_packet; source_tid = receive_packet->source_tid; executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING; the_proxy->receive_packet = receive_packet; the_proxy->Object.id = source_tid; the_proxy->current_priority = receive_packet->source_priority; the_proxy->current_state = _States_Set( STATES_DORMANT, the_state ); the_proxy->Wait.count = executing->Wait.count; the_proxy->Wait.return_argument = executing->Wait.return_argument; the_proxy->Wait.return_argument_second = executing->Wait.return_argument_second; the_proxy->Wait.option = executing->Wait.option; the_proxy->Wait.return_code = executing->Wait.return_code; the_proxy->Wait.timeout_code = executing->Wait.timeout_code; the_proxy->thread_queue_callout = _Thread_queue_MP_callout_do_nothing; _RBTree_Insert_inline( &_Thread_MP_Active_proxies, &the_proxy->Active, &source_tid, _Thread_MP_Proxy_less ); _Thread_MP_Proxies_release( &lock_context ); return (Thread_Control *) the_proxy; } _Thread_MP_Proxies_release( &lock_context ); _Terminate( INTERNAL_ERROR_CORE, true, INTERNAL_ERROR_OUT_OF_PROXIES ); /* * NOTE: The following return ensures that the compiler will * think that all paths return a value. */ return NULL; }