Changeset 6da06c5 in rtems for testsuites/smptests


Ignore:
Timestamp:
Aug 30, 2016, 6:46:25 AM (3 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
1c18ebf
Parents:
caf2cbd
git-author:
Chris Johns <chrisj@…> (08/30/16 06:46:25)
git-committer:
Chris Johns <chrisj@…> (09/01/16 01:11:22)
Message:

libmisc/capture: Fix the capture engine on SMP.

This patches some issues with the capture engine:

  1. Check is the engine is open in ctrace commands.
  2. Check all record open and appends for overflow.
  3. Fix the record open to take the size of user data and not the record header.
  4. Use packed structs for data being written to the per cpu buffers.
  5. Remove direct struct access to the capture buffers to avoid misaligned accesses.
  6. Add support to extract records, no struct access to the capture buffers.
  7. Update ctrace to extract records from the capture buffers.
  8. Add support to ctrace to always print the task name if it has one.
  9. Add support to manage names or the lack of a name.
  1. Range of minor fixes.
  2. Fix a long standing bug in ctset's handling of args.

Closes #2780.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • testsuites/smptests/smpcapture02/init.c

    rcaf2cbd r6da06c5  
    1515 *
    1616 */
     17
     18/* #define VERBOSE 1 */
    1719
    1820#ifdef HAVE_CONFIG_H
     
    5153static rtems_interrupt_handler org_clock_handler;
    5254
    53 enum cap_rec_types {
     55typedef enum {
    5456  enter_add_number,
    5557  exit_add_number,
    5658  clock_tick
    57 };
     59} cap_rec_type;
    5860
    5961/*
    6062 * These records define the data stored in the capture trace.
    61  * The records must be 64-bit aligned to make sure that the time
    62  * attribute in rtems_capture_record_t is correctly aligned.
     63 * The records must be packed so alignment issues are not a factor.
    6364 */
    6465typedef struct {
    65   enum cap_rec_types id;
    6666  uint32_t a;
    6767  uint32_t b;
    68 } __attribute__ ((aligned (8))) enter_add_number_record_t;
     68} RTEMS_PACKED enter_add_number_record_t;
    6969
    7070typedef struct {
    71   enum cap_rec_types id;
    7271  uint32_t res;
    73 } __attribute__ ((aligned (8))) exit_add_number_record_t;
     72} RTEMS_PACKED exit_add_number_record_t;
    7473
    7574typedef struct {
    76   enum cap_rec_types id;
    7775  void *arg;
    78 } __attribute__ ((aligned (8))) clock_tick_record_t;
    79 
    80 typedef struct {
    81   enum cap_rec_types id;
    82 } empty_record_t ;
     76} RTEMS_PACKED clock_tick_record_t;
     77
     78/*
     79 * Create a printable set of char's from a name.
     80 */
     81#define PNAME(n) \
     82  (char) (n >> 24) & 0xff, (char) (n >> 16) & 0xff, \
     83  (char) (n >> 8) & 0xff, (char) (n >> 0) & 0xff
    8384
    8485/*
     
    8788static uint32_t add_number(uint32_t a, uint32_t b)
    8889{
    89   return a+b;
     90  return a + b;
    9091}
    9192
     
    9697static uint32_t add_number_wrapper(uint32_t a, uint32_t b)
    9798{
     99  rtems_capture_record_lock_context lock;
    98100  enter_add_number_record_t enter_rec;
    99101  exit_add_number_record_t exit_rec;
     102  cap_rec_type id;
    100103  uint32_t res;
    101104  void* rec;
    102105
    103   enter_rec.id = enter_add_number;
     106  id = enter_add_number;
    104107  enter_rec.a = a;
    105108  enter_rec.b = b;
    106109
    107   rtems_capture_begin_add_record(_Thread_Get_executing(),
    108       RTEMS_CAPTURE_TIMESTAMP, sizeof(rtems_capture_record_t)+
    109       sizeof(enter_add_number_record_t), &rec);
    110   rec = rtems_capture_append_to_record(rec, &enter_rec, sizeof(enter_rec));
    111   rtems_capture_end_add_record(rec);
     110  rec = rtems_capture_record_open(_Thread_Get_executing(),
     111                                  RTEMS_CAPTURE_TIMESTAMP,
     112                                  sizeof(id) + sizeof(enter_rec),
     113                                  &lock);
     114  rtems_test_assert(rec != NULL);
     115  rec = rtems_capture_record_append(rec, &id, sizeof(id));
     116  rtems_test_assert(rec != NULL);
     117  rec = rtems_capture_record_append(rec, &enter_rec, sizeof(enter_rec));
     118  rtems_test_assert(rec != NULL);
     119  rtems_capture_record_close(&lock);
    112120
    113121  res = add_number(a, b);
    114122
    115   exit_rec.id = exit_add_number;
     123  id = exit_add_number;
    116124  exit_rec.res = res;
    117125
    118   rtems_capture_begin_add_record(_Thread_Get_executing(),
    119       RTEMS_CAPTURE_TIMESTAMP, sizeof(rtems_capture_record_t)+
    120       sizeof(exit_add_number_record_t), &rec);
    121   rec = rtems_capture_append_to_record(rec, &exit_rec, sizeof(exit_rec));
    122   rtems_capture_end_add_record(rec);
     126  rec = rtems_capture_record_open(_Thread_Get_executing(),
     127                                  RTEMS_CAPTURE_TIMESTAMP,
     128                                  sizeof(id) + sizeof(exit_rec),
     129                                  &lock);
     130  rtems_test_assert(rec != NULL);
     131  rec = rtems_capture_record_append(rec, &id, sizeof(id));
     132  rtems_test_assert(rec != NULL);
     133  rec = rtems_capture_record_append(rec, &exit_rec, sizeof(exit_rec));
     134  rtems_test_assert(rec != NULL);
     135  rtems_capture_record_close(&lock);
    123136
    124137  return res;
     
    229242static void clock_tick_wrapper(void *arg)
    230243{
     244  rtems_capture_record_lock_context lock;
     245  cap_rec_type id  = clock_tick;
     246  Thread_Control* tcb = _Thread_Get_executing();
    231247  void* rec;
    232   clock_tick_record_t clock_tick_record = {.id = clock_tick};
    233   Thread_Control* tcb = _Thread_Get_executing();
    234 
    235   rtems_capture_begin_add_record(tcb, RTEMS_CAPTURE_TIMESTAMP,
    236       sizeof(rtems_capture_record_t) + sizeof(clock_tick_record_t), &rec);
    237   rec = rtems_capture_append_to_record(rec, &clock_tick_record,
    238       sizeof(clock_tick_record));
    239   rtems_capture_end_add_record(rec);
     248
     249  rec = rtems_capture_record_open(tcb,
     250                                  RTEMS_CAPTURE_TIMESTAMP,
     251                                  sizeof(id),
     252                                  &lock);
     253  rtems_test_assert(rec != NULL);
     254  rec = rtems_capture_record_append(rec, &id, sizeof(id));
     255  rtems_test_assert(rec != NULL);
     256  rtems_capture_record_close(&lock);
    240257
    241258  org_clock_handler(arg);
     
    264281  uint32_t cpu;
    265282  uint32_t cpu_count;
    266   uint32_t read;
    267283  uint32_t enter_count;
    268284  uint32_t exit_count;
    269285  uint32_t clock_tick_count;
    270286  uint32_t res_should_be;
     287  rtems_vector_number vec;
     288  size_t read;
     289  const void *recs;
     290  cap_rec_type id;
     291  rtems_capture_record_t rec;
     292  rtems_capture_record_t prev_rec;
     293  enter_add_number_record_t enter_rec;
     294  exit_add_number_record_t exit_rec;
     295  clock_interrupt_handler cih = {.found = 0};
     296
     297#ifdef VERBOSE
    271298  rtems_name name;
    272   rtems_capture_record_t *recs;
    273   rtems_capture_record_t *prev_rec;
    274   empty_record_t *record;
    275   enter_add_number_record_t *enter_add_number_rec;
    276   exit_add_number_record_t *exit_add_number_rec;
    277   rtems_vector_number vec;
    278   clock_interrupt_handler cih = {.found = 0};
     299#endif
    279300
    280301  TEST_BEGIN();
     
    326347    sc = rtems_capture_read(cpu, &read, &recs);
    327348    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
    328 
    329     prev_rec = recs;
     349    rtems_test_assert(recs != NULL);
     350
     351    memset(&rec, 0, sizeof(rec));
     352    prev_rec = rec;
    330353    enter_count = 0;
    331354    exit_count = 0;
     
    334357    for ( i = 0; i < read; i++ ) {
    335358
     359      recs = rtems_capture_record_extract(recs, &rec, sizeof(rec));
     360      rtems_test_assert(recs != NULL);
     361
    336362      /* Verify that time goes forward */
    337       rtems_test_assert(recs->time>=prev_rec->time);
    338 
    339       if ( recs->events & RTEMS_CAPTURE_TIMESTAMP ) {
    340         record = (empty_record_t*)((char*) recs +
    341             sizeof(rtems_capture_record_t));
    342 
    343         switch ( record->id ) {
     363      rtems_test_assert(rec.time >= prev_rec.time);
     364
     365      if ((rec.events & RTEMS_CAPTURE_TIMESTAMP) != 0) {
     366        recs = rtems_capture_record_extract(recs, &id, sizeof(id));
     367        rtems_test_assert(recs != NULL);
     368
     369        switch (id) {
    344370        case enter_add_number:
    345           rtems_test_assert(enter_count==exit_count);
     371          rtems_test_assert(enter_count == exit_count);
    346372          enter_count++;
    347           enter_add_number_rec = (enter_add_number_record_t*)record;
    348           res_should_be = add_number(enter_add_number_rec->a,
    349               enter_add_number_rec->b);
    350           rtems_object_get_classic_name(recs->task_id, &name);
    351 
     373          recs = rtems_capture_record_extract(recs,
     374                                              &enter_rec,
     375                                              sizeof(enter_rec));
     376          rtems_test_assert(recs != NULL);
     377          res_should_be = add_number(enter_rec.a, enter_rec.b);
    352378#ifdef VERBOSE
    353379          /* Print record */
    354           printf("Time: %"PRIu64"us Task: %4s => Add %"PRIu32" and"
    355               " %"PRIu32"\n",
    356               recs->time/1000,
    357               (char*)&name,
    358               enter_add_number_rec->a,
    359               enter_add_number_rec->b);
     380          rtems_object_get_classic_name(rec.task_id, &name);
     381          printf("Time: %"PRIu64"us Task: %c%c%c%c => Add %"PRIu32" and %"PRIu32" is %"PRIu32"\n",
     382                 rec.time / 1000, PNAME(name), enter_rec.a, enter_rec.b, res_should_be);
    360383#endif
    361384          break;
    362385        case exit_add_number:
    363           rtems_test_assert(enter_count==exit_count+1);
     386          rtems_test_assert(enter_count == exit_count+1);
    364387          exit_count++;
    365           exit_add_number_rec = (exit_add_number_record_t*)record;
    366           /* Verify that the result matches the expected result */
    367           rtems_test_assert(res_should_be == exit_add_number_rec->res);
    368 
     388          recs = rtems_capture_record_extract(recs,
     389                                              &exit_rec,
     390                                              sizeof(exit_rec));
     391          rtems_test_assert(recs != NULL);
    369392#ifdef VERBOSE
    370393          /* Print record */
    371           rtems_object_get_classic_name(recs->task_id, &name);
    372           printf("Time: %"PRIu64"us Task: %4s => Result is %"PRIu32"\n",
    373               recs->time/1000,
    374               (char*)&name,
    375               exit_add_number_rec->res);
    376 #endif
     394          rtems_object_get_classic_name(rec.task_id, &name);
     395          printf("Time: %"PRIu64"us Task: %c%c%c%c => Result is %"PRIu32"\n",
     396                 rec.time / 1000, PNAME(name), exit_rec.res);
     397#endif
     398          /* Verify that the result matches the expected result */
     399          rtems_test_assert(res_should_be == exit_rec.res);
    377400          break;
    378401        case clock_tick:
    379402          clock_tick_count++;
    380403#ifdef VERBOSE
    381           rtems_object_get_classic_name(recs->task_id, &name);
    382           printf("Time: %"PRIu64"us Task: %4s => Clock tick\n",
    383               recs->time/1000,
    384               (char*)&name);
     404          rtems_object_get_classic_name(rec.task_id, &name);
     405          printf("Time: %"PRIu64"us Task: %c%c%c%c => Clock tick\n",
     406                 rec.time/1000, PNAME(name));
    385407#endif
    386408          break;
     
    390412      }
    391413
    392       prev_rec = recs;
    393       recs = (rtems_capture_record_t*) ((char*) recs + recs->size);
     414      prev_rec = rec;
    394415    }
    395416
     
    399420    rtems_capture_release(cpu, read);
    400421  }
    401 
    402   if( cih.found )
    403     rtems_test_assert(clock_tick_count == cpu_count * CLOCK_TICKS);
    404422
    405423  TEST_END();
Note: See TracChangeset for help on using the changeset viewer.