static void CPU_usage_Per_thread_handler( Thread_Control *the_thread ) { #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); #else the_thread->cpu_time_used = 0; #endif }
void _TOD_Handler_initialization(void) { /* POSIX format TOD (timespec) */ _Timestamp_Set( &_TOD_Now, TOD_SECONDS_1970_THROUGH_1988, 0 ); /* Uptime (timespec) */ _Timestamp_Set_to_zero( &_TOD_Uptime ); /* TOD has not been set */ _TOD_Is_set = false; _TOD_Activate(); }
void _TOD_Handler_initialization(void) { TOD_Control *tod = &_TOD; _ISR_lock_Initialize( &tod->lock ); _Timestamp_Set( &tod->now, TOD_SECONDS_1970_THROUGH_1988, 0 ); _Timestamp_Set_to_zero( &tod->uptime ); tod->nanoseconds_since_last_tick = _TOD_Nanoseconds_since_tick_default_handler; /* TOD has not been set */ tod->is_set = false; }
static void CPU_usage_Per_thread_handler( Thread_Control *the_thread ) { const Scheduler_Control *scheduler; ISR_lock_Context state_lock_context; ISR_lock_Context scheduler_lock_context; _Thread_State_acquire( the_thread, &state_lock_context ); scheduler = _Scheduler_Get( the_thread ); _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); _Thread_State_release( the_thread, &state_lock_context ); }
bool _Thread_Initialize( Objects_Information *information, Thread_Control *the_thread, void *stack_area, size_t stack_size, bool is_fp, Priority_Control priority, bool is_preemptible, Thread_CPU_budget_algorithms budget_algorithm, Thread_CPU_budget_algorithm_callout budget_callout, uint32_t isr_level, Objects_Name name ) { size_t actual_stack_size = 0; void *stack = NULL; #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) void *fp_area; #endif void *sched = NULL; void *extensions_area; bool extension_status; int i; #if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) { return false; } #endif /* * Initialize the Ada self pointer */ #if __RTEMS_ADA__ the_thread->rtems_ada_self = NULL; #endif /* * Zero out all the allocated memory fields */ for ( i=0 ; i <= THREAD_API_LAST ; i++ ) the_thread->API_Extensions[i] = NULL; extensions_area = NULL; the_thread->libc_reent = NULL; #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) fp_area = NULL; #endif /* * Allocate and Initialize the stack for this thread. */ #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API) actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size ); if ( !actual_stack_size || actual_stack_size < stack_size ) return false; /* stack allocation failed */ stack = the_thread->Start.stack; #else if ( !stack_area ) { actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size ); if ( !actual_stack_size || actual_stack_size < stack_size ) return false; /* stack allocation failed */ stack = the_thread->Start.stack; the_thread->Start.core_allocated_stack = true; } else { stack = stack_area; actual_stack_size = stack_size; the_thread->Start.core_allocated_stack = false; } #endif _Stack_Initialize( &the_thread->Start.Initial_stack, stack, actual_stack_size ); /* * Allocate the floating point area for this thread */ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) if ( is_fp ) { fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE ); if ( !fp_area ) goto failed; fp_area = _Context_Fp_start( fp_area, 0 ); } the_thread->fp_context = fp_area; the_thread->Start.fp_context = fp_area; #endif /* * Initialize the thread timer */ _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL ); #ifdef __RTEMS_STRICT_ORDER_MUTEX__ /* Initialize the head of chain of held mutexes */ _Chain_Initialize_empty(&the_thread->lock_mutex); #endif /* * Allocate the extensions area for this thread */ if ( _Thread_Maximum_extensions ) { extensions_area = _Workspace_Allocate( (_Thread_Maximum_extensions + 1) * sizeof( void * ) ); if ( !extensions_area ) goto failed; } the_thread->extensions = (void **) extensions_area; /* * Clear the extensions area so extension users can determine * if they are linked to the thread. An extension user may * create the extension long after tasks have been created * so they cannot rely on the thread create user extension * call. */ if ( the_thread->extensions ) { for ( i = 0; i <= _Thread_Maximum_extensions ; i++ ) the_thread->extensions[i] = NULL; } /* * General initialization */ the_thread->Start.is_preemptible = is_preemptible; the_thread->Start.budget_algorithm = budget_algorithm; the_thread->Start.budget_callout = budget_callout; switch ( budget_algorithm ) { case THREAD_CPU_BUDGET_ALGORITHM_NONE: case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE: break; #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE) case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE: the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice; break; #endif #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT: break; #endif } the_thread->Start.isr_level = isr_level; #if defined(RTEMS_SMP) the_thread->is_scheduled = false; the_thread->is_executing = false; /* Initialize the cpu field for the non-SMP schedulers */ the_thread->cpu = _Per_CPU_Get_by_index( 0 ); #endif the_thread->current_state = STATES_DORMANT; the_thread->Wait.queue = NULL; the_thread->resource_count = 0; the_thread->real_priority = priority; the_thread->Start.initial_priority = priority; sched =_Scheduler_Allocate( the_thread ); if ( !sched ) goto failed; _Thread_Set_priority( the_thread, priority ); /* * Initialize the CPU usage statistics */ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); #else the_thread->cpu_time_used = 0; #endif /* * Open the object */ _Objects_Open( information, &the_thread->Object, name ); /* * We assume the Allocator Mutex is locked and dispatching is * enabled when we get here. We want to be able to run the * user extensions with dispatching enabled. The Allocator * Mutex provides sufficient protection to let the user extensions * run safely. */ extension_status = _User_extensions_Thread_create( the_thread ); if ( extension_status ) return true; failed: _Workspace_Free( the_thread->libc_reent ); for ( i=0 ; i <= THREAD_API_LAST ; i++ ) _Workspace_Free( the_thread->API_Extensions[i] ); _Workspace_Free( extensions_area ); #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) _Workspace_Free( fp_area ); #endif _Workspace_Free( sched ); _Thread_Stack_Free( the_thread ); return false; }
bool _Thread_Initialize( Objects_Information *information, Thread_Control *the_thread, const Scheduler_Control *scheduler, void *stack_area, size_t stack_size, bool is_fp, Priority_Control priority, bool is_preemptible, Thread_CPU_budget_algorithms budget_algorithm, Thread_CPU_budget_algorithm_callout budget_callout, uint32_t isr_level, Objects_Name name ) { uintptr_t tls_size = _TLS_Get_size(); size_t actual_stack_size = 0; void *stack = NULL; #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) void *fp_area = NULL; #endif bool extension_status; size_t i; bool scheduler_node_initialized = false; Per_CPU_Control *cpu = _Per_CPU_Get_by_index( 0 ); #if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && !is_preemptible ) { return false; } #endif for ( i = 0 ; i < _Thread_Control_add_on_count ; ++i ) { const Thread_Control_add_on *add_on = &_Thread_Control_add_ons[ i ]; *(void **) ( (char *) the_thread + add_on->destination_offset ) = (char *) the_thread + add_on->source_offset; } /* * Initialize the Ada self pointer */ #if __RTEMS_ADA__ the_thread->rtems_ada_self = NULL; #endif the_thread->Start.tls_area = NULL; /* * Allocate and Initialize the stack for this thread. */ #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API) actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size ); if ( !actual_stack_size || actual_stack_size < stack_size ) return false; /* stack allocation failed */ stack = the_thread->Start.stack; #else if ( !stack_area ) { actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size ); if ( !actual_stack_size || actual_stack_size < stack_size ) return false; /* stack allocation failed */ stack = the_thread->Start.stack; the_thread->Start.core_allocated_stack = true; } else { stack = stack_area; actual_stack_size = stack_size; the_thread->Start.core_allocated_stack = false; } #endif _Stack_Initialize( &the_thread->Start.Initial_stack, stack, actual_stack_size ); /* Thread-local storage (TLS) area allocation */ if ( tls_size > 0 ) { uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment ); uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align ); the_thread->Start.tls_area = _Workspace_Allocate_aligned( tls_alloc, tls_align ); if ( the_thread->Start.tls_area == NULL ) { goto failed; } } /* * Allocate the floating point area for this thread */ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) if ( is_fp ) { fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE ); if ( !fp_area ) goto failed; fp_area = _Context_Fp_start( fp_area, 0 ); } the_thread->fp_context = fp_area; the_thread->Start.fp_context = fp_area; #endif /* * Initialize the thread timer */ _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL ); #ifdef __RTEMS_STRICT_ORDER_MUTEX__ /* Initialize the head of chain of held mutexes */ _Chain_Initialize_empty(&the_thread->lock_mutex); #endif /* * Clear the extensions area so extension users can determine * if they are linked to the thread. An extension user may * create the extension long after tasks have been created * so they cannot rely on the thread create user extension * call. The object index starts with one, so the first extension context is * unused. */ for ( i = 1 ; i <= rtems_configuration_get_maximum_extensions() ; ++i ) the_thread->extensions[ i ] = NULL; /* * General initialization */ the_thread->Start.isr_level = isr_level; the_thread->Start.is_preemptible = is_preemptible; the_thread->Start.budget_algorithm = budget_algorithm; the_thread->Start.budget_callout = budget_callout; switch ( budget_algorithm ) { case THREAD_CPU_BUDGET_ALGORITHM_NONE: case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE: break; #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE) case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE: the_thread->cpu_time_budget = rtems_configuration_get_ticks_per_timeslice(); break; #endif #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT) case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT: break; #endif } #if defined(RTEMS_SMP) the_thread->Scheduler.state = THREAD_SCHEDULER_BLOCKED; the_thread->Scheduler.own_control = scheduler; the_thread->Scheduler.control = scheduler; the_thread->Scheduler.own_node = the_thread->Scheduler.node; _Resource_Node_initialize( &the_thread->Resource_node ); _CPU_Context_Set_is_executing( &the_thread->Registers, false ); #endif _Thread_Debug_set_real_processor( the_thread, cpu ); /* Initialize the CPU for the non-SMP schedulers */ _Thread_Set_CPU( the_thread, cpu ); the_thread->current_state = STATES_DORMANT; the_thread->Wait.queue = NULL; the_thread->resource_count = 0; the_thread->real_priority = priority; the_thread->Start.initial_priority = priority; _Scheduler_Node_initialize( scheduler, the_thread ); scheduler_node_initialized = true; _Thread_Set_priority( the_thread, priority ); /* * Initialize the CPU usage statistics */ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); #else the_thread->cpu_time_used = 0; #endif /* * initialize thread's key vaule node chain */ _Chain_Initialize_empty( &the_thread->Key_Chain ); _Thread_Action_control_initialize( &the_thread->Post_switch_actions ); _Thread_Action_initialize( &the_thread->Life.Action, _Thread_Life_action_handler ); the_thread->Life.state = THREAD_LIFE_NORMAL; the_thread->Life.terminator = NULL; /* * Open the object */ _Objects_Open( information, &the_thread->Object, name ); /* * We assume the Allocator Mutex is locked and dispatching is * enabled when we get here. We want to be able to run the * user extensions with dispatching enabled. The Allocator * Mutex provides sufficient protection to let the user extensions * run safely. */ extension_status = _User_extensions_Thread_create( the_thread ); if ( extension_status ) return true; failed: if ( scheduler_node_initialized ) { _Scheduler_Node_destroy( scheduler, the_thread ); } _Workspace_Free( the_thread->Start.tls_area ); #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) _Workspace_Free( fp_area ); #endif _Thread_Stack_Free( the_thread ); return false; }
/* * rtems_cpu_usage_report */ void rtems_cpu_usage_report_with_plugin( void *context, rtems_printk_plugin_t print ) { uint32_t i; uint32_t api_index; Thread_Control *the_thread; Objects_Information *information; char name[13]; uint32_t ival, fval; #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ Timestamp_Control uptime, total, ran, uptime_at_last_reset; uint32_t seconds, nanoseconds; #else uint32_t total_units = 0; #endif if ( !print ) return; /* * When not using nanosecond CPU usage resolution, we have to count * the number of "ticks" we gave credit for to give the user a rough * guideline as to what each number means proportionally. */ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ _Timestamp_Set_to_zero( &total ); uptime_at_last_reset = CPU_usage_Uptime_at_last_reset; #else for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) { #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG) if ( !_Objects_Information_table[ api_index ] ) continue; #endif information = _Objects_Information_table[ api_index ][ 1 ]; if ( information ) { for ( i=1 ; i <= information->maximum ; i++ ) { the_thread = (Thread_Control *)information->local_table[ i ]; if ( the_thread ) total_units += the_thread->cpu_time_used; } } } #endif (*print)( context, "-------------------------------------------------------------------------------\n" " CPU USAGE BY THREAD\n" "------------+----------------------------------------+---------------+---------\n" #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ " ID | NAME | SECONDS | PERCENT\n" #else " ID | NAME | TICKS | PERCENT\n" #endif "------------+----------------------------------------+---------------+---------\n" ); for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) { #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG) if ( !_Objects_Information_table[ api_index ] ) continue; #endif information = _Objects_Information_table[ api_index ][ 1 ]; if ( information ) { for ( i=1 ; i <= information->maximum ; i++ ) { the_thread = (Thread_Control *)information->local_table[ i ]; if ( !the_thread ) continue; rtems_object_get_name( the_thread->Object.id, sizeof(name), name ); (*print)( context, " 0x%08" PRIx32 " | %-38s |", the_thread->Object.id, name ); #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ { Timestamp_Control last; /* * If this is the currently executing thread, account for time * since the last context switch. */ ran = the_thread->cpu_time_used; if ( is_executing_on_a_core( the_thread, &last ) ) { Timestamp_Control used; _TOD_Get_uptime( &uptime ); _Timestamp_Subtract( &last, &uptime, &used ); _Timestamp_Add_to( &ran, &used ); } else { _TOD_Get_uptime( &uptime ); } _Timestamp_Subtract( &uptime_at_last_reset, &uptime, &total ); _Timestamp_Divide( &ran, &total, &ival, &fval ); /* * Print the information */ seconds = _Timestamp_Get_seconds( &ran ); nanoseconds = _Timestamp_Get_nanoseconds( &ran ) / TOD_NANOSECONDS_PER_MICROSECOND; (*print)( context, "%7" PRIu32 ".%06" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n", seconds, nanoseconds, ival, fval ); } #else if (total_units) { uint64_t ival_64; ival_64 = the_thread->cpu_time_used; ival_64 *= 100000; ival = ival_64 / total_units; } else { ival = 0; } fval = ival % 1000; ival /= 1000; (*print)( context, "%14" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n", the_thread->cpu_time_used, ival, fval ); #endif } } } #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__ seconds = _Timestamp_Get_seconds( &total ); nanoseconds = _Timestamp_Get_nanoseconds( &total ) / TOD_NANOSECONDS_PER_MICROSECOND; (*print)( context, "------------+----------------------------------------+---------------+---------\n" " TIME SINCE LAST CPU USAGE RESET IN SECONDS: %7" PRIu32 ".%06" PRIu32 "\n" "-------------------------------------------------------------------------------\n", seconds, nanoseconds ); #else (*print)( context, "------------+----------------------------------------+---------------+---------\n" " TICKS SINCE LAST SYSTEM RESET: %14" PRIu32 "\n" " TOTAL UNITS: %14" PRIu32 "\n" "-------------------------------------------------------------------------------\n", _Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset, total_units ); #endif }
static void CPU_usage_Per_thread_handler( Thread_Control *the_thread ) { _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); }
static void rtems_cpuusage_top_thread (rtems_task_argument arg) { rtems_cpu_usage_data* data = (rtems_cpu_usage_data*) arg; char name[13]; int i; Heap_Information_block wksp; uint32_t ival, fval; int task_count; rtems_event_set out; rtems_status_code sc; bool first_time = true; data->thread_active = true; _TOD_Get_uptime(&data->last_uptime); CPU_usage_Set_to_zero(&data->zero); while (data->thread_run) { Timestamp_Control uptime_at_last_reset = CPU_usage_Uptime_at_last_reset; size_t tasks_size; size_t usage_size; Timestamp_Control load; data->task_count = 0; rtems_iterate_over_all_threads_2(task_counter, data); tasks_size = sizeof(Thread_Control*) * (data->task_count + 1); usage_size = sizeof(Timestamp_Control) * (data->task_count + 1); if (data->task_count > data->task_size) { data->tasks = realloc(data->tasks, tasks_size); data->usage = realloc(data->usage, usage_size); data->current_usage = realloc(data->current_usage, usage_size); if ((data->tasks == NULL) || (data->usage == NULL) || (data->current_usage == NULL)) { rtems_printf(data->printer, "top worker: error: no memory\n"); data->thread_run = false; break; } } memset(data->tasks, 0, tasks_size); memset(data->usage, 0, usage_size); memset(data->current_usage, 0, usage_size); _Timestamp_Set_to_zero(&data->total); _Timestamp_Set_to_zero(&data->current); data->stack_size = 0; _TOD_Get_uptime(&data->uptime); _Timestamp_Subtract(&uptime_at_last_reset, &data->uptime, &data->uptime); _Timestamp_Subtract(&data->last_uptime, &data->uptime, &data->period); data->last_uptime = data->uptime; rtems_iterate_over_all_threads_2(task_usage, data); if (data->task_count > data->task_size) { data->last_tasks = realloc(data->last_tasks, tasks_size); data->last_usage = realloc(data->last_usage, usage_size); if ((data->last_tasks == NULL) || (data->last_usage == NULL)) { rtems_printf(data->printer, "top worker: error: no memory\n"); data->thread_run = false; break; } data->task_size = data->task_count; } memcpy(data->last_tasks, data->tasks, tasks_size); memcpy(data->last_usage, data->usage, usage_size); data->last_task_count = data->task_count; /* * We need to loop again to get suitable current usage values as we need a * last sample to work. */ if (first_time) { rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(500)); first_time = false; continue; } _Protected_heap_Get_information(&_Workspace_Area, &wksp); if (data->single_page) rtems_printf(data->printer, "\x1b[H\x1b[J" " ENTER:Exit SPACE:Refresh" " S:Scroll A:All <>:Order +/-:Lines\n"); rtems_printf(data->printer, "\n"); /* * Uptime and period of this sample. */ rtems_printf(data->printer, "Uptime: "); print_time(data, &data->uptime, 20); rtems_printf(data->printer, " Period: "); print_time(data, &data->period, 20); /* * Task count, load and idle levels. */ rtems_printf(data->printer, "\nTasks: %4i ", data->task_count); _Timestamp_Subtract(&data->idle, &data->total, &load); _Timestamp_Divide(&load, &data->uptime, &ival, &fval); rtems_printf(data->printer, "Load Average: %4" PRIu32 ".%03" PRIu32 "%%", ival, fval); _Timestamp_Subtract(&data->current_idle, &data->current, &load); _Timestamp_Divide(&load, &data->period, &ival, &fval); rtems_printf(data->printer, " Load: %4" PRIu32 ".%03" PRIu32 "%%", ival, fval); _Timestamp_Divide(&data->current_idle, &data->period, &ival, &fval); rtems_printf(data->printer, " Idle: %4" PRIu32 ".%03" PRIu32 "%%", ival, fval); /* * Memory usage. */ if (rtems_configuration_get_unified_work_area()) { rtems_printf(data->printer, "\nMem: "); print_memsize(data, wksp.Free.total, "free"); print_memsize(data, wksp.Used.total, "used"); } else { region_information_block libc_heap; malloc_info(&libc_heap); rtems_printf(data->printer, "\nMem: Wksp: "); print_memsize(data, wksp.Free.total, "free"); print_memsize(data, wksp.Used.total, "used Heap: "); print_memsize(data, libc_heap.Free.total, "free"); print_memsize(data, libc_heap.Used.total, "used"); } print_memsize(data, data->stack_size, "stack\n"); rtems_printf(data->printer, "\n" " ID | NAME | RPRI | CPRI | TIME | TOTAL | CURRENT\n" "-%s---------+---------------------+-%s-----%s-----+---------------------+-%s------+--%s----\n", data->sort_order == RTEMS_TOP_SORT_ID ? "^^" : "--", data->sort_order == RTEMS_TOP_SORT_REAL_PRI ? "^^" : "--", data->sort_order == RTEMS_TOP_SORT_CURRENT_PRI ? "^^" : "--", data->sort_order == RTEMS_TOP_SORT_TOTAL ? "^^" : "--", data->sort_order == RTEMS_TOP_SORT_CURRENT ? "^^" : "--" ); task_count = 0; for (i = 0; i < data->task_count; i++) { Thread_Control* thread = data->tasks[i]; Timestamp_Control usage; Timestamp_Control current_usage; if (thread == NULL) break; if (data->single_page && (data->show != 0) && (i >= data->show)) break; /* * We need to count the number displayed to clear the remainder of the * the display. */ ++task_count; /* * If the API os POSIX print the entry point. */ rtems_object_get_name(thread->Object.id, sizeof(name), name); if (name[0] == '\0') snprintf(name, sizeof(name) - 1, "(%p)", thread->Start.Entry.Kinds.Numeric.entry); rtems_printf(data->printer, " 0x%08" PRIx32 " | %-19s | %3" PRId64 " | %3" PRId64 " | ", thread->Object.id, name, thread->Real_priority.priority, _Thread_Get_priority(thread)); usage = data->usage[i]; current_usage = data->current_usage[i]; /* * Print the information */ print_time(data, &usage, 19); _Timestamp_Divide(&usage, &data->total, &ival, &fval); rtems_printf(data->printer, " |%4" PRIu32 ".%03" PRIu32, ival, fval); _Timestamp_Divide(¤t_usage, &data->period, &ival, &fval); rtems_printf(data->printer, " |%4" PRIu32 ".%03" PRIu32 "\n", ival, fval); } if (data->single_page && (data->show != 0) && (task_count < data->show)) { i = data->show - task_count; while (i > 0) { rtems_printf(data->printer, "\x1b[K\n"); i--; } } sc = rtems_event_receive(RTEMS_EVENT_1, RTEMS_EVENT_ANY, RTEMS_MILLISECONDS_TO_TICKS (data->poll_rate_usecs), &out); if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT)) { rtems_printf(data->printer, "error: event receive: %s\n", rtems_status_text(sc)); break; } } free(data->tasks); free(data->last_tasks); free(data->last_usage); free(data->current_usage); data->thread_active = false; rtems_task_delete (RTEMS_SELF); }