Exemple #1
0
void *POSIX_Init(
  void *argument
)
{
  char               name[128];
  char              *ptr;
  rtems_status_code  status;

  TEST_BEGIN();

  ptr = rtems_object_get_name( pthread_self(), 128, name );
  printf( "rtems_object_get_name returned (%s) for init thread\n", ptr );

  /* Set my name to Justin */
  puts( "Setting current thread name to Justin" );
  status = rtems_object_set_name( pthread_self(), "Justin" );
  directive_failed( status, "rtems_object_set_name" );

  ptr = rtems_object_get_name( pthread_self(), 128, name );
  printf( "rtems_object_get_name returned (%s) for init thread\n", ptr );

  /* Set my name to Jordan */
  puts( "Setting current thread name to Jordan" );
  status = rtems_object_set_name( pthread_self(), "Jordan" );
  directive_failed( status, "rtems_object_set_name" );

  ptr = rtems_object_get_name( pthread_self(), 128, name );
  printf( "rtems_object_get_name returned (%s) for init thread\n", ptr );

  /* exercise the POSIX path through some routines */
  printf( "rtems_object_api_minimum_class(OBJECTS_POSIX_API) returned %d\n",
          rtems_object_api_minimum_class(OBJECTS_POSIX_API) );
  printf( "rtems_object_api_maximum_class(OBJECTS_POSIX_API) returned %d\n",
          rtems_object_api_maximum_class(OBJECTS_POSIX_API) );

  printf( "rtems_object_get_api_name(POSIX_API) = %s\n",
     rtems_object_get_api_name(OBJECTS_POSIX_API) );

  printf("rtems_object_get_api_class_name(POSIX_API, POSIX_KEYS) = %s\n",
    rtems_object_get_api_class_name( OBJECTS_POSIX_API, OBJECTS_POSIX_KEYS)
  );


  TEST_END();
  rtems_test_exit( 0 );

  return NULL;

}
Exemple #2
0
rtems_task Test_task(
  rtems_task_argument unused
)
{
  rtems_id          tid;
  rtems_time_of_day time;
  uint32_t    task_index;
  rtems_status_code status;
  int               cpu_num;
  char              name[5];
  char             *p;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

  status = rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &tid );
  task_index = task_number( tid );
  for ( ; ; ) {

    /* Get the CPU Number */
    cpu_num = bsp_smp_processor_id();

    status = rtems_clock_get_tod( &time );
    if ( time.second >= 35 ) {
      locked_printf( "*** END OF SMP08 TEST ***" );
      rtems_test_exit( 0 );
    }

    PrintTaskInfo( p, &time );
    status = rtems_task_wake_after(
      task_index * 5 * rtems_clock_get_ticks_per_second() );
  }
}
Exemple #3
0
rtems_task Test_task(
  rtems_task_argument unused
)
{
  rtems_id          tid;
  rtems_time_of_day time;
  uint32_t    task_index;
  rtems_status_code status;
  char              name[5];
  char             *p;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

  status = rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &tid );
  rtems_test_assert( status == RTEMS_SUCCESSFUL );
  task_index = task_number( tid );
  for ( ; ; ) {
    status = rtems_clock_get_tod( &time );
    rtems_test_assert( status == RTEMS_SUCCESSFUL );
    if ( time.second >= 35 ) {
      TEST_END();
      rtems_test_exit( 0 );
    }

    PrintTaskInfo( p, &time );
    status = rtems_task_wake_after(
      task_index * 5 * rtems_clock_get_ticks_per_second() );
    rtems_test_assert( status == RTEMS_SUCCESSFUL );
  }
}
Exemple #4
0
rtems_task Test_task(
  rtems_task_argument task_index
)
{
  uint32_t          cpu_num;
  char              name[5];
  char             *p;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

   /* Get the CPU Number */
  cpu_num = rtems_smp_get_current_processor();

  /* Print that the task is up and running. */
  Loop();
  locked_printf(" CPU %" PRIu32 " running Task %s\n", cpu_num, name);

  /* Set the flag that the task is up and running */
  TaskRan[cpu_num] = true;


  /* Drop into a loop which will keep this task on
   * running on the cpu.
   */
  while(1);
}
Exemple #5
0
rtems_task Wait_task(
    rtems_task_argument argument
    )
{
  char              name[5];
  char             *p;
  bool               allDone;
  int                i;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

  /* Wait on the all tasks to run */
  while (1) {
    allDone = true;
    for ( i=0; i<TASK_NUMS ; i++ ) {
      if (TaskRan[i] == false)
        allDone = false;
    }
    if (allDone) {
      puts( "\n\n*** END OF TEST spatomic07 ***\n" );
      rtems_test_exit( 0 );
    }
  }
}
Exemple #6
0
int
rtems_monitor_dump_name(rtems_id id)
{
    char name_buffer[18] = "????";

    rtems_object_get_name( id, sizeof(name_buffer), name_buffer );

    return fprintf( stdout, name_buffer );
}
Exemple #7
0
rtems_task Test_task(
    rtems_task_argument argument
    )
{
  char              name[5];
  char             *p;
  rtems_status_code  status;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

  /* Print that the task is up and running. */
  /* test relaxed barrier */
  ATOMIC_CAS_NO_BARRIER(int, Int, argument, ATOMIC_RELAXED_BARRIER);

  ATOMIC_CAS_NO_BARRIER(long, Long, argument, ATOMIC_RELAXED_BARRIER);

  ATOMIC_CAS_NO_BARRIER(ptr, Pointer, argument, ATOMIC_RELAXED_BARRIER);

  ATOMIC_CAS_NO_BARRIER(32, Int32, argument, ATOMIC_RELAXED_BARRIER);

  /* test acquire barrier */
  ATOMIC_CAS_NO_BARRIER(int, Int, argument, ATOMIC_ACQUIRE_BARRIER);

  ATOMIC_CAS_NO_BARRIER(long, Long, argument, ATOMIC_ACQUIRE_BARRIER);

  ATOMIC_CAS_NO_BARRIER(ptr, Pointer, argument, ATOMIC_ACQUIRE_BARRIER);

  ATOMIC_CAS_NO_BARRIER(32, Int32, argument, ATOMIC_ACQUIRE_BARRIER);

  /* test release barrier */
  ATOMIC_CAS_NO_BARRIER(int, Int, argument, ATOMIC_RELEASE_BARRIER);

  ATOMIC_CAS_NO_BARRIER(long, Long, argument, ATOMIC_RELEASE_BARRIER);

  ATOMIC_CAS_NO_BARRIER(ptr, Pointer, argument, ATOMIC_RELEASE_BARRIER);

  ATOMIC_CAS_NO_BARRIER(32, Int32, argument, ATOMIC_RELEASE_BARRIER);

  /* Set the flag that the task is up and running */
  TaskRan[argument] = true;

  status = rtems_task_delete( RTEMS_SELF );
  directive_failed( status, "delete" );
}
rtems_task Test_task(
    rtems_task_argument argument
    )
{
  uint32_t          cpu_num;
  char              name[5];
  char             *p;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

   /* Get the CPU Number */
  cpu_num = rtems_smp_get_current_processor();

  /* Print that the task is up and running. */
  /* test relaxed barrier */
  ATOMIC_FETCH_ADD_NO_BARRIER(ulong, Ulong, unsigned long, cpu_num, ATOMIC_ORDER_RELAXED);

  ATOMIC_FETCH_ADD_NO_BARRIER(ptr, Pointer, uintptr_t, cpu_num, ATOMIC_ORDER_RELAXED);

  /* test acquire barrier */
  ATOMIC_FETCH_ADD_NO_BARRIER(ulong, Ulong, unsigned long, cpu_num, ATOMIC_ORDER_ACQUIRE);

  ATOMIC_FETCH_ADD_NO_BARRIER(ptr, Pointer, uintptr_t, cpu_num, ATOMIC_ORDER_ACQUIRE);

  /* test release barrier */
  ATOMIC_FETCH_ADD_NO_BARRIER(ulong, Ulong, unsigned long, cpu_num, ATOMIC_ORDER_RELEASE);

  ATOMIC_FETCH_ADD_NO_BARRIER(ptr, Pointer, uintptr_t, cpu_num, ATOMIC_ORDER_RELEASE);

//  ATOMIC_FETCH_ADD_NO_BARRIER(64, cpu_num);

  /* Set the flag that the task is up and running */
  TaskRan[cpu_num] = true;

  /* Drop into a loop which will keep this task on
   * running on the cpu.
   */
  while(1);
}
Exemple #9
0
static void
rtems_bsd_dump_thread(Thread_Control *thread)
{
	const struct thread *td = rtems_bsd_get_thread(thread);

	if (td != NULL) {
		char buf[5];
		const char *name = td->td_name;

		if (name == NULL || name[0] == '\0') {
			rtems_object_get_name(thread->Object.id, sizeof(buf), &buf[0]);
			name = &buf[0];
		}

		fprintf(
			stdout,
			" 0x%08" PRIx32 " | %8" PRIu32 " | %s\n",
			thread->Object.id,
			_Thread_Get_priority(thread),
			name
		);
	}
}
Exemple #10
0
rtems_task Test_task(
  rtems_task_argument do_exit
)
{
  int               cpu_num;
  char              name[5];
  char             *p;

  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

  cpu_num = bsp_smp_processor_id();
  locked_printf(" CPU %d running Task %s\n", cpu_num, name);

  Ran = true;

  if ( do_exit ) {
    locked_printf( "*** END OF TEST SMP06 ***\n" );
    rtems_test_exit(0);
  }
  while(1)
    ;
}
Exemple #11
0
rtems_task Test_task(
  rtems_task_argument argument
)
{
  uint32_t          cpu_num;
  rtems_status_code sc;
  char              name[5];
  char             *p;

  /* Get the task name */
  p = rtems_object_get_name( RTEMS_SELF, 5, name );
  rtems_test_assert( p != NULL );

   /* Get the CPU Number */
  cpu_num = rtems_get_current_processor();

  /* Print that the task is up and running. */
  locked_printf(" CPU %" PRIu32 " runnng Task %s and blocking\n", cpu_num, name);

  sc = rtems_semaphore_obtain( Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
  directive_failed( sc,"obtain in test task");

  if ( !TSRFired )
    locked_printf( "*** ERROR TSR DID NOT FIRE BUT TEST TASK AWAKE***" );

  TaskRan = true;

  /* Print that the task is up and running. */
  locked_printf(
    " CPU %" PRIu32 " running Task %s after semaphore release\n", 
    cpu_num, 
    name
  );

  /* FIXME: Task deletion currently not supported */
  (void) rtems_task_suspend( RTEMS_SELF );
}
void rtems_rate_monotonic_report_statistics_with_plugin(
  void                  *context,
  rtems_printk_plugin_t  print
)
{
  rtems_status_code                      status;
  rtems_id                               id;
  rtems_rate_monotonic_period_statistics the_stats;
  rtems_rate_monotonic_period_status     the_status;
  char                                   name[5];

  if ( !print )
    return;

  (*print)( context, "Period information by period\n" );
  (*print)( context, "--- CPU times are in seconds ---\n" );
  (*print)( context, "--- Wall times are in seconds ---\n" );
/*
Layout by columns -- in memory of Hollerith :)

1234567890123456789012345678901234567890123456789012345678901234567890123456789\
   ID     OWNER COUNT MISSED X
ididididid NNNN ccccc mmmmmm X

  Uncomment the following if you are tinkering with the formatting.
  Be sure to test the various cases.
  (*print)( context,"\
1234567890123456789012345678901234567890123456789012345678901234567890123456789\
\n");
*/
  (*print)( context,
      "   ID     OWNER COUNT MISSED     "
      "     CPU TIME                  WALL TIME\n"
      "                               "
      "     MIN/MAX/AVG                MIN/MAX/AVG\n"
  );

  /*
   * Cycle through all possible ids and try to report on each one.  If it
   * is a period that is inactive, we just get an error back.  No big deal.
   */
  for ( id=_Rate_monotonic_Information.minimum_id ;
        id <= _Rate_monotonic_Information.maximum_id ;
        id++ ) {
    status = rtems_rate_monotonic_get_statistics( id, &the_stats );
    if ( status != RTEMS_SUCCESSFUL )
      continue;

    /* If the above passed, so should this but check it anyway */
    #if defined(RTEMS_DEBUG)
      status = rtems_rate_monotonic_get_status( id, &the_status );
      if ( status != RTEMS_SUCCESSFUL )
        continue;
    #else
      (void) rtems_rate_monotonic_get_status( id, &the_status );
    #endif

    rtems_object_get_name( the_status.owner, sizeof(name), name );

    /*
     *  Print part of report line that is not dependent on granularity
     */
    (*print)( context,
      "0x%08" PRIx32 " %4s %5" PRId32 " %6" PRId32 " ",
      id, name,
      the_stats.count, the_stats.missed_count
    );

    /*
     *  If the count is zero, don't print statistics
     */
    if (the_stats.count == 0) {
      (*print)( context, "\n" );
      continue;
    }

    /*
     *  print CPU Usage part of statistics
     */
    {
      struct timespec  cpu_average;
      struct timespec *min_cpu = &the_stats.min_cpu_time;
      struct timespec *max_cpu = &the_stats.max_cpu_time;
      struct timespec *total_cpu = &the_stats.total_cpu_time;

      _Timespec_Divide_by_integer( total_cpu, the_stats.count, &cpu_average );
      (*print)( context,
        "%" PRId32 "."  NANOSECONDS_FMT "/"        /* min cpu time */
        "%" PRId32 "."  NANOSECONDS_FMT "/"        /* max cpu time */
        "%" PRId32 "."  NANOSECONDS_FMT " ",       /* avg cpu time */
        _Timespec_Get_seconds( min_cpu ),
	  _Timespec_Get_nanoseconds( min_cpu ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( max_cpu ),
	  _Timespec_Get_nanoseconds( max_cpu ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( &cpu_average ),
	  _Timespec_Get_nanoseconds( &cpu_average ) / NANOSECONDS_DIVIDER
       );
    }

    /*
     *  print wall time part of statistics
     */
    {
      struct timespec  wall_average;
      struct timespec *min_wall = &the_stats.min_wall_time;
      struct timespec *max_wall = &the_stats.max_wall_time;
      struct timespec *total_wall = &the_stats.total_wall_time;

      _Timespec_Divide_by_integer(total_wall, the_stats.count, &wall_average);
      (*print)( context,
        "%" PRId32 "." NANOSECONDS_FMT "/"        /* min wall time */
        "%" PRId32 "." NANOSECONDS_FMT "/"        /* max wall time */
        "%" PRId32 "." NANOSECONDS_FMT "\n",      /* avg wall time */
        _Timespec_Get_seconds( min_wall ),
          _Timespec_Get_nanoseconds( min_wall ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( max_wall ),
          _Timespec_Get_nanoseconds( max_wall ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( &wall_average ),
          _Timespec_Get_nanoseconds( &wall_average ) / NANOSECONDS_DIVIDER
      );
    }
  }
}
Exemple #13
0
/* Get thread information, return 0 if thread does not
   exist and 1 otherwise */
static int rtems_gdb_stub_get_thread_info(
  int gdb_index,
  struct rtems_gdb_stub_thread_info *info
)
{
   int first = 1;
   size_t api_index;

   ASSERT(info != NULL);

   if (gdb_index <= 0) {
      return 0;
   }

   if (_System_state_Get() != SYSTEM_STATE_UP || gdb_index == 1) {
      /* We have one thread let us use value
         which will never happen for real thread */
      strcpy(info->display, "idle thread");
      strcpy(info->name, "IDLE");
      info->more_display[0] = 0; /* Nothing */

      return 1;
   }

   for (
     api_index = 1;
     api_index <= OBJECTS_APIS_LAST;
     ++api_index
   ) {
     if (_Objects_Information_table[api_index] != NULL) {
       const Objects_Information *obj_info =
         _Objects_Information_table[api_index][1];
       Objects_Id min_id = obj_info->minimum_id;
       Objects_Id max_id = obj_info->maximum_id;
       int last = first + (int) (max_id - min_id);

       if (gdb_index <= last) {
         Thread_Control *th = (Thread_Control *)
           obj_info->local_table[gdb_index - first + 1];

         if (th != NULL) {
           char tmp_buf[9];

           strcpy(info->display, "task: control at 0x");

           tmp_buf[0] = gdb_hexchars[(((int)th) >> 28) & 0xf];
           tmp_buf[1] = gdb_hexchars[(((int)th) >> 24) & 0xf];
           tmp_buf[2] = gdb_hexchars[(((int)th) >> 20) & 0xf];
           tmp_buf[3] = gdb_hexchars[(((int)th) >> 16) & 0xf];
           tmp_buf[4] = gdb_hexchars[(((int)th) >> 12) & 0xf];
           tmp_buf[5] = gdb_hexchars[(((int)th) >> 8) & 0xf];
           tmp_buf[6] = gdb_hexchars[(((int)th) >> 4) & 0xf];
           tmp_buf[7] = gdb_hexchars[((int)th) & 0xf];
           tmp_buf[8] = 0;

           strcat(info->display, tmp_buf);
           rtems_object_get_name( th->Object.id, 5, info->name );
           info->more_display[0] = 0; /* Nothing */

           return 1;
         } else {
           /* Thread does not exist */
           return 0;
         }
       }
Exemple #14
0
/*
 *  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
}
Exemple #15
0
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(&current_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);
}