States_Control _Thread_Set_state( Thread_Control *the_thread, States_Control state ) { ISR_lock_Context lock_context; States_Control previous_state; States_Control next_state; _Assert( state != 0 ); _Thread_State_acquire( the_thread, &lock_context ); previous_state = the_thread->current_state; next_state = _States_Set( state, previous_state); the_thread->current_state = next_state; if ( _States_Is_ready( previous_state ) ) { _Scheduler_Block( the_thread ); } _Thread_State_release( the_thread, &lock_context ); return previous_state; }
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 ); }
void _Scheduler_priority_Tick( void ) { Thread_Control *executing; executing = _Thread_Executing; #ifdef __RTEMS_USE_TICKS_FOR_STATISTICS__ /* * Increment the number of ticks this thread has been executing */ executing->cpu_time_used++; #endif /* * If the thread is not preemptible or is not ready, then * just return. */ if ( !executing->is_preemptible ) return; if ( !_States_Is_ready( executing->current_state ) ) return; /* * The cpu budget algorithm determines what happens next. */ switch ( executing->budget_algorithm ) { case THREAD_CPU_BUDGET_ALGORITHM_NONE: break; case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE: #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE) case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE: #endif if ( (int)(--executing->cpu_time_budget) <= 0 ) { /* * A yield performs the ready chain mechanics needed when * resetting a timeslice. If no other thread's are ready * at the priority of the currently executing thread, then the * executing thread's timeslice is reset. Otherwise, the * currently executing thread is placed at the rear of the * FIFO for this priority and a new heir is selected. */ _Scheduler_Yield(); executing->cpu_time_budget = _Thread_Ticks_per_timeslice; } break; #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT: if ( --executing->cpu_time_budget == 0 ) (*executing->budget_callout)( executing ); break; #endif } }
bool _Scheduler_priority_affinity_SMP_Set_affinity( const Scheduler_Control *scheduler, Thread_Control *thread, size_t cpusetsize, const cpu_set_t *cpuset ) { Scheduler_priority_affinity_SMP_Node *node; States_Control current_state; /* * Validate that the cpset meets basic requirements. */ if ( !_CPU_set_Is_valid( cpuset, cpusetsize ) ) { return false; } node = _Scheduler_priority_affinity_SMP_Thread_get_node( thread ); /* * The old and new set are the same, there is no point in * doing anything. */ if ( CPU_EQUAL_S( cpusetsize, cpuset, node->Affinity.set ) ) return true; current_state = thread->current_state; if ( _States_Is_ready( current_state ) ) { _Scheduler_priority_affinity_SMP_Block( scheduler, thread ); } CPU_COPY( node->Affinity.set, cpuset ); if ( _States_Is_ready( current_state ) ) { /* * FIXME: Do not ignore threads in need for help. */ (void) _Scheduler_priority_affinity_SMP_Unblock( scheduler, thread ); } return true; }
void _Thread_Tickle_timeslice( void ) { Thread_Control *executing; executing = _Thread_Executing; #ifdef __RTEMS_USE_TICKS_FOR_STATISTICS__ /* * Increment the number of ticks this thread has been executing */ executing->cpu_time_used++; #endif /* * If the thread is not preemptible or is not ready, then * just return. */ if ( !executing->is_preemptible ) return; if ( !_States_Is_ready( executing->current_state ) ) return; /* * The cpu budget algorithm determines what happens next. */ switch ( executing->budget_algorithm ) { case THREAD_CPU_BUDGET_ALGORITHM_NONE: break; case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE: #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE) case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE: #endif if ( (int)(--executing->cpu_time_budget) <= 0 ) { _Thread_Reset_timeslice(); executing->cpu_time_budget = _Thread_Ticks_per_timeslice; } break; #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT: if ( --executing->cpu_time_budget == 0 ) (*executing->budget_callout)( executing ); break; #endif } }
bool _Thread_Evaluate_mode( void ) { Thread_Control *executing; executing = _Thread_Executing; if ( !_States_Is_ready( executing->current_state ) || ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) ) { _Context_Switch_necessary = true; return true; } return false; }
void _Thread_Resume( Thread_Control *the_thread, bool force ) { ISR_Level level; States_Control current_state; _ISR_Disable( level ); #if defined(RTEMS_ITRON_API) if ( force == true ) the_thread->suspend_count = 0; else the_thread->suspend_count--; if ( the_thread->suspend_count > 0 ) { _ISR_Enable( level ); return; } #endif current_state = the_thread->current_state; if ( current_state & STATES_SUSPENDED ) { current_state = the_thread->current_state = _States_Clear(STATES_SUSPENDED, current_state); if ( _States_Is_ready( current_state ) ) { _Priority_Add_to_bit_map( &the_thread->Priority_map ); _Chain_Append_unprotected(the_thread->ready, &the_thread->Object.Node); _ISR_Flash( level ); if ( the_thread->current_priority < _Thread_Heir->current_priority ) { _Thread_Heir = the_thread; if ( _Thread_Executing->is_preemptible || the_thread->current_priority == 0 ) _Context_Switch_necessary = true; } } } _ISR_Enable( level ); }
void _Thread_Clear_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; States_Control current_state; _ISR_Disable( level ); current_state = the_thread->current_state; if ( current_state & state ) { current_state = the_thread->current_state = _States_Clear( state, current_state ); if ( _States_Is_ready( current_state ) ) { _Priority_Add_to_bit_map( &the_thread->Priority_map ); _Chain_Append_unprotected(the_thread->ready, &the_thread->Object.Node); _ISR_Flash( level ); /* * If the thread that was unblocked is more important than the heir, * then we have a new heir. This may or may not result in a * context switch. * * Normal case: * If the current thread is preemptible, then we need to do * a context switch. * Pseudo-ISR case: * Even if the thread isn't preemptible, if the new heir is * a pseudo-ISR system task, 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 || the_thread->current_priority == 0 ) _Context_Switch_necessary = true; } } } _ISR_Enable( level ); }
void _Thread_Set_transient( Thread_Control *the_thread ) { ISR_Level level; uint32_t old_state; _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 ) ) { _Scheduler_Extract( the_thread ); } _ISR_Enable( level ); }
/* * INTERRUPT LATENCY: * priority map * select heir */ void _Thread_Clear_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; States_Control current_state; _ISR_Disable( level ); current_state = the_thread->current_state; if ( current_state & state ) { current_state = the_thread->current_state = _States_Clear( state, current_state ); if ( _States_Is_ready( current_state ) ) { _Scheduler_Unblock( the_thread ); } } _ISR_Enable( level ); }
void _Thread_Set_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; States_Control current_state; _ISR_Disable( level ); current_state = the_thread->current_state; if ( _States_Is_ready( current_state ) ) { the_thread->current_state = state; _Scheduler_Block( _Scheduler_Get( the_thread ), the_thread ); } else { the_thread->current_state = _States_Set( state, current_state); } _ISR_Enable( level ); }
void _Thread_Set_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; _ISR_Disable( level ); if ( !_States_Is_ready( the_thread->current_state ) ) { the_thread->current_state = _States_Set( state, the_thread->current_state ); _ISR_Enable( level ); return; } the_thread->current_state = state; _Scheduler_Block( the_thread ); _ISR_Enable( level ); }
void _Thread_Suspend( Thread_Control *the_thread ) { ISR_Level level; Chain_Control *ready; ready = the_thread->ready; _ISR_Disable( level ); #if defined(RTEMS_ITRON_API) the_thread->suspend_count++; #endif if ( !_States_Is_ready( the_thread->current_state ) ) { the_thread->current_state = _States_Set( STATES_SUSPENDED, the_thread->current_state ); _ISR_Enable( level ); return; } the_thread->current_state = STATES_SUSPENDED; 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_Flash( level ); if ( _Thread_Is_heir( the_thread ) ) _Thread_Calculate_heir(); if ( _Thread_Is_executing( the_thread ) ) _Context_Switch_necessary = true; _ISR_Enable( level ); }
void _Thread_Set_state( Thread_Control *the_thread, States_Control state ) { ISR_Level level; Chain_Control *ready; ready = the_thread->ready; _ISR_Disable( level ); if ( !_States_Is_ready( the_thread->current_state ) ) { the_thread->current_state = _States_Set( state, the_thread->current_state ); _ISR_Enable( level ); return; } the_thread->current_state = 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_Flash( level ); if ( _Thread_Is_heir( the_thread ) ) _Thread_Calculate_heir(); if ( _Thread_Is_executing( the_thread ) ) _Context_Switch_necessary = TRUE; _ISR_Enable( level ); }
void _Thread_Change_priority( Thread_Control *the_thread, Priority_Control new_priority, void *arg, Thread_Change_priority_filter filter, bool prepend_it ) { ISR_lock_Context lock_context; ISR_lock_Control *lock; lock = _Thread_Lock_acquire( the_thread, &lock_context ); /* * For simplicity set the priority restore hint unconditionally since this is * an average case optimization. Otherwise complicated atomic operations * would be necessary. Synchronize with a potential read of the resource * count in the filter function. See also _CORE_mutex_Surrender(), * _Thread_Set_priority_filter() and _Thread_Restore_priority_filter(). */ the_thread->priority_restore_hint = true; _Atomic_Fence( ATOMIC_ORDER_ACQ_REL ); /* * Do not bother recomputing all the priority related information if * we are not REALLY changing priority. */ if ( ( *filter )( the_thread, &new_priority, arg ) ) { uint32_t my_generation; my_generation = the_thread->priority_generation + 1; the_thread->current_priority = new_priority; the_thread->priority_generation = my_generation; ( *the_thread->Wait.operations->priority_change )( the_thread, new_priority, the_thread->Wait.queue ); _Thread_Lock_release( lock, &lock_context ); _Thread_State_acquire( the_thread, &lock_context ); if ( the_thread->priority_generation == my_generation ) { if ( _States_Is_ready( the_thread->current_state ) ) { _Scheduler_Change_priority( the_thread, new_priority, prepend_it ); } else { _Scheduler_Update_priority( the_thread, new_priority ); } } _Thread_State_release( the_thread, &lock_context ); } else { _Thread_Lock_release( lock, &lock_context ); } }
int killinfo( pid_t pid, int sig, const union sigval *value ) { sigset_t mask; POSIX_API_Control *api; uint32_t the_api; uint32_t index; uint32_t maximum; Objects_Information *the_info; Objects_Control **object_table; Thread_Control *the_thread; Thread_Control *interested; Priority_Control interested_priority; Chain_Control *the_chain; Chain_Node *the_node; siginfo_t siginfo_struct; siginfo_t *siginfo; POSIX_signals_Siginfo_node *psiginfo; /* * Only supported for the "calling process" (i.e. this node). */ if ( pid != getpid() ) rtems_set_errno_and_return_minus_one( ESRCH ); /* * Validate the signal passed. */ if ( !sig ) rtems_set_errno_and_return_minus_one( EINVAL ); if ( !is_valid_signo(sig) ) rtems_set_errno_and_return_minus_one( EINVAL ); /* * If the signal is being ignored, then we are out of here. */ if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) return 0; /* * P1003.1c/Draft 10, p. 33 says that certain signals should always * be directed to the executing thread such as those caused by hardware * faults. */ if ( (sig == SIGFPE) || (sig == SIGILL) || (sig == SIGSEGV ) ) return pthread_kill( pthread_self(), sig ); mask = signo_to_mask( sig ); /* * Build up a siginfo structure */ siginfo = &siginfo_struct; siginfo->si_signo = sig; siginfo->si_code = SI_USER; if ( !value ) { siginfo->si_value.sival_int = 0; } else { siginfo->si_value = *value; } _Thread_Disable_dispatch(); /* * Is the currently executing thread interested? If so then it will * get it an execute it as soon as the dispatcher executes. */ the_thread = _Thread_Executing; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; if ( _POSIX_signals_Is_interested( api, mask ) ) { goto process_it; } /* * Is an interested thread waiting for this signal (sigwait())? * * There is no requirement on the order of threads pending on a sigwait(). */ /* XXX violation of visibility -- need to define thread queue support */ the_chain = &_POSIX_signals_Wait_queue.Queues.Fifo; for ( the_node = _Chain_First( the_chain ); !_Chain_Is_tail( the_chain, the_node ) ; the_node = the_node->next ) { the_thread = THREAD_CHAIN_NODE_TO_THREAD( the_node ); api = the_thread->API_Extensions[ THREAD_API_POSIX ]; #if defined(DEBUG_SIGNAL_PROCESSING) printk( "Waiting Thread=%p option=0x%08x mask=0x%08x blocked=0x%08x\n", the_thread, the_thread->Wait.option, mask, api->signals_blocked); #endif /* * Is this thread is actually blocked waiting for the signal? */ if (the_thread->Wait.option & mask) goto process_it; /* * Is this thread is blocked waiting for another signal but has * not blocked this one? */ if (~api->signals_blocked & mask) goto process_it; } /* * Is any other thread interested? The highest priority interested * thread is selected. In the event of a tie, then the following * additional criteria is used: * * + ready thread over blocked * + blocked on call interruptible by signal (can return EINTR) * + blocked on call not interruptible by signal * * This looks at every thread in the system regardless of the creating API. * * NOTES: * * + rtems internal threads do not receive signals. */ interested = NULL; interested_priority = PRIORITY_MAXIMUM + 1; for (the_api = OBJECTS_CLASSIC_API; the_api <= OBJECTS_APIS_LAST; the_api++) { /* * This can occur when no one is interested and an API is not configured. */ if ( !_Objects_Information_table[ the_api ] ) continue; the_info = _Objects_Information_table[ the_api ][ 1 ]; #if defined(RTEMS_DEBUG) /* * This cannot happen in the current (as of June 2009) implementation * of initialization but at some point, the object information * structure for a particular manager may not be installed. */ if ( !the_info ) continue; #endif maximum = the_info->maximum; object_table = the_info->local_table; for ( index = 1 ; index <= maximum ; index++ ) { the_thread = (Thread_Control *) object_table[ index ]; if ( !the_thread ) continue; #if defined(DEBUG_SIGNAL_PROCESSING) printk("\n 0x%08x/0x%08x %d/%d 0x%08x 1", the_thread->Object.id, ((interested) ? interested->Object.id : 0), the_thread->current_priority, interested_priority, the_thread->current_state ); #endif /* * If this thread is of lower priority than the interested thread, * go on to the next thread. */ if ( the_thread->current_priority > interested_priority ) continue; DEBUG_STEP("2"); /* * If this thread is not interested, then go on to the next thread. */ api = the_thread->API_Extensions[ THREAD_API_POSIX ]; #if defined(RTEMS_DEBUG) if ( !api ) continue; #endif if ( !_POSIX_signals_Is_interested( api, mask ) ) continue; DEBUG_STEP("3"); /* * Now we know the thread under consideration is interested. * If the thread under consideration is of higher priority, then * it becomes the interested thread. * * NOTE: We initialized interested_priority to PRIORITY_MAXIMUM + 1 * so we never have to worry about deferencing a NULL * interested thread. */ if ( the_thread->current_priority < interested_priority ) { interested = the_thread; interested_priority = the_thread->current_priority; continue; } DEBUG_STEP("4"); /* * Now the thread and the interested thread have the same priority. * We have to sort through the combinations of blocked/not blocked * and blocking interruptibutable by signal. * * If the interested thread is ready, don't think about changing. */ if ( interested && !_States_Is_ready( interested->current_state ) ) { /* preferred ready over blocked */ DEBUG_STEP("5"); if ( _States_Is_ready( the_thread->current_state ) ) { interested = the_thread; interested_priority = the_thread->current_priority; continue; } DEBUG_STEP("6"); /* prefer blocked/interruptible over blocked/not interruptible */ if ( !_States_Is_interruptible_by_signal(interested->current_state) ) { DEBUG_STEP("7"); if ( _States_Is_interruptible_by_signal(the_thread->current_state) ) { DEBUG_STEP("8"); interested = the_thread; interested_priority = the_thread->current_priority; continue; } } } } } if ( interested ) { the_thread = interested; goto process_it; } /* * OK so no threads were interested right now. It will be left on the * global pending until a thread receives it. The global set of threads * can change interest in this signal in one of the following ways: * * + a thread is created with the signal unblocked, * + pthread_sigmask() unblocks the signal, * + sigprocmask() unblocks the signal, OR * + sigaction() which changes the handler to SIG_IGN. */ the_thread = NULL; goto post_process_signal; /* * We found a thread which was interested, so now we mark that this * thread needs to do the post context switch extension so it can * evaluate the signals pending. */ process_it: /* * Returns true if the signal was synchronously given to a thread * blocked waiting for the signal. */ if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) { _Thread_Enable_dispatch(); return 0; } post_process_signal: /* * We may have woken up a thread but we definitely need to post the * signal to the process wide information set. */ _POSIX_signals_Set_process_signals( mask ); if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) { psiginfo = (POSIX_signals_Siginfo_node *) _Chain_Get( &_POSIX_signals_Inactive_siginfo ); if ( !psiginfo ) { _Thread_Enable_dispatch(); rtems_set_errno_and_return_minus_one( EAGAIN ); } psiginfo->Info = *siginfo; _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node ); } DEBUG_STEP("\n"); _Thread_Enable_dispatch(); return 0; }
bool _Scheduler_simple_smp_Assign( Thread_Control *consider ) { bool found; /* have we found a cpu to place it on? */ uint32_t found_cpu; /* CPU to place this thread */ bool blocked; /* CPU has blocked thread? */ Thread_Control *pheir; /* heir on found cpu to potentially replace */ Thread_Control *h; Thread_Control *e; uint32_t cpu; /* * Initialize various variables to indicate we have not found * a potential core for the thread under consideration. */ found = false; blocked = false; found_cpu = 0; pheir = NULL; for ( cpu=0 ; cpu < _SMP_Processor_count ; cpu++ ) { D( "SCHED CPU=%d consider=0x%08x ASSIGN\n", cpu, consider->Object.id ); /* * If the thread under consideration is already executing or * heir, then we don't have a better option for it. */ e = _Per_CPU_Information[cpu].executing; if ( e == consider ) { D( "SCHED CPU=%d Executing=0x%08x considering=0x%08x ASSIGNED\n", cpu, e->Object.id, consider->Object.id ); return true; } if ( !_States_Is_ready( e->current_state ) ) { pheir = e; found_cpu = cpu; found = true; blocked = true; D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x BLOCKED\n", cpu, e->Object.id, consider->Object.id ); continue; } h = _Per_CPU_Information[cpu].heir; if ( h == consider ) { D( "SCHED CPU=%d Heir=0x%08x considering=0x%08x ASSIGNED\n", cpu, h->Object.id, consider->Object.id ); return true; } if ( blocked ) continue; /* * If we haven't found a potential CPU to locate the thread * under consideration on, we need to consider if this is a * more important threads first (e.g. priority <). * * But when a thread changes its priority and ends up at the end of * the priority group for the new heir, we also need to schedule * a new heir. This is the "=" part of the check. */ if ( !found ) { if ( consider->current_priority <= h->current_priority ) { pheir = h; found_cpu = cpu; found = true; D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x MAYBE #1\n", cpu, h->Object.id, consider->Object.id ); } continue; } /* * Past this point, found is true. */ /* * If we have found a potential CPU on which to make the * thread under consideration the heir, then we need to * check if the current CPU is a more appropriate place * for this thread to be placed. * * Check 1: heir of potential CPU is more important * then heir of current CPU. We want to * replace the least important thread possible. */ if ( h->current_priority > pheir->current_priority ) { pheir = h; found_cpu = cpu; D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x MAYBE #2\n", cpu, h->Object.id, consider->Object.id ); continue; } if ( h->current_priority > pheir->current_priority ) continue; /* * If heir of potential CPU and of the current CPU are of the SAME * priority, then which has been running longer? * * Which CPU has had its executing thread longer? */ if ( _Timestamp_Less_than( &_Per_CPU_Information[cpu].time_of_last_context_switch, &_Per_CPU_Information[found_cpu].time_of_last_context_switch ) ) { pheir = h; found_cpu = cpu; D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x LONGER\n", cpu, h->Object.id, consider->Object.id ); continue; } /* * If we are looking at a core with a non-preemptible thread * for potential placement, then favor a core with a preeemtible * thread of the same priority. This should help avoid priority * inversions and let threads run earlier. */ if ( !pheir->is_preemptible && h->is_preemptible ) { D( "SCHED CPU=%d PHeir==0x%08x is NOT PREEMPTIBLE\n", cpu, pheir->Object.id ); pheir = h; found_cpu = cpu; D( "SCHED CPU=%d PHeir=0x%08x considering=0x%08x PREEMPTIBLE\n", cpu, h->Object.id, consider->Object.id ); continue; } } /* * If we found a cpu to make this thread heir of, then we * need to consider whether we need a dispatch on that CPU. */ if ( found ) { e = _Per_CPU_Information[found_cpu].executing; D( "SCHED CPU=%d executing=0x%08x considering=0x%08x FOUND\n", found_cpu, e->Object.id, consider->Object.id ); _Per_CPU_Information[found_cpu].heir = consider; if ( !_States_Is_ready( e->current_state ) ) { D( "SCHED CPU=%d executing not ready dispatch needed\n", found_cpu); _Per_CPU_Information[found_cpu].dispatch_necessary = true; } else if ( consider->current_priority < e->current_priority ) { if ( e->is_preemptible || consider->current_priority == 0 ) { D( "SCHED CPU=%d preempting\n", found_cpu); _Per_CPU_Information[found_cpu].dispatch_necessary = true; } } } /* * Return true to indicate we changed an heir. This indicates * scheduling needs to examine more threads. */ return found; }
ER ref_tsk( T_RTSK *pk_rtsk, ID tskid ) { register Thread_Control *the_thread; Objects_Locations location; Priority_Control core_priority; if (!pk_rtsk) return E_PAR; the_thread = _ITRON_Task_Get( tskid, &location ); switch ( location ) { #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: #endif case OBJECTS_ERROR: return _ITRON_Task_Clarify_get_id_error( tskid ); case OBJECTS_LOCAL: if ( location != OBJECTS_LOCAL ) return _ITRON_Task_Clarify_get_id_error( tskid ); /* * The following are extended functions [level X ]. * XXX - tskwait, wid, wupcnt, and tskatr are presently not implemented. */ pk_rtsk->tskwait = 0; pk_rtsk->wid = 0; pk_rtsk->wupcnt = 0; pk_rtsk->suscnt = the_thread->suspend_count; pk_rtsk->tskatr = 0; /* XXX - Not correctly implemented */ pk_rtsk->task = (FP) the_thread->Start.entry_point; core_priority = the_thread->Start.initial_priority; pk_rtsk->itskpri = _ITRON_Task_Core_to_Priority( core_priority ); pk_rtsk->stksz = the_thread->Start.Initial_stack.size; /* * The following are required. */ pk_rtsk->exinf = NULL; /* extended information */ pk_rtsk->tskpri = _ITRON_Task_Core_to_Priority(the_thread->current_priority); /* * Mask in the tskstat information * Convert the task state XXX double check this */ pk_rtsk->tskstat = 0; if ( the_thread == _Thread_Executing ) pk_rtsk->tskstat |= TTS_RUN; if ( _States_Is_ready(the_thread->current_state) ) pk_rtsk->tskstat |= TTS_RDY; if ( _States_Is_dormant( the_thread->current_state) ) pk_rtsk->tskstat |= TTS_DMT; if ( _States_Is_suspended(the_thread->current_state) ) pk_rtsk->tskstat |= TTS_SUS; if ( _States_Is_blocked(the_thread->current_state) ) pk_rtsk->tskstat |= TTS_WAI; break; } _ITRON_return_errorno( E_OK ); }