void __ISR_Handler( uint32_t vector) { ISR_Level level; _ISR_Disable( level ); _Thread_Dispatch_disable_level++; #if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) if ( _ISR_Nest_level == 0 ) { /* Install irq stack */ _old_stack_ptr = stack_ptr; stack_ptr = _CPU_Interrupt_stack_high; } #endif _ISR_Nest_level++; _ISR_Enable( level ); /* call isp */ if ( _ISR_Vector_table[ vector]) (*_ISR_Vector_table[ vector ])( vector ); _ISR_Disable( level ); _Thread_Dispatch_disable_level--; _ISR_Nest_level--; #if(CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) if ( _ISR_Nest_level == 0 ) /* restore old stack pointer */ stack_ptr = _old_stack_ptr; #endif _ISR_Enable( level ); if ( _ISR_Nest_level ) return; if ( _Thread_Dispatch_disable_level ) { _ISR_Signals_to_thread_executing = FALSE; return; } if ( _Context_Switch_necessary || _ISR_Signals_to_thread_executing ) { _ISR_Signals_to_thread_executing = FALSE; _Thread_Dispatch(); } }
void __ISR_Handler( uint32_t vector) { ISR_Level level; _ISR_Disable( level ); _Thread_Dispatch_increment_disable_level(); #if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) if ( _ISR_Nest_level == 0 ) { /* Install irq stack */ _old_stack_ptr = stack_ptr; stack_ptr = _CPU_Interrupt_stack_high; } #endif _ISR_Nest_level++; _ISR_Enable( level ); /* call isp */ if ( _ISR_Vector_table[ vector]) (*_ISR_Vector_table[ vector ])( vector ); _ISR_Disable( level ); _Thread_Dispatch_decrement_disable_level(); _ISR_Nest_level--; #if (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) if ( _ISR_Nest_level == 0 ) /* restore old stack pointer */ stack_ptr = _old_stack_ptr; #endif _ISR_Enable( level ); if ( _ISR_Nest_level ) return; if ( _Thread_Dispatch_in_critical_section() ) { return; } if ( _Thread_Dispatch_necessary ) { _Thread_Dispatch(); } }
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; }
void _CORE_barrier_Wait( CORE_barrier_Control *the_barrier, Thread_Control *executing, Objects_Id id, bool wait, Watchdog_Interval timeout, CORE_barrier_API_mp_support_callout api_barrier_mp_support ) { ISR_Level level; executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL; _ISR_Disable( level ); the_barrier->number_of_waiting_threads++; if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) { if ( the_barrier->number_of_waiting_threads == the_barrier->Attributes.maximum_count) { executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED; _ISR_Enable( level ); _CORE_barrier_Release( the_barrier, id, api_barrier_mp_support ); return; } } _Thread_queue_Enter_critical_section( &the_barrier->Wait_queue ); executing->Wait.queue = &the_barrier->Wait_queue; executing->Wait.id = id; _ISR_Enable( level ); _Thread_queue_Enqueue( &the_barrier->Wait_queue, timeout ); }
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 ); } }
Thread_blocking_operation_States _Thread_queue_Enqueue_fifo ( Thread_queue_Control *the_thread_queue, Thread_Control *the_thread, ISR_Level *level_p ) { Thread_blocking_operation_States sync_state; ISR_Level level; _ISR_Disable( level ); sync_state = the_thread_queue->sync_state; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; if (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) { _Chain_Append_unprotected( &the_thread_queue->Queues.Fifo, &the_thread->Object.Node ); the_thread->Wait.queue = the_thread_queue; the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED; _ISR_Enable( level ); return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED; } /* * An interrupt completed the thread's blocking request. * For example, the blocking thread could have been given * the mutex by an ISR or timed out. * * WARNING! Returning with interrupts disabled! */ *level_p = level; return sync_state; }
static void _RTEMS_Tasks_Dispatch_if_necessary( Thread_Control *executing, bool needs_asr_dispatching ) { if ( _Thread_Dispatch_is_enabled() ) { bool dispatch_necessary = needs_asr_dispatching; /* * FIXME: This locking approach is brittle. It only works since the * current simple SMP scheduler has no support for the non-preempt mode. */ #if defined( RTEMS_SMP ) ISR_Level level; _ISR_Disable( level ); #endif if ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) { dispatch_necessary = true; _Thread_Dispatch_necessary = dispatch_necessary; } #if defined( RTEMS_SMP ) _ISR_Enable( level ); #endif if ( dispatch_necessary ) { _Thread_Dispatch(); } } }
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 ); }
void _CPU_ISR_install_vector( uint32_t vector, proc_ptr new_handler, proc_ptr *old_handler ) { proc_ptr *table = (proc_ptr *) bsp_start_vector_table_begin; proc_ptr current_handler; ISR_Level level; _ISR_Disable( level ); current_handler = table [vector]; /* The current handler is now the old one */ if (old_handler != NULL) { *old_handler = (proc_ptr) current_handler; } /* Write only if necessary to avoid writes to a maybe read-only memory */ if (current_handler != new_handler) { table [vector] = new_handler; } _ISR_Enable( level ); }
uint32_t _Thread_Dispatch_increment_disable_level( void ) { Giant_Control *giant = &_Giant; ISR_Level isr_level; uint32_t self_cpu_index; uint32_t disable_level; Per_CPU_Control *self_cpu; _ISR_Disable( isr_level ); /* * We must obtain the processor ID after interrupts are disabled to prevent * thread migration. */ self_cpu_index = _SMP_Get_current_processor(); _Giant_Do_acquire( self_cpu_index ); self_cpu = _Per_CPU_Get_by_index( self_cpu_index ); disable_level = self_cpu->thread_dispatch_disable_level; ++disable_level; self_cpu->thread_dispatch_disable_level = disable_level; _ISR_Enable( isr_level ); return disable_level; }
uint32_t _Thread_Dispatch_set_disable_level(uint32_t value) { ISR_Level isr_level; uint32_t disable_level; _ISR_Disable( isr_level ); disable_level = _Thread_Dispatch_disable_level; _ISR_Enable( isr_level ); /* * If we need the dispatch level to go higher * call increment method the desired number of times. */ while ( value > disable_level ) { disable_level = _Thread_Dispatch_increment_disable_level(); } /* * If we need the dispatch level to go lower * call increment method the desired number of times. */ while ( value < disable_level ) { disable_level = _Thread_Dispatch_decrement_disable_level(); } return value; }
void _Thread_queue_Requeue( Thread_queue_Control *the_thread_queue, Thread_Control *the_thread ) { /* * Just in case the thread really wasn't blocked on a thread queue * when we get here. */ if ( !the_thread_queue ) return; /* * If queueing by FIFO, there is nothing to do. This only applies to * priority blocking discipline. */ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) { Thread_queue_Control *tq = the_thread_queue; ISR_Level level; ISR_Level level_ignored; _ISR_Disable( level ); if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) { _Thread_queue_Enter_critical_section( tq ); _Thread_queue_Extract_priority_helper( tq, the_thread, true ); (void) _Thread_queue_Enqueue_priority( tq, the_thread, &level_ignored ); } _ISR_Enable( level ); } }
void _API_Mutex_Lock( API_Mutex_Control *the_mutex ) { bool previous_thread_life_protection; ISR_Level level; previous_thread_life_protection = _Thread_Set_life_protection( true ); #if defined(RTEMS_SMP) _Thread_Disable_dispatch(); #endif _ISR_Disable( level ); _CORE_mutex_Seize( &the_mutex->Mutex, _Thread_Executing, the_mutex->Object.id, true, 0, level ); if ( the_mutex->Mutex.nest_count == 1 ) { the_mutex->previous_thread_life_protection = previous_thread_life_protection; } #if defined(RTEMS_SMP) _Thread_Enable_dispatch(); #endif }
void _Thread_Reset_timeslice( void ) { ISR_Level level; Thread_Control *executing; Chain_Control *ready; executing = _Thread_Executing; ready = executing->ready; _ISR_Disable( level ); if ( _Chain_Has_only_one_node( ready ) ) { _ISR_Enable( level ); return; } _Chain_Extract_unprotected( &executing->Object.Node ); _Chain_Append_unprotected( ready, &executing->Object.Node ); _ISR_Flash( level ); if ( _Thread_Is_heir( executing ) ) _Thread_Heir = (Thread_Control *) ready->first; _Context_Switch_necessary = true; _ISR_Enable( level ); }
Objects_Control *_Objects_Get_isr_disable( Objects_Information *information, Objects_Id id, Objects_Locations *location, ISR_Level *level_p ) { Objects_Control *the_object; uint32_t index; ISR_Level level; index = id - information->minimum_id + 1; _ISR_Disable( level ); if ( information->maximum >= index ) { if ( (the_object = information->local_table[ index ]) != NULL ) { *location = OBJECTS_LOCAL; *level_p = level; return the_object; } _ISR_Enable( level ); *location = OBJECTS_ERROR; return NULL; } _ISR_Enable( level ); *location = OBJECTS_ERROR; #if defined(RTEMS_MULTIPROCESSING) _Objects_MP_Is_remote( information, id, location, &the_object ); return the_object; #else return NULL; #endif }
void _Scheduler_priority_Yield(void) { Scheduler_priority_Per_thread *sched_info; ISR_Level level; Thread_Control *executing; Chain_Control *ready; executing = _Thread_Executing; sched_info = (Scheduler_priority_Per_thread *) executing->scheduler_info; ready = sched_info->ready_chain; _ISR_Disable( level ); if ( !_Chain_Has_only_one_node( ready ) ) { _Chain_Extract_unprotected( &executing->Object.Node ); _Chain_Append_unprotected( ready, &executing->Object.Node ); _ISR_Flash( level ); if ( _Thread_Is_heir( executing ) ) _Thread_Heir = (Thread_Control *) _Chain_First( ready ); _Thread_Dispatch_necessary = true; } else if ( !_Thread_Is_heir( executing ) ) _Thread_Dispatch_necessary = true; _ISR_Enable( level ); }
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 ); } }
boolean _Watchdog_Insert_ticks_helper( Watchdog_Control *timer, Watchdog_Interval ticks, Objects_Id id, Watchdog_Service_routine_entry TSR, void *arg ) { ISR_Level level; (void) _Watchdog_Remove( timer ); _ISR_Disable( level ); /* * Check to see if the watchdog has just been inserted by a * higher priority interrupt. If so, abandon this insert. */ if ( timer->state != WATCHDOG_INACTIVE ) { _ISR_Enable( level ); return FALSE; } /* * OK. Now we now the timer was not rescheduled by an interrupt * so we can atomically initialize it as in use. */ _Watchdog_Initialize( timer, TSR, id, arg ); _Watchdog_Insert_ticks( timer, ticks ); _ISR_Enable( level ); return TRUE; }
void _Thread_Set_transient( Thread_Control *the_thread ) { ISR_Level level; uint32_t old_state; Chain_Control *ready; ready = the_thread->ready; _ISR_Disable( level ); old_state = the_thread->current_state; the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state ); if ( _States_Is_ready( old_state ) ) { if ( _Chain_Has_only_one_node( ready ) ) { _Chain_Initialize_empty( ready ); _Priority_Remove_from_bit_map( &the_thread->Priority_map ); } else _Chain_Extract_unprotected( &the_thread->Object.Node ); } _ISR_Enable( level ); }
rtems_status_code rtems_timer_fire_after( rtems_id id, rtems_interval ticks, rtems_timer_service_routine_entry routine, void *user_data ) { Timer_Control *the_timer; Objects_Locations location; ISR_Level level; if ( ticks == 0 ) return RTEMS_INVALID_NUMBER; if ( !routine ) return RTEMS_INVALID_ADDRESS; the_timer = _Timer_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Timer_Cancel( the_timer ); _ISR_Disable( level ); /* * Check to see if the watchdog has just been inserted by a * higher priority interrupt. If so, abandon this insert. */ if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { _ISR_Enable( level ); _Objects_Put( &the_timer->Object ); return RTEMS_SUCCESSFUL; } /* * OK. Now we now the timer was not rescheduled by an interrupt * so we can atomically initialize it as in use. */ the_timer->the_class = TIMER_INTERVAL; _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); _ISR_Enable( level ); _Watchdog_Insert_ticks( &the_timer->Ticker, ticks ); _Objects_Put( &the_timer->Object ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* should never return this */ #endif case OBJECTS_ERROR: break; } return RTEMS_INVALID_ID; }
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; }
unsigned int sh_set_irq_priority( unsigned int irq, unsigned int prio ) { uint32_t shiftcount; uint32_t prioreg; uint16_t temp16; ISR_Level level; /* * first check for valid interrupt */ if (( irq > 113) || (_Hardware_isr_Table[irq] == _dummy_isp)) return -1; /* * check for valid irq priority */ if ( prio > 15 ) return -1; /* * look up appropriate interrupt priority register */ if ( irq > 71) { irq = irq - 72; shiftcount = 12 - ((irq & ~0x03) % 16); switch( irq / 16) { case 0: { prioreg = INTC_IPRC; break;} case 1: { prioreg = INTC_IPRD; break;} case 2: { prioreg = INTC_IPRE; break;} default: return -1; } } else { shiftcount = 12 - 4 * ( irq % 4); if ( irq > 67) prioreg = INTC_IPRB; else prioreg = INTC_IPRA; } /* * Set the interrupt priority register */ _ISR_Disable( level ); temp16 = read16( prioreg); temp16 &= ~( 15 << shiftcount); temp16 |= prio << shiftcount; write16( temp16, prioreg); _ISR_Enable( level ); return 0; }
rtems_interrupt_level rtems_interrupt_disable( void ) { rtems_interrupt_level previous_level; _ISR_Disable( previous_level ); return previous_level; }
void _CPU_cache_invalidate_1_instruction_line(const void *d_addr) { ISR_Level level; _ISR_Disable (level); _CPU_OR1K_Cache_instruction_block_invalidate(d_addr); _ISR_Enable(level); }
void _Giant_Acquire( void ) { ISR_Level isr_level; _ISR_Disable( isr_level ); _Assert( _Thread_Dispatch_disable_level != 0 ); _Giant_Do_acquire( _SMP_Get_current_processor() ); _ISR_Enable( isr_level ); }
static void block_op(Thread_Control *thread) { const Scheduler_Control *scheduler = _Scheduler_Get(thread); ISR_Level level; _ISR_Disable( level ); (*scheduler->Operations.block)(scheduler, thread); _ISR_Enable( level ); }
void _Giant_Release( void ) { ISR_Level isr_level; _ISR_Disable( isr_level ); _Assert( _Thread_Dispatch_disable_level != 0 ); _Giant_Do_release(); _ISR_Enable( isr_level ); }
static inline void _CPU_OR1K_Cache_data_block_writeback(const void *d_addr) { ISR_Level level; _ISR_Disable (level); _OR1K_mtspr(CPU_OR1K_SPR_DCBWR, (uintptr_t) d_addr); _ISR_Enable(level); }
static void _POSIX_signals_Post_switch_hook( Thread_Control *the_thread ) { POSIX_API_Control *api; int signo; ISR_Level level; int hold_errno; Thread_Control *executing; executing = _Thread_Get_executing(); api = the_thread->API_Extensions[ THREAD_API_POSIX ]; /* * We need to ensure that if the signal handler executes a call * which overwrites the unblocking status, we restore it. */ hold_errno = executing->Wait.return_code; /* * api may be NULL in case of a thread close in progress */ if ( !api ) return; /* * If we invoke any user code, there is the possibility that * a new signal has been posted that we should process so we * restart the loop if a signal handler was invoked. * * The first thing done is to check there are any signals to be * processed at all. No point in doing this loop otherwise. */ while (1) { _ISR_Disable( level ); if ( !(~api->signals_blocked & (api->signals_pending | _POSIX_signals_Pending)) ) { _ISR_Enable( level ); break; } _ISR_Enable( level ); for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */ for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { _POSIX_signals_Check_signal( api, signo, false ); _POSIX_signals_Check_signal( api, signo, true ); } } executing->Wait.return_code = hold_errno; }