1*d44bc558SAdrian Hunter #include <sys/time.h> 2*d44bc558SAdrian Hunter #include <sys/prctl.h> 3*d44bc558SAdrian Hunter #include <time.h> 4*d44bc558SAdrian Hunter #include <stdlib.h> 5*d44bc558SAdrian Hunter 6*d44bc558SAdrian Hunter #include "parse-events.h" 7*d44bc558SAdrian Hunter #include "evlist.h" 8*d44bc558SAdrian Hunter #include "evsel.h" 9*d44bc558SAdrian Hunter #include "thread_map.h" 10*d44bc558SAdrian Hunter #include "cpumap.h" 11*d44bc558SAdrian Hunter #include "tests.h" 12*d44bc558SAdrian Hunter 13*d44bc558SAdrian Hunter static int spin_sleep(void) 14*d44bc558SAdrian Hunter { 15*d44bc558SAdrian Hunter struct timeval start, now, diff, maxtime; 16*d44bc558SAdrian Hunter struct timespec ts; 17*d44bc558SAdrian Hunter int err, i; 18*d44bc558SAdrian Hunter 19*d44bc558SAdrian Hunter maxtime.tv_sec = 0; 20*d44bc558SAdrian Hunter maxtime.tv_usec = 50000; 21*d44bc558SAdrian Hunter 22*d44bc558SAdrian Hunter err = gettimeofday(&start, NULL); 23*d44bc558SAdrian Hunter if (err) 24*d44bc558SAdrian Hunter return err; 25*d44bc558SAdrian Hunter 26*d44bc558SAdrian Hunter /* Spin for 50ms */ 27*d44bc558SAdrian Hunter while (1) { 28*d44bc558SAdrian Hunter for (i = 0; i < 1000; i++) 29*d44bc558SAdrian Hunter barrier(); 30*d44bc558SAdrian Hunter 31*d44bc558SAdrian Hunter err = gettimeofday(&now, NULL); 32*d44bc558SAdrian Hunter if (err) 33*d44bc558SAdrian Hunter return err; 34*d44bc558SAdrian Hunter 35*d44bc558SAdrian Hunter timersub(&now, &start, &diff); 36*d44bc558SAdrian Hunter if (timercmp(&diff, &maxtime, > /* For checkpatch */)) 37*d44bc558SAdrian Hunter break; 38*d44bc558SAdrian Hunter } 39*d44bc558SAdrian Hunter 40*d44bc558SAdrian Hunter ts.tv_nsec = 50 * 1000 * 1000; 41*d44bc558SAdrian Hunter ts.tv_sec = 0; 42*d44bc558SAdrian Hunter 43*d44bc558SAdrian Hunter /* Sleep for 50ms */ 44*d44bc558SAdrian Hunter err = nanosleep(&ts, NULL); 45*d44bc558SAdrian Hunter if (err == EINTR) 46*d44bc558SAdrian Hunter err = 0; 47*d44bc558SAdrian Hunter 48*d44bc558SAdrian Hunter return err; 49*d44bc558SAdrian Hunter } 50*d44bc558SAdrian Hunter 51*d44bc558SAdrian Hunter struct switch_tracking { 52*d44bc558SAdrian Hunter struct perf_evsel *switch_evsel; 53*d44bc558SAdrian Hunter struct perf_evsel *cycles_evsel; 54*d44bc558SAdrian Hunter pid_t *tids; 55*d44bc558SAdrian Hunter int nr_tids; 56*d44bc558SAdrian Hunter int comm_seen[4]; 57*d44bc558SAdrian Hunter int cycles_before_comm_1; 58*d44bc558SAdrian Hunter int cycles_between_comm_2_and_comm_3; 59*d44bc558SAdrian Hunter int cycles_after_comm_4; 60*d44bc558SAdrian Hunter }; 61*d44bc558SAdrian Hunter 62*d44bc558SAdrian Hunter static int check_comm(struct switch_tracking *switch_tracking, 63*d44bc558SAdrian Hunter union perf_event *event, const char *comm, int nr) 64*d44bc558SAdrian Hunter { 65*d44bc558SAdrian Hunter if (event->header.type == PERF_RECORD_COMM && 66*d44bc558SAdrian Hunter (pid_t)event->comm.pid == getpid() && 67*d44bc558SAdrian Hunter (pid_t)event->comm.tid == getpid() && 68*d44bc558SAdrian Hunter strcmp(event->comm.comm, comm) == 0) { 69*d44bc558SAdrian Hunter if (switch_tracking->comm_seen[nr]) { 70*d44bc558SAdrian Hunter pr_debug("Duplicate comm event\n"); 71*d44bc558SAdrian Hunter return -1; 72*d44bc558SAdrian Hunter } 73*d44bc558SAdrian Hunter switch_tracking->comm_seen[nr] = 1; 74*d44bc558SAdrian Hunter pr_debug3("comm event: %s nr: %d\n", event->comm.comm, nr); 75*d44bc558SAdrian Hunter return 1; 76*d44bc558SAdrian Hunter } 77*d44bc558SAdrian Hunter return 0; 78*d44bc558SAdrian Hunter } 79*d44bc558SAdrian Hunter 80*d44bc558SAdrian Hunter static int check_cpu(struct switch_tracking *switch_tracking, int cpu) 81*d44bc558SAdrian Hunter { 82*d44bc558SAdrian Hunter int i, nr = cpu + 1; 83*d44bc558SAdrian Hunter 84*d44bc558SAdrian Hunter if (cpu < 0) 85*d44bc558SAdrian Hunter return -1; 86*d44bc558SAdrian Hunter 87*d44bc558SAdrian Hunter if (!switch_tracking->tids) { 88*d44bc558SAdrian Hunter switch_tracking->tids = calloc(nr, sizeof(pid_t)); 89*d44bc558SAdrian Hunter if (!switch_tracking->tids) 90*d44bc558SAdrian Hunter return -1; 91*d44bc558SAdrian Hunter for (i = 0; i < nr; i++) 92*d44bc558SAdrian Hunter switch_tracking->tids[i] = -1; 93*d44bc558SAdrian Hunter switch_tracking->nr_tids = nr; 94*d44bc558SAdrian Hunter return 0; 95*d44bc558SAdrian Hunter } 96*d44bc558SAdrian Hunter 97*d44bc558SAdrian Hunter if (cpu >= switch_tracking->nr_tids) { 98*d44bc558SAdrian Hunter void *addr; 99*d44bc558SAdrian Hunter 100*d44bc558SAdrian Hunter addr = realloc(switch_tracking->tids, nr * sizeof(pid_t)); 101*d44bc558SAdrian Hunter if (!addr) 102*d44bc558SAdrian Hunter return -1; 103*d44bc558SAdrian Hunter switch_tracking->tids = addr; 104*d44bc558SAdrian Hunter for (i = switch_tracking->nr_tids; i < nr; i++) 105*d44bc558SAdrian Hunter switch_tracking->tids[i] = -1; 106*d44bc558SAdrian Hunter switch_tracking->nr_tids = nr; 107*d44bc558SAdrian Hunter return 0; 108*d44bc558SAdrian Hunter } 109*d44bc558SAdrian Hunter 110*d44bc558SAdrian Hunter return 0; 111*d44bc558SAdrian Hunter } 112*d44bc558SAdrian Hunter 113*d44bc558SAdrian Hunter static int process_sample_event(struct perf_evlist *evlist, 114*d44bc558SAdrian Hunter union perf_event *event, 115*d44bc558SAdrian Hunter struct switch_tracking *switch_tracking) 116*d44bc558SAdrian Hunter { 117*d44bc558SAdrian Hunter struct perf_sample sample; 118*d44bc558SAdrian Hunter struct perf_evsel *evsel; 119*d44bc558SAdrian Hunter pid_t next_tid, prev_tid; 120*d44bc558SAdrian Hunter int cpu, err; 121*d44bc558SAdrian Hunter 122*d44bc558SAdrian Hunter if (perf_evlist__parse_sample(evlist, event, &sample)) { 123*d44bc558SAdrian Hunter pr_debug("perf_evlist__parse_sample failed\n"); 124*d44bc558SAdrian Hunter return -1; 125*d44bc558SAdrian Hunter } 126*d44bc558SAdrian Hunter 127*d44bc558SAdrian Hunter evsel = perf_evlist__id2evsel(evlist, sample.id); 128*d44bc558SAdrian Hunter if (evsel == switch_tracking->switch_evsel) { 129*d44bc558SAdrian Hunter next_tid = perf_evsel__intval(evsel, &sample, "next_pid"); 130*d44bc558SAdrian Hunter prev_tid = perf_evsel__intval(evsel, &sample, "prev_pid"); 131*d44bc558SAdrian Hunter cpu = sample.cpu; 132*d44bc558SAdrian Hunter pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n", 133*d44bc558SAdrian Hunter cpu, prev_tid, next_tid); 134*d44bc558SAdrian Hunter err = check_cpu(switch_tracking, cpu); 135*d44bc558SAdrian Hunter if (err) 136*d44bc558SAdrian Hunter return err; 137*d44bc558SAdrian Hunter /* 138*d44bc558SAdrian Hunter * Check for no missing sched_switch events i.e. that the 139*d44bc558SAdrian Hunter * evsel->system_wide flag has worked. 140*d44bc558SAdrian Hunter */ 141*d44bc558SAdrian Hunter if (switch_tracking->tids[cpu] != -1 && 142*d44bc558SAdrian Hunter switch_tracking->tids[cpu] != prev_tid) { 143*d44bc558SAdrian Hunter pr_debug("Missing sched_switch events\n"); 144*d44bc558SAdrian Hunter return -1; 145*d44bc558SAdrian Hunter } 146*d44bc558SAdrian Hunter switch_tracking->tids[cpu] = next_tid; 147*d44bc558SAdrian Hunter } 148*d44bc558SAdrian Hunter 149*d44bc558SAdrian Hunter if (evsel == switch_tracking->cycles_evsel) { 150*d44bc558SAdrian Hunter pr_debug3("cycles event\n"); 151*d44bc558SAdrian Hunter if (!switch_tracking->comm_seen[0]) 152*d44bc558SAdrian Hunter switch_tracking->cycles_before_comm_1 = 1; 153*d44bc558SAdrian Hunter if (switch_tracking->comm_seen[1] && 154*d44bc558SAdrian Hunter !switch_tracking->comm_seen[2]) 155*d44bc558SAdrian Hunter switch_tracking->cycles_between_comm_2_and_comm_3 = 1; 156*d44bc558SAdrian Hunter if (switch_tracking->comm_seen[3]) 157*d44bc558SAdrian Hunter switch_tracking->cycles_after_comm_4 = 1; 158*d44bc558SAdrian Hunter } 159*d44bc558SAdrian Hunter 160*d44bc558SAdrian Hunter return 0; 161*d44bc558SAdrian Hunter } 162*d44bc558SAdrian Hunter 163*d44bc558SAdrian Hunter static int process_event(struct perf_evlist *evlist, union perf_event *event, 164*d44bc558SAdrian Hunter struct switch_tracking *switch_tracking) 165*d44bc558SAdrian Hunter { 166*d44bc558SAdrian Hunter if (event->header.type == PERF_RECORD_SAMPLE) 167*d44bc558SAdrian Hunter return process_sample_event(evlist, event, switch_tracking); 168*d44bc558SAdrian Hunter 169*d44bc558SAdrian Hunter if (event->header.type == PERF_RECORD_COMM) { 170*d44bc558SAdrian Hunter int err, done = 0; 171*d44bc558SAdrian Hunter 172*d44bc558SAdrian Hunter err = check_comm(switch_tracking, event, "Test COMM 1", 0); 173*d44bc558SAdrian Hunter if (err < 0) 174*d44bc558SAdrian Hunter return -1; 175*d44bc558SAdrian Hunter done += err; 176*d44bc558SAdrian Hunter err = check_comm(switch_tracking, event, "Test COMM 2", 1); 177*d44bc558SAdrian Hunter if (err < 0) 178*d44bc558SAdrian Hunter return -1; 179*d44bc558SAdrian Hunter done += err; 180*d44bc558SAdrian Hunter err = check_comm(switch_tracking, event, "Test COMM 3", 2); 181*d44bc558SAdrian Hunter if (err < 0) 182*d44bc558SAdrian Hunter return -1; 183*d44bc558SAdrian Hunter done += err; 184*d44bc558SAdrian Hunter err = check_comm(switch_tracking, event, "Test COMM 4", 3); 185*d44bc558SAdrian Hunter if (err < 0) 186*d44bc558SAdrian Hunter return -1; 187*d44bc558SAdrian Hunter done += err; 188*d44bc558SAdrian Hunter if (done != 1) { 189*d44bc558SAdrian Hunter pr_debug("Unexpected comm event\n"); 190*d44bc558SAdrian Hunter return -1; 191*d44bc558SAdrian Hunter } 192*d44bc558SAdrian Hunter } 193*d44bc558SAdrian Hunter 194*d44bc558SAdrian Hunter return 0; 195*d44bc558SAdrian Hunter } 196*d44bc558SAdrian Hunter 197*d44bc558SAdrian Hunter struct event_node { 198*d44bc558SAdrian Hunter struct list_head list; 199*d44bc558SAdrian Hunter union perf_event *event; 200*d44bc558SAdrian Hunter u64 event_time; 201*d44bc558SAdrian Hunter }; 202*d44bc558SAdrian Hunter 203*d44bc558SAdrian Hunter static int add_event(struct perf_evlist *evlist, struct list_head *events, 204*d44bc558SAdrian Hunter union perf_event *event) 205*d44bc558SAdrian Hunter { 206*d44bc558SAdrian Hunter struct perf_sample sample; 207*d44bc558SAdrian Hunter struct event_node *node; 208*d44bc558SAdrian Hunter 209*d44bc558SAdrian Hunter node = malloc(sizeof(struct event_node)); 210*d44bc558SAdrian Hunter if (!node) { 211*d44bc558SAdrian Hunter pr_debug("malloc failed\n"); 212*d44bc558SAdrian Hunter return -1; 213*d44bc558SAdrian Hunter } 214*d44bc558SAdrian Hunter node->event = event; 215*d44bc558SAdrian Hunter list_add(&node->list, events); 216*d44bc558SAdrian Hunter 217*d44bc558SAdrian Hunter if (perf_evlist__parse_sample(evlist, event, &sample)) { 218*d44bc558SAdrian Hunter pr_debug("perf_evlist__parse_sample failed\n"); 219*d44bc558SAdrian Hunter return -1; 220*d44bc558SAdrian Hunter } 221*d44bc558SAdrian Hunter 222*d44bc558SAdrian Hunter if (!sample.time) { 223*d44bc558SAdrian Hunter pr_debug("event with no time\n"); 224*d44bc558SAdrian Hunter return -1; 225*d44bc558SAdrian Hunter } 226*d44bc558SAdrian Hunter 227*d44bc558SAdrian Hunter node->event_time = sample.time; 228*d44bc558SAdrian Hunter 229*d44bc558SAdrian Hunter return 0; 230*d44bc558SAdrian Hunter } 231*d44bc558SAdrian Hunter 232*d44bc558SAdrian Hunter static void free_event_nodes(struct list_head *events) 233*d44bc558SAdrian Hunter { 234*d44bc558SAdrian Hunter struct event_node *node; 235*d44bc558SAdrian Hunter 236*d44bc558SAdrian Hunter while (!list_empty(events)) { 237*d44bc558SAdrian Hunter node = list_entry(events->next, struct event_node, list); 238*d44bc558SAdrian Hunter list_del(&node->list); 239*d44bc558SAdrian Hunter free(node); 240*d44bc558SAdrian Hunter } 241*d44bc558SAdrian Hunter } 242*d44bc558SAdrian Hunter 243*d44bc558SAdrian Hunter static int compar(const void *a, const void *b) 244*d44bc558SAdrian Hunter { 245*d44bc558SAdrian Hunter const struct event_node *nodea = a; 246*d44bc558SAdrian Hunter const struct event_node *nodeb = b; 247*d44bc558SAdrian Hunter s64 cmp = nodea->event_time - nodeb->event_time; 248*d44bc558SAdrian Hunter 249*d44bc558SAdrian Hunter return cmp; 250*d44bc558SAdrian Hunter } 251*d44bc558SAdrian Hunter 252*d44bc558SAdrian Hunter static int process_events(struct perf_evlist *evlist, 253*d44bc558SAdrian Hunter struct switch_tracking *switch_tracking) 254*d44bc558SAdrian Hunter { 255*d44bc558SAdrian Hunter union perf_event *event; 256*d44bc558SAdrian Hunter unsigned pos, cnt = 0; 257*d44bc558SAdrian Hunter LIST_HEAD(events); 258*d44bc558SAdrian Hunter struct event_node *events_array, *node; 259*d44bc558SAdrian Hunter int i, ret; 260*d44bc558SAdrian Hunter 261*d44bc558SAdrian Hunter for (i = 0; i < evlist->nr_mmaps; i++) { 262*d44bc558SAdrian Hunter while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 263*d44bc558SAdrian Hunter cnt += 1; 264*d44bc558SAdrian Hunter ret = add_event(evlist, &events, event); 265*d44bc558SAdrian Hunter perf_evlist__mmap_consume(evlist, i); 266*d44bc558SAdrian Hunter if (ret < 0) 267*d44bc558SAdrian Hunter goto out_free_nodes; 268*d44bc558SAdrian Hunter } 269*d44bc558SAdrian Hunter } 270*d44bc558SAdrian Hunter 271*d44bc558SAdrian Hunter events_array = calloc(cnt, sizeof(struct event_node)); 272*d44bc558SAdrian Hunter if (!events_array) { 273*d44bc558SAdrian Hunter pr_debug("calloc failed\n"); 274*d44bc558SAdrian Hunter ret = -1; 275*d44bc558SAdrian Hunter goto out_free_nodes; 276*d44bc558SAdrian Hunter } 277*d44bc558SAdrian Hunter 278*d44bc558SAdrian Hunter pos = 0; 279*d44bc558SAdrian Hunter list_for_each_entry(node, &events, list) 280*d44bc558SAdrian Hunter events_array[pos++] = *node; 281*d44bc558SAdrian Hunter 282*d44bc558SAdrian Hunter qsort(events_array, cnt, sizeof(struct event_node), compar); 283*d44bc558SAdrian Hunter 284*d44bc558SAdrian Hunter for (pos = 0; pos < cnt; pos++) { 285*d44bc558SAdrian Hunter ret = process_event(evlist, events_array[pos].event, 286*d44bc558SAdrian Hunter switch_tracking); 287*d44bc558SAdrian Hunter if (ret < 0) 288*d44bc558SAdrian Hunter goto out_free; 289*d44bc558SAdrian Hunter } 290*d44bc558SAdrian Hunter 291*d44bc558SAdrian Hunter ret = 0; 292*d44bc558SAdrian Hunter out_free: 293*d44bc558SAdrian Hunter pr_debug("%u events recorded\n", cnt); 294*d44bc558SAdrian Hunter free(events_array); 295*d44bc558SAdrian Hunter out_free_nodes: 296*d44bc558SAdrian Hunter free_event_nodes(&events); 297*d44bc558SAdrian Hunter return ret; 298*d44bc558SAdrian Hunter } 299*d44bc558SAdrian Hunter 300*d44bc558SAdrian Hunter /** 301*d44bc558SAdrian Hunter * test__switch_tracking - test using sched_switch and tracking events. 302*d44bc558SAdrian Hunter * 303*d44bc558SAdrian Hunter * This function implements a test that checks that sched_switch events and 304*d44bc558SAdrian Hunter * tracking events can be recorded for a workload (current process) using the 305*d44bc558SAdrian Hunter * evsel->system_wide and evsel->tracking flags (respectively) with other events 306*d44bc558SAdrian Hunter * sometimes enabled or disabled. 307*d44bc558SAdrian Hunter */ 308*d44bc558SAdrian Hunter int test__switch_tracking(void) 309*d44bc558SAdrian Hunter { 310*d44bc558SAdrian Hunter const char *sched_switch = "sched:sched_switch"; 311*d44bc558SAdrian Hunter struct switch_tracking switch_tracking = { .tids = NULL, }; 312*d44bc558SAdrian Hunter struct record_opts opts = { 313*d44bc558SAdrian Hunter .mmap_pages = UINT_MAX, 314*d44bc558SAdrian Hunter .user_freq = UINT_MAX, 315*d44bc558SAdrian Hunter .user_interval = ULLONG_MAX, 316*d44bc558SAdrian Hunter .freq = 4000, 317*d44bc558SAdrian Hunter .target = { 318*d44bc558SAdrian Hunter .uses_mmap = true, 319*d44bc558SAdrian Hunter }, 320*d44bc558SAdrian Hunter }; 321*d44bc558SAdrian Hunter struct thread_map *threads = NULL; 322*d44bc558SAdrian Hunter struct cpu_map *cpus = NULL; 323*d44bc558SAdrian Hunter struct perf_evlist *evlist = NULL; 324*d44bc558SAdrian Hunter struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel; 325*d44bc558SAdrian Hunter struct perf_evsel *switch_evsel, *tracking_evsel; 326*d44bc558SAdrian Hunter const char *comm; 327*d44bc558SAdrian Hunter int err = -1; 328*d44bc558SAdrian Hunter 329*d44bc558SAdrian Hunter threads = thread_map__new(-1, getpid(), UINT_MAX); 330*d44bc558SAdrian Hunter if (!threads) { 331*d44bc558SAdrian Hunter pr_debug("thread_map__new failed!\n"); 332*d44bc558SAdrian Hunter goto out_err; 333*d44bc558SAdrian Hunter } 334*d44bc558SAdrian Hunter 335*d44bc558SAdrian Hunter cpus = cpu_map__new(NULL); 336*d44bc558SAdrian Hunter if (!cpus) { 337*d44bc558SAdrian Hunter pr_debug("cpu_map__new failed!\n"); 338*d44bc558SAdrian Hunter goto out_err; 339*d44bc558SAdrian Hunter } 340*d44bc558SAdrian Hunter 341*d44bc558SAdrian Hunter evlist = perf_evlist__new(); 342*d44bc558SAdrian Hunter if (!evlist) { 343*d44bc558SAdrian Hunter pr_debug("perf_evlist__new failed!\n"); 344*d44bc558SAdrian Hunter goto out_err; 345*d44bc558SAdrian Hunter } 346*d44bc558SAdrian Hunter 347*d44bc558SAdrian Hunter perf_evlist__set_maps(evlist, cpus, threads); 348*d44bc558SAdrian Hunter 349*d44bc558SAdrian Hunter /* First event */ 350*d44bc558SAdrian Hunter err = parse_events(evlist, "cpu-clock:u"); 351*d44bc558SAdrian Hunter if (err) { 352*d44bc558SAdrian Hunter pr_debug("Failed to parse event dummy:u\n"); 353*d44bc558SAdrian Hunter goto out_err; 354*d44bc558SAdrian Hunter } 355*d44bc558SAdrian Hunter 356*d44bc558SAdrian Hunter cpu_clocks_evsel = perf_evlist__last(evlist); 357*d44bc558SAdrian Hunter 358*d44bc558SAdrian Hunter /* Second event */ 359*d44bc558SAdrian Hunter err = parse_events(evlist, "cycles:u"); 360*d44bc558SAdrian Hunter if (err) { 361*d44bc558SAdrian Hunter pr_debug("Failed to parse event cycles:u\n"); 362*d44bc558SAdrian Hunter goto out_err; 363*d44bc558SAdrian Hunter } 364*d44bc558SAdrian Hunter 365*d44bc558SAdrian Hunter cycles_evsel = perf_evlist__last(evlist); 366*d44bc558SAdrian Hunter 367*d44bc558SAdrian Hunter /* Third event */ 368*d44bc558SAdrian Hunter if (!perf_evlist__can_select_event(evlist, sched_switch)) { 369*d44bc558SAdrian Hunter fprintf(stderr, " (no sched_switch)"); 370*d44bc558SAdrian Hunter err = 0; 371*d44bc558SAdrian Hunter goto out; 372*d44bc558SAdrian Hunter } 373*d44bc558SAdrian Hunter 374*d44bc558SAdrian Hunter err = parse_events(evlist, sched_switch); 375*d44bc558SAdrian Hunter if (err) { 376*d44bc558SAdrian Hunter pr_debug("Failed to parse event %s\n", sched_switch); 377*d44bc558SAdrian Hunter goto out_err; 378*d44bc558SAdrian Hunter } 379*d44bc558SAdrian Hunter 380*d44bc558SAdrian Hunter switch_evsel = perf_evlist__last(evlist); 381*d44bc558SAdrian Hunter 382*d44bc558SAdrian Hunter perf_evsel__set_sample_bit(switch_evsel, CPU); 383*d44bc558SAdrian Hunter perf_evsel__set_sample_bit(switch_evsel, TIME); 384*d44bc558SAdrian Hunter 385*d44bc558SAdrian Hunter switch_evsel->system_wide = true; 386*d44bc558SAdrian Hunter switch_evsel->no_aux_samples = true; 387*d44bc558SAdrian Hunter switch_evsel->immediate = true; 388*d44bc558SAdrian Hunter 389*d44bc558SAdrian Hunter /* Test moving an event to the front */ 390*d44bc558SAdrian Hunter if (cycles_evsel == perf_evlist__first(evlist)) { 391*d44bc558SAdrian Hunter pr_debug("cycles event already at front"); 392*d44bc558SAdrian Hunter goto out_err; 393*d44bc558SAdrian Hunter } 394*d44bc558SAdrian Hunter perf_evlist__to_front(evlist, cycles_evsel); 395*d44bc558SAdrian Hunter if (cycles_evsel != perf_evlist__first(evlist)) { 396*d44bc558SAdrian Hunter pr_debug("Failed to move cycles event to front"); 397*d44bc558SAdrian Hunter goto out_err; 398*d44bc558SAdrian Hunter } 399*d44bc558SAdrian Hunter 400*d44bc558SAdrian Hunter perf_evsel__set_sample_bit(cycles_evsel, CPU); 401*d44bc558SAdrian Hunter perf_evsel__set_sample_bit(cycles_evsel, TIME); 402*d44bc558SAdrian Hunter 403*d44bc558SAdrian Hunter /* Fourth event */ 404*d44bc558SAdrian Hunter err = parse_events(evlist, "dummy:u"); 405*d44bc558SAdrian Hunter if (err) { 406*d44bc558SAdrian Hunter pr_debug("Failed to parse event dummy:u\n"); 407*d44bc558SAdrian Hunter goto out_err; 408*d44bc558SAdrian Hunter } 409*d44bc558SAdrian Hunter 410*d44bc558SAdrian Hunter tracking_evsel = perf_evlist__last(evlist); 411*d44bc558SAdrian Hunter 412*d44bc558SAdrian Hunter perf_evlist__set_tracking_event(evlist, tracking_evsel); 413*d44bc558SAdrian Hunter 414*d44bc558SAdrian Hunter tracking_evsel->attr.freq = 0; 415*d44bc558SAdrian Hunter tracking_evsel->attr.sample_period = 1; 416*d44bc558SAdrian Hunter 417*d44bc558SAdrian Hunter perf_evsel__set_sample_bit(tracking_evsel, TIME); 418*d44bc558SAdrian Hunter 419*d44bc558SAdrian Hunter /* Config events */ 420*d44bc558SAdrian Hunter perf_evlist__config(evlist, &opts); 421*d44bc558SAdrian Hunter 422*d44bc558SAdrian Hunter /* Check moved event is still at the front */ 423*d44bc558SAdrian Hunter if (cycles_evsel != perf_evlist__first(evlist)) { 424*d44bc558SAdrian Hunter pr_debug("Front event no longer at front"); 425*d44bc558SAdrian Hunter goto out_err; 426*d44bc558SAdrian Hunter } 427*d44bc558SAdrian Hunter 428*d44bc558SAdrian Hunter /* Check tracking event is tracking */ 429*d44bc558SAdrian Hunter if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) { 430*d44bc558SAdrian Hunter pr_debug("Tracking event not tracking\n"); 431*d44bc558SAdrian Hunter goto out_err; 432*d44bc558SAdrian Hunter } 433*d44bc558SAdrian Hunter 434*d44bc558SAdrian Hunter /* Check non-tracking events are not tracking */ 435*d44bc558SAdrian Hunter evlist__for_each(evlist, evsel) { 436*d44bc558SAdrian Hunter if (evsel != tracking_evsel) { 437*d44bc558SAdrian Hunter if (evsel->attr.mmap || evsel->attr.comm) { 438*d44bc558SAdrian Hunter pr_debug("Non-tracking event is tracking\n"); 439*d44bc558SAdrian Hunter goto out_err; 440*d44bc558SAdrian Hunter } 441*d44bc558SAdrian Hunter } 442*d44bc558SAdrian Hunter } 443*d44bc558SAdrian Hunter 444*d44bc558SAdrian Hunter if (perf_evlist__open(evlist) < 0) { 445*d44bc558SAdrian Hunter fprintf(stderr, " (not supported)"); 446*d44bc558SAdrian Hunter err = 0; 447*d44bc558SAdrian Hunter goto out; 448*d44bc558SAdrian Hunter } 449*d44bc558SAdrian Hunter 450*d44bc558SAdrian Hunter err = perf_evlist__mmap(evlist, UINT_MAX, false); 451*d44bc558SAdrian Hunter if (err) { 452*d44bc558SAdrian Hunter pr_debug("perf_evlist__mmap failed!\n"); 453*d44bc558SAdrian Hunter goto out_err; 454*d44bc558SAdrian Hunter } 455*d44bc558SAdrian Hunter 456*d44bc558SAdrian Hunter perf_evlist__enable(evlist); 457*d44bc558SAdrian Hunter 458*d44bc558SAdrian Hunter err = perf_evlist__disable_event(evlist, cpu_clocks_evsel); 459*d44bc558SAdrian Hunter if (err) { 460*d44bc558SAdrian Hunter pr_debug("perf_evlist__disable_event failed!\n"); 461*d44bc558SAdrian Hunter goto out_err; 462*d44bc558SAdrian Hunter } 463*d44bc558SAdrian Hunter 464*d44bc558SAdrian Hunter err = spin_sleep(); 465*d44bc558SAdrian Hunter if (err) { 466*d44bc558SAdrian Hunter pr_debug("spin_sleep failed!\n"); 467*d44bc558SAdrian Hunter goto out_err; 468*d44bc558SAdrian Hunter } 469*d44bc558SAdrian Hunter 470*d44bc558SAdrian Hunter comm = "Test COMM 1"; 471*d44bc558SAdrian Hunter err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0); 472*d44bc558SAdrian Hunter if (err) { 473*d44bc558SAdrian Hunter pr_debug("PR_SET_NAME failed!\n"); 474*d44bc558SAdrian Hunter goto out_err; 475*d44bc558SAdrian Hunter } 476*d44bc558SAdrian Hunter 477*d44bc558SAdrian Hunter err = perf_evlist__disable_event(evlist, cycles_evsel); 478*d44bc558SAdrian Hunter if (err) { 479*d44bc558SAdrian Hunter pr_debug("perf_evlist__disable_event failed!\n"); 480*d44bc558SAdrian Hunter goto out_err; 481*d44bc558SAdrian Hunter } 482*d44bc558SAdrian Hunter 483*d44bc558SAdrian Hunter comm = "Test COMM 2"; 484*d44bc558SAdrian Hunter err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0); 485*d44bc558SAdrian Hunter if (err) { 486*d44bc558SAdrian Hunter pr_debug("PR_SET_NAME failed!\n"); 487*d44bc558SAdrian Hunter goto out_err; 488*d44bc558SAdrian Hunter } 489*d44bc558SAdrian Hunter 490*d44bc558SAdrian Hunter err = spin_sleep(); 491*d44bc558SAdrian Hunter if (err) { 492*d44bc558SAdrian Hunter pr_debug("spin_sleep failed!\n"); 493*d44bc558SAdrian Hunter goto out_err; 494*d44bc558SAdrian Hunter } 495*d44bc558SAdrian Hunter 496*d44bc558SAdrian Hunter comm = "Test COMM 3"; 497*d44bc558SAdrian Hunter err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0); 498*d44bc558SAdrian Hunter if (err) { 499*d44bc558SAdrian Hunter pr_debug("PR_SET_NAME failed!\n"); 500*d44bc558SAdrian Hunter goto out_err; 501*d44bc558SAdrian Hunter } 502*d44bc558SAdrian Hunter 503*d44bc558SAdrian Hunter err = perf_evlist__enable_event(evlist, cycles_evsel); 504*d44bc558SAdrian Hunter if (err) { 505*d44bc558SAdrian Hunter pr_debug("perf_evlist__disable_event failed!\n"); 506*d44bc558SAdrian Hunter goto out_err; 507*d44bc558SAdrian Hunter } 508*d44bc558SAdrian Hunter 509*d44bc558SAdrian Hunter comm = "Test COMM 4"; 510*d44bc558SAdrian Hunter err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0); 511*d44bc558SAdrian Hunter if (err) { 512*d44bc558SAdrian Hunter pr_debug("PR_SET_NAME failed!\n"); 513*d44bc558SAdrian Hunter goto out_err; 514*d44bc558SAdrian Hunter } 515*d44bc558SAdrian Hunter 516*d44bc558SAdrian Hunter err = spin_sleep(); 517*d44bc558SAdrian Hunter if (err) { 518*d44bc558SAdrian Hunter pr_debug("spin_sleep failed!\n"); 519*d44bc558SAdrian Hunter goto out_err; 520*d44bc558SAdrian Hunter } 521*d44bc558SAdrian Hunter 522*d44bc558SAdrian Hunter perf_evlist__disable(evlist); 523*d44bc558SAdrian Hunter 524*d44bc558SAdrian Hunter switch_tracking.switch_evsel = switch_evsel; 525*d44bc558SAdrian Hunter switch_tracking.cycles_evsel = cycles_evsel; 526*d44bc558SAdrian Hunter 527*d44bc558SAdrian Hunter err = process_events(evlist, &switch_tracking); 528*d44bc558SAdrian Hunter 529*d44bc558SAdrian Hunter zfree(&switch_tracking.tids); 530*d44bc558SAdrian Hunter 531*d44bc558SAdrian Hunter if (err) 532*d44bc558SAdrian Hunter goto out_err; 533*d44bc558SAdrian Hunter 534*d44bc558SAdrian Hunter /* Check all 4 comm events were seen i.e. that evsel->tracking works */ 535*d44bc558SAdrian Hunter if (!switch_tracking.comm_seen[0] || !switch_tracking.comm_seen[1] || 536*d44bc558SAdrian Hunter !switch_tracking.comm_seen[2] || !switch_tracking.comm_seen[3]) { 537*d44bc558SAdrian Hunter pr_debug("Missing comm events\n"); 538*d44bc558SAdrian Hunter goto out_err; 539*d44bc558SAdrian Hunter } 540*d44bc558SAdrian Hunter 541*d44bc558SAdrian Hunter /* Check cycles event got enabled */ 542*d44bc558SAdrian Hunter if (!switch_tracking.cycles_before_comm_1) { 543*d44bc558SAdrian Hunter pr_debug("Missing cycles events\n"); 544*d44bc558SAdrian Hunter goto out_err; 545*d44bc558SAdrian Hunter } 546*d44bc558SAdrian Hunter 547*d44bc558SAdrian Hunter /* Check cycles event got disabled */ 548*d44bc558SAdrian Hunter if (switch_tracking.cycles_between_comm_2_and_comm_3) { 549*d44bc558SAdrian Hunter pr_debug("cycles events even though event was disabled\n"); 550*d44bc558SAdrian Hunter goto out_err; 551*d44bc558SAdrian Hunter } 552*d44bc558SAdrian Hunter 553*d44bc558SAdrian Hunter /* Check cycles event got enabled again */ 554*d44bc558SAdrian Hunter if (!switch_tracking.cycles_after_comm_4) { 555*d44bc558SAdrian Hunter pr_debug("Missing cycles events\n"); 556*d44bc558SAdrian Hunter goto out_err; 557*d44bc558SAdrian Hunter } 558*d44bc558SAdrian Hunter out: 559*d44bc558SAdrian Hunter if (evlist) { 560*d44bc558SAdrian Hunter perf_evlist__disable(evlist); 561*d44bc558SAdrian Hunter perf_evlist__delete(evlist); 562*d44bc558SAdrian Hunter } else { 563*d44bc558SAdrian Hunter cpu_map__delete(cpus); 564*d44bc558SAdrian Hunter thread_map__delete(threads); 565*d44bc558SAdrian Hunter } 566*d44bc558SAdrian Hunter 567*d44bc558SAdrian Hunter return err; 568*d44bc558SAdrian Hunter 569*d44bc558SAdrian Hunter out_err: 570*d44bc558SAdrian Hunter err = -1; 571*d44bc558SAdrian Hunter goto out; 572*d44bc558SAdrian Hunter } 573