//Assert if put_myid() could not find you a slot //Ideally each pthread must be associated with cpu int get_myid(void) { int i, ncpus; pthread_t pid; pid = (long)pthread_self(); ncpus = get_nr_cpus(); spinlock_lock(&sl); for (i = 0; i < ncpus; i++) { if (pcpu[i].pid == pid) goto ret; } // First time caller if ((i = put_myid(pid)) >= 0) { goto ret; } else { spinlock_unlock(&sl); assert(0); } ret: myassert(i == threadId, "get_myid returning wrong id:%d, threadId:%d, PID:%p\n", i, threadId, pid); spinlock_unlock(&sl); return i; }
// Returns -1 on error, returns id >=0 otherwise static int put_myid(long pid) { int i; int ncpus; ncpus = get_nr_cpus(); for (i = 0; i < ncpus; i++) { if (pcpu[i].pid == -1) { pcpu[i].pid = pid; dprintLine("Installing %p as %d\n", pid, i); return i; } } myassert(0, "Failed to find place to put cpuId for %p\n", pid); return -1; }
int main(int argc, char* argv[]) { pthread_t proc_events_thread; void *status; int rc, opt, cycles = INT_MAX; #ifdef DEBUG_ENABLED logfile = fopen(DEBUG_LOGFILE, "w"); if (logfile == NULL) DIE_PERROR("Cannot open file " DEBUG_LOGFILE " for writing"); #endif #ifdef CONFIG_NCURSES /* default is ncurses output */ output = &oops_ncurses; #else output = &oops_stdout; #endif while (1) { int option_index = 0; static struct option long_options[] = { { "realtime", no_argument, &opt_realtime, 1}, { "all_cpus", no_argument, &opt_all_cpus, 1}, { "sort", required_argument, 0, 's'}, { "output", required_argument, 0, 'o'}, { "seconds", required_argument, 0, 't' }, { "milliseconds",required_argument, 0, 'm' }, { "cycles", required_argument, 0, 'c' }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 }, }; opt = getopt_long(argc, argv, "s:o:c:h?", long_options, &option_index); if (opt == -1) break; switch (opt) { case 'o': if (strcmp(optarg, "csv") == 0) output = &oops_csv; else if (strcmp(optarg, "stdout") == 0) output = &oops_stdout; #ifdef CONFIG_NCURSES else if (strcmp(optarg, "ncurses") == 0) output = &oops_ncurses; #endif else if (strcmp(optarg, "nop") == 0) output = &oops_nop; else { /* unknown */ fprintf(stderr, "Unknown output method %s\n", optarg); print_help(argc, argv); } break; case 's': if (strcmp(optarg, "name") == 0) opt_sort = OPT_SORT_NAME; else if (strcmp(optarg, "id") == 0) opt_sort = OPT_SORT_TID; else if (strcmp(optarg, "time") == 0) opt_sort = OPT_SORT_TIME; else if (strcmp(optarg, "io") == 0) opt_sort = OPT_SORT_IO; else if (strcmp(optarg, "mem") == 0) opt_sort = OPT_SORT_MEM; else { /* unknown */ fprintf(stderr, "Unknown sort method %s\n", optarg); print_help(argc, argv); } break; case 't': target.tv_sec = atoi(optarg); break; case 'm': target.tv_nsec = atol(optarg) * NSECS_PER_MSEC; break; case 'c': cycles = atoi(optarg); break; case 0: break; case '?': case 'h': default: print_help(argc, argv); } } nr_cpus = get_nr_cpus(); bm_alloc(PID_MAX); rc = pthread_create(&proc_events_thread, NULL, proc_events_main, NULL); if (rc) DIE_PERROR("pthread_create failed"); pthread_setname_np(proc_events_thread, "nlmon-pevent"); setup_netlink(); start_task_monitor(); while (!procfs_thread) { DEBUG("...\n"); pthread_yield(); __sync_synchronize(); } rc = pthread_join(procfs_thread, &status); if (rc) DIE_PERROR("pthread_join failed"); else DEBUG("procfs scan thread exited\n"); data_init_cpu(); if (opt_realtime) elevate_prio(); cache_init(); output->init_output(); while (cycles--) measure_one_cycle(); output->exit_output(); stop_task_monitor(); exit(EXIT_SUCCESS); }