void *worker_thread(void* arg) { struct sched_param sched_param; int policy; int rc; int mypri; int j; nsec_t start, wake; j = (intptr_t)arg; if (pthread_getschedparam(pthread_self(), &policy, &sched_param) != 0) { printf("ERR: Couldn't get pthread info. Priority value wrong\n"); mypri = -1; } else { mypri = sched_param.sched_priority; } start = rt_gettime() - beginrun; debug(0, "%08lld us: RealtimeThread-%03d pri %03d started\n", start/NS_PER_US, j, mypri); rc = pthread_mutex_lock(&mutex); running_threads++; rc = pthread_cond_wait(&cond, &mutex); wake = rt_gettime() - beginrun; running_threads--; wakeup.arr[wakeup.counter++] = mypri; debug(0, "%08lld us: RealtimeThread-%03d pri %03d awake\n", wake/NS_PER_US, j, mypri); rc = pthread_mutex_unlock(&mutex); return NULL; }
void * high_prio_thread(void *arg) { nsec_t high_start, high_end, high_get_lock; unsigned int i; stats_container_init(&cpu_delay_dat, iterations); stats_container_init(&cpu_delay_hist, HIST_BUCKETS); stats_quantiles_init(&cpu_delay_quantiles, (int)log10(iterations)); printf("High prio thread started\n"); for (i = 0; i < iterations; i++) { /* Wait for all threads to reach barrier wait. When woken up, low prio thread will own the mutex */ pthread_barrier_wait(&bar1); high_start = rt_gettime(); pthread_mutex_lock(&lock); high_end = rt_gettime(); high_get_lock = high_end - low_unlock; busy_work_ms(high_work_time); pthread_mutex_unlock(&lock); rec.x = i; rec.y = high_get_lock / NS_PER_US; stats_container_append(&cpu_delay_dat, rec); /* Wait for all threads to finish this iteration */ pthread_barrier_wait(&bar2); } stats_hist(&cpu_delay_hist, &cpu_delay_dat); stats_container_save("samples", "pi_perf Latency Scatter Plot", "Iteration", "Latency (us)", &cpu_delay_dat, "points"); stats_container_save("hist", "pi_perf Latency Histogram", "Latency (us)", "Samples", &cpu_delay_hist, "steps"); printf("Time taken for high prio thread to get the lock once released by low prio thread\n"); printf("Min delay = %ld us\n", stats_min(&cpu_delay_dat)); printf("Max delay = %ld us\n", stats_max(&cpu_delay_dat)); printf("Average delay = %4.2f us\n", stats_avg(&cpu_delay_dat)); printf("Standard Deviation = %4.2f us\n", stats_stddev(&cpu_delay_dat)); printf("Quantiles:\n"); stats_quantiles_calc(&cpu_delay_dat, &cpu_delay_quantiles); stats_quantiles_print(&cpu_delay_quantiles); max_pi_delay = stats_max(&cpu_delay_dat); return NULL; }
void matrix_mult_record(int m_size, int index) { nsec_t start, end, delta; int i; start = rt_gettime(); for (i = 0; i < ops; i++) matrix_mult(MATRIX_SIZE); end = rt_gettime(); delta = (long)((end - start)/NS_PER_US); curdat->records[index].x = index; curdat->records[index].y = delta; }
void *periodic_thread(void *thread) { struct thread *t = (struct thread *)thread; struct periodic_arg *parg = (struct periodic_arg *)t->arg; nsec_t period = parg->period; void*(*func)(void*) = parg->func; int i = 0; nsec_t next, now; nsec_t exe_start, exe_end, exe_time; next = rt_gettime(); while (i < parg->iterations) { next += period; if (rt_gettime() > next) { printf("TID %d missed period, aborting\n", t->id); fail[t->id] = 1; break; } exe_start = rt_gettime(); func(parg->arg); exe_end = rt_gettime(); exe_time = exe_end - exe_start; rec.x = i; rec.y = exe_time/NS_PER_US; stats_container_append(&dat[t->id], rec); i++; now = rt_gettime(); if (now > next) { printf("Missed period, aborting (calc took too long)\n"); fail[t->id] = 1; break; } rt_nanosleep(next - now); } printf("TID %d (%c - prio %d) complete\n", t->id, groupname[t->id>>2], t->priority); return NULL; }
static unsigned long busy_loop(unsigned long long start_time) { unsigned long long time; unsigned long l = 0; do { l++; time = rt_gettime(); } while ((time - start_time) < RUN_INTERVAL); return l; }
void * low_prio_thread(void *arg) { nsec_t low_start, low_hold; unsigned int i; stats_container_init(&low_dat, iterations); printf("Low prio thread started\n"); for (i = 0; i < iterations; i++) { pthread_mutex_lock(&lock); /* Wait for all threads to reach barrier wait. Since we already own the mutex, high prio thread will boost our priority. */ pthread_barrier_wait(&bar1); low_start = rt_gettime(); busy_work_ms(low_work_time); low_unlock = rt_gettime(); low_hold = low_unlock - low_start; pthread_mutex_unlock(&lock); rec.x = i; rec.y = low_hold / NS_PER_US; stats_container_append(&low_dat, rec); if (i == iterations-1) end = 1; /* Wait for all threads to finish this iteration */ pthread_barrier_wait(&bar2); } return NULL; }
void *start_task(void *data) { struct thread *thr = (struct thread *)data; long id = (long) thr->arg; thread_pids[id] = gettid(); unsigned long long start_time; int ret; int high = 0; cpu_set_t cpumask; cpu_set_t save_cpumask; int cpu = 0; unsigned long l; long pid; ret = sched_getaffinity(0, sizeof(save_cpumask), &save_cpumask); if (ret < 0) debug(DBG_ERR, "sched_getaffinity failed: %s\n", strerror(ret)); pid = gettid(); /* Check if we are the highest prio task */ if (id == nr_tasks-1) high = 1; while (!done) { if (high) { /* rotate around the CPUS */ if (!CPU_ISSET(cpu, &save_cpumask)) cpu = 0; CPU_ZERO(&cpumask); CPU_SET(cpu, &cpumask); cpu++; sched_setaffinity(0, sizeof(cpumask), &cpumask); } pthread_barrier_wait(&start_barrier); start_time = rt_gettime(); ftrace_write("Thread %d: started %lld diff %lld\n", pid, start_time, start_time - now); l = busy_loop(start_time); record_time(id, start_time / NS_PER_US, l); pthread_barrier_wait(&end_barrier); } return (void *)pid; }
void *signal_sending_thread(void *arg) { int target_thread = (intptr_t)((struct thread *)arg)->arg; int i, ret; debug(DBG_INFO, "Signal sending thread: target thread id =%d\n", (int)PTHREADOF(target_thread)); /* Wait for the receiving thread to initialize */ while (!atomic_get(&flag)) {usleep(100);}; atomic_set(0, &flag); /* Warm up */ for (i=0; i<5; i++) { debug(DBG_DEBUG, "Sending signal (Warm up). Loopcnt = %d\n", i); if ((ret = pthread_kill(PTHREADOF(target_thread), SIGNALNUMBER))) { printf("pthread_kill returned %d\n", ret); } /* Wait till the receiving thread processes the signal */ while (!atomic_get(&flag)) {usleep(100);}; atomic_set(0, &flag); } for (i=0; i<ITERATIONS; i++) { debug(DBG_DEBUG, "Sending signal. Loopcnt = %d\n", i); /* Record the time just before sending the signal */ begin = rt_gettime(); if ((ret = pthread_kill(PTHREADOF(target_thread), SIGNALNUMBER))) { printf("pthread_kill returned %d\n", ret); } /* Wait till the receiving thread processes the signal */ while (!atomic_get(&flag)) { usleep(100); } if (atomic_get(&flag) == 2) break; atomic_set(0, &flag); } return NULL; }
static void record_time(int id, unsigned long long time, unsigned long l) { unsigned long long ltime; stats_record_t rec; if (loop >= nr_runs) return; time -= now; ltime = rt_gettime() / NS_PER_US; ltime -= now; rec.x = loop; rec.y = time; stats_container_append(&intervals[id], rec); rec.x = loop; rec.y = ltime; stats_container_append(&intervals_length[id], rec); rec.x = loop; rec.y = l; stats_container_append(&intervals_loops[id], rec); }
void *low_prio_rt_thread(void *arg) { struct thread *t = (struct thread *)arg; while (!thread_quit(t)) { while_not_flag(LOW_START_CYCLE, t) rt_nanosleep(1 * NS_PER_MS); debug(DBG_INFO, "low try mutex\n"); pthread_mutex_lock(&pi_mutex); debug(DBG_INFO, "low grab mutex\n"); write_flag(MED_START_WORK); rt_nanosleep(1 * NS_PER_MS); while_not_flag(LOW_DROP_MUTEX, t) { //printf("!"); fflush(NULL); rt_nanosleep(1); } debug(DBG_INFO, "low drop mutex\n"); low_drop_time = rt_gettime(); pthread_mutex_unlock(&pi_mutex); while_not_flag(END_OF_CYCLE, t) { //printf("@"); fflush(NULL); rt_nanosleep(1 * NS_PER_MS); }
void *master_thread(void* arg) { int rc; nsec_t start; /* make sure children are started */ while (running_threads < rt_threads) usleep(1000); /* give the worker threads a chance to get to sleep in the kernel * in the unlocked broadcast case. */ usleep(1000); start = rt_gettime() - beginrun; printf("%08lld us: Master thread about to wake the workers\n", start/NS_PER_US); /* start the children threads */ if (locked_broadcast) rc = pthread_mutex_lock(&mutex); rc = pthread_cond_broadcast(&cond); if (locked_broadcast) rc = pthread_mutex_unlock(&mutex); return NULL; }
int periodic_thread(nsec_t period, int iterations, int loops) { stats_container_t dat; stats_container_t hist; stats_quantiles_t quantiles; stats_record_t rec; int i = 0; int fail = 0; nsec_t next, now; nsec_t exe_start, exe_end, exe_time; char *samples_filename; char *hist_filename; stats_container_init(&dat, iterations); stats_container_init(&hist, HIST_BUCKETS); stats_quantiles_init(&quantiles, (int)log10(iterations)); if (asprintf(&samples_filename, "%s-samples", filename_prefix) == -1) { fprintf(stderr, "Failed to allocate string for samples filename\n"); return -1; } if (asprintf(&hist_filename, "%s-hist", filename_prefix) == -1) { fprintf(stderr, "Failed to allocate string for samples filename\n"); return -1; } next = rt_gettime(); while (i < iterations) { next += period; now = rt_gettime(); if (now > next) { printf("Missed period, aborting (didn't get scheduled in time)\n"); fail = 1; break; } exe_start = rt_gettime(); calc(loops); exe_end = rt_gettime(); exe_time = exe_end - exe_start; rec.x = i; rec.y = exe_time/NS_PER_US; stats_container_append(&dat, rec); i++; now = rt_gettime(); if (now > next) { printf("Missed period, aborting (calc took too long)\n"); fail = 1; break; } rt_nanosleep(next - now); } stats_container_save(samples_filename, "Periodic CPU Load Scatter Plot",\ "Iteration", "Runtime (us)", &dat, "points"); stats_container_save(hist_filename, "Periodic CPU Load Histogram",\ "Runtime (us)", "Samples", &hist, "steps"); printf(" Execution Time Statistics:\n"); printf("Min: %ld us\n", stats_min(&dat)); printf("Max: %ld us\n", stats_max(&dat)); printf("Avg: %.4f us\n", stats_avg(&dat)); printf("StdDev: %.4f us\n", stats_stddev(&dat)); printf("Quantiles:\n"); stats_quantiles_calc(&dat, &quantiles); stats_quantiles_print(&quantiles); printf("Criteria: no missed periods\n"); printf("Result: %s\n", fail ? "FAIL":"PASS"); free(samples_filename); free(hist_filename); return fail; }
int main(int argc, char *argv[]) { int per_id; setup(); pass_criteria = PASS_US; rt_init("d:l:ht:i:", parse_args, argc, argv); printf("-------------------------------\n"); printf("Scheduling Latency\n"); printf("-------------------------------\n\n"); if (load_ms*NS_PER_MS >= period-OVERHEAD) { printf("ERROR: load must be < period - %d us\n", OVERHEAD/NS_PER_US); exit(1); } if (iterations == 0) iterations = DEFAULT_ITERATIONS; if (iterations < MIN_ITERATIONS) { printf("Too few iterations (%d), use min iteration instead (%d)\n", iterations, MIN_ITERATIONS); iterations = MIN_ITERATIONS; } printf("Running %d iterations with a period of %llu ms\n", iterations, period/NS_PER_MS); printf("Periodic load duration: %d ms\n", load_ms); printf("Expected running time: %d s\n", (int)(iterations*((float)period / NS_PER_SEC))); if (stats_container_init(&dat, iterations)) exit(1); if (stats_container_init(&hist, HIST_BUCKETS)) { stats_container_free(&dat); exit(1); } /* use the highest value for the quantiles */ if (stats_quantiles_init(&quantiles, (int)log10(iterations))) { stats_container_free(&hist); stats_container_free(&dat); exit(1); } /* wait one quarter second to execute */ start = rt_gettime() + 250 * NS_PER_MS; per_id = create_fifo_thread(periodic_thread, (void*)0, PRIO); join_thread(per_id); join_threads(); printf("\nCriteria: latencies < %d us\n", (int)pass_criteria); printf("Result: %s\n", ret ? "FAIL" : "PASS"); stats_container_free(&dat); stats_container_free(&hist); stats_quantiles_free(&quantiles); return ret; }
void *periodic_thread(void *arg) { int i; nsec_t delay, avg_delay = 0, start_delay, min_delay = -1ULL, max_delay = 0; int failures = 0; nsec_t next = 0, now = 0, sched_delta = 0, delta = 0, prev = 0, iter_start; /* wait for the specified start time */ rt_nanosleep_until(start); now = rt_gettime(); start_delay = (now - start)/NS_PER_US; iter_start = next = now; debug(DBG_INFO, "ITERATION DELAY(US) MAX_DELAY(US) FAILURES\n"); debug(DBG_INFO, "--------- --------- ------------- --------\n"); if (latency_threshold) { latency_trace_enable(); latency_trace_start(); } for (i = 0; i < iterations; i++) { /* wait for the period to start */ next += period; prev = now; now = rt_gettime(); if (next < now) { printf("\nPERIOD MISSED!\n"); printf(" scheduled delta: %8llu us\n", sched_delta/1000); printf(" actual delta: %8llu us\n", delta/1000); printf(" latency: %8llu us\n", (delta-sched_delta)/1000); printf("---------------------------------------\n"); printf(" previous start: %8llu us\n", (prev-iter_start)/1000); printf(" now: %8llu us\n", (now-iter_start)/1000); printf(" scheduled start: %8llu us\n", (next-iter_start)/1000); printf("next scheduled start is in the past!\n"); ret = 1; break; } sched_delta = next - now; /* how long we should sleep */ delta = 0; do { nsec_t new_now; rt_nanosleep(next - now); new_now = rt_gettime(); delta += new_now - now; /* how long we did sleep */ now = new_now; } while (now < next); /* start of period */ delay = (now - iter_start - (nsec_t)(i+1)*period)/NS_PER_US; rec.x = i; rec.y = delay; stats_container_append(&dat, rec); if (delay < min_delay) min_delay = delay; if (delay > max_delay) max_delay = delay; if (delay > pass_criteria) { failures++; ret = 1; } avg_delay += delay; if (latency_threshold && delay > latency_threshold) break; /* continuous status ticker */ debug(DBG_INFO, "%9i %9llu %13llu %8i\r", i, delay, max_delay, failures); fflush(stdout); busy_work_ms(load_ms); } if (latency_threshold) { latency_trace_stop(); if (i != iterations) { printf("Latency threshold (%lluus) exceeded at iteration %d\n", latency_threshold, i); latency_trace_print(); stats_container_resize(&dat, i+1); } } /* save samples before the quantile calculation messes things up! */ stats_hist(&hist, &dat); stats_container_save("samples", "Periodic Scheduling Latency Scatter Plot",\ "Iteration", "Latency (us)", &dat, "points"); stats_container_save("hist", "Periodic Scheduling Latency Histogram",\ "Latency (us)", "Samples", &hist, "steps"); avg_delay /= i; printf("\n\n"); printf("Start: %4llu us: %s\n", start_delay, start_delay < pass_criteria ? "PASS" : "FAIL"); printf("Min: %4llu us: %s\n", min_delay, min_delay < pass_criteria ? "PASS" : "FAIL"); printf("Max: %4llu us: %s\n", max_delay, max_delay < pass_criteria ? "PASS" : "FAIL"); printf("Avg: %4llu us: %s\n", avg_delay, avg_delay < pass_criteria ? "PASS" : "FAIL"); printf("StdDev: %.4f us\n", stats_stddev(&dat)); printf("Quantiles:\n"); stats_quantiles_calc(&dat, &quantiles); stats_quantiles_print(&quantiles); printf("Failed Iterations: %d\n", failures); return NULL; }
int main(int argc, char* argv[]) { int threads_per_prio; int numcpus; int numprios; int prio; int i; setup(); rt_init("hn:l:", parse_args, argc, argv); if (rt_threads == 0) { numcpus = sysconf(_SC_NPROCESSORS_ONLN); rt_threads = numcpus; } wakeup.arr = (int *)malloc(rt_threads * sizeof(int)); wakeup.counter = 0; printf("\n-----------------------\n"); printf("Priority Ordered Wakeup\n"); printf("-----------------------\n"); printf("Worker Threads: %d\n", rt_threads); printf("Calling pthread_cond_broadcast() with mutex: %s\n\n", locked_broadcast ? "LOCKED" : "UNLOCKED"); beginrun = rt_gettime(); init_pi_mutex(&mutex); /* calculate the number of threads per priority */ /* we get num numprios -1 for the workers, leaving one for the master */ numprios = sched_get_priority_max(SCHED_FIFO) - sched_get_priority_min(SCHED_FIFO); threads_per_prio = rt_threads / numprios; if (rt_threads % numprios) threads_per_prio++; /* start the worker threads */ prio = sched_get_priority_min(SCHED_FIFO); for (i = rt_threads; i > 0; i--) { if ((i != rt_threads && (i % threads_per_prio) == 0)) prio++; create_fifo_thread(worker_thread, (void*)(intptr_t)i, prio); } /* start the master thread */ create_fifo_thread(master_thread, (void*)(intptr_t)i, ++prio); /* wait for threads to complete */ join_threads(); pthread_mutex_destroy(&mutex); printf("\nCriteria: Threads should be woken up in priority order\n"); for (i = 0; i < (wakeup.counter-1); i++) { if (wakeup.arr[i] < wakeup.arr[i+1]) { printf("FAIL: Thread %d woken before %d\n", wakeup.arr[i], wakeup.arr[i+1]); ret++; } } printf("Result: %s\n", ret ? "FAIL" : "PASS"); return ret; }
int main(int argc, char **argv) { pthread_t *threads; long i; int ret; struct timespec intv; struct sched_param param; rt_init("a:r:t:e:l:h:", parse_args, argc, argv); signal(SIGINT, stop_log); if (argc >= (optind + 1)) nr_tasks = atoi(argv[optind]); else { numcpus = sysconf(_SC_NPROCESSORS_ONLN); nr_tasks = numcpus + 1; } intervals = malloc(sizeof(stats_container_t) * nr_tasks); if (!intervals) debug(DBG_ERR, "malloc failed\n"); memset(intervals, 0, sizeof(stats_container_t) * nr_tasks); intervals_length = malloc(sizeof(stats_container_t) * nr_tasks); if (!intervals_length) debug(DBG_ERR, "malloc failed\n"); memset(intervals_length, 0, sizeof(stats_container_t) * nr_tasks); if (!intervals_loops) debug(DBG_ERR, "malloc failed\n"); intervals_loops = malloc(sizeof(stats_container_t) * nr_tasks); memset(intervals_loops, 0, sizeof(stats_container_t) * nr_tasks); threads = malloc(sizeof(*threads) * nr_tasks); if (!threads) debug(DBG_ERR, "malloc failed\n"); memset(threads, 0, sizeof(*threads) * nr_tasks); ret = pthread_barrier_init(&start_barrier, NULL, nr_tasks + 1); ret = pthread_barrier_init(&end_barrier, NULL, nr_tasks + 1); if (ret < 0) debug(DBG_ERR, "pthread_barrier_init failed: %s\n", strerror(ret)); for (i = 0; i < nr_tasks; i++) { stats_container_init(&intervals[i], nr_runs); stats_container_init(&intervals_length[i], nr_runs); stats_container_init(&intervals_loops[i], nr_runs); } thread_pids = malloc(sizeof(long) * nr_tasks); if (!thread_pids) debug(DBG_ERR, "malloc thread_pids failed\n"); for (i = 0; i < nr_tasks; i++) { threads[i] = create_fifo_thread(start_task, (void *)i, prio_start + i); } /* * Progress bar uses stderr to let users see it when * redirecting output. So we convert stderr to use line * buffering so the progress bar doesn't flicker. */ setlinebuf(stderr); /* up our prio above all tasks */ memset(¶m, 0, sizeof(param)); param.sched_priority = nr_tasks + prio_start; if (sched_setscheduler(0, SCHED_FIFO, ¶m)) debug(DBG_WARN, "Warning, can't set priority of" "main thread !\n"); intv.tv_sec = INTERVAL / NS_PER_SEC; intv.tv_nsec = INTERVAL % (1 * NS_PER_SEC); print_progress_bar(0); setup_ftrace_marker(); for (loop = 0; loop < nr_runs; loop++) { unsigned long long end; now = rt_gettime() / NS_PER_US; ftrace_write("Loop %d now=%lld\n", loop, now); pthread_barrier_wait(&start_barrier); ftrace_write("All running!!!\n"); rt_nanosleep(intv.tv_nsec); print_progress_bar((loop * 100) / nr_runs); end = rt_gettime() / NS_PER_US; ftrace_write("Loop %d end now=%lld diff=%lld\n", loop, end, end - now); ret = pthread_barrier_wait(&end_barrier); if (stop || (check && check_times(loop))) { loop++; nr_runs = loop; break; } } putc('\n', stderr); pthread_barrier_wait(&start_barrier); done = 1; pthread_barrier_wait(&end_barrier); join_threads(); print_results(); if (stop) { /* * We use this test in bash while loops * So if we hit Ctrl-C then let the while * loop know to break. */ if (check < 0) exit(-1); else exit(1); } if (check < 0) exit(-1); else exit(0); return 0; }
void *worker_thread(void *arg) { struct sched_param sched_param; int policy, rc, mypri = 0, tid, times = 0; tid = (intptr_t) (((struct thread *)arg)->arg); nsec_t pstart, pend; if (pthread_getschedparam(pthread_self(), &policy, &sched_param) != 0) { printf("ERR: Couldn't get pthread info \n"); } else { mypri = sched_param.sched_priority; } /* check in */ pthread_mutex_lock(&bmutex); threads_running++; pthread_mutex_unlock(&bmutex); /* block */ rc = pthread_mutex_lock(&mutex[tid]); if (tid == 0) pthread_barrier_wait(&barrier); rc = pthread_cond_wait(&cond[tid], &mutex[tid]); rc = pthread_mutex_unlock(&mutex[tid]); debug(DBG_INFO, "%llu: Thread %d(%d) wakes up from sleep \n", rt_gettime(), tid, mypri); /*check if we're the last thread */ if (tid == NUM_WORKERS - 1) { t_after_wait[tid] = 1; pthread_mutex_lock(&bmutex); threads_running--; pthread_mutex_unlock(&bmutex); return NULL; } /* Signal next thread */ rc = pthread_mutex_lock(&mutex[tid + 1]); rc = pthread_cond_signal(&cond[tid + 1]); debug(DBG_INFO, "%llu: Thread %d(%d): Sent signal (%d) to (%d)\n", rt_gettime(), tid, mypri, rc, tid + 1); pstart = pend = rt_gettime(); rc = pthread_mutex_unlock(&mutex[tid + 1]); debug(DBG_INFO, "%llu: Thread %d(%d) setting it's bit \n", rt_gettime(), tid, mypri); t_after_wait[tid] = 1; while (t_after_wait[tid + 1] != 1) { pend = rt_gettime(); times++; } if (times >= (int)pass_criteria) { printf ("Thread %d(%d): Non-Preempt limit reached. %llu ns latency\n", tid, mypri, pend - pstart); ret = 1; } /* check out */ pthread_mutex_lock(&bmutex); threads_running--; pthread_mutex_unlock(&bmutex); return NULL; }
void main_thread(void) { int ret, i, j; nsec_t start, end; long smin = 0, smax = 0, cmin = 0, cmax = 0, delta = 0; float savg, cavg; int cpuid; if ( stats_container_init(&sdat, iterations) || stats_container_init(&shist, HIST_BUCKETS) || stats_container_init(&cdat, iterations) || stats_container_init(&chist, HIST_BUCKETS) ) { fprintf (stderr, "Cannot init stats container\n"); exit(1); } tids = malloc(sizeof(int) * numcpus); if (!tids) { perror("malloc"); exit(1); } memset(tids, 0, numcpus); cpuid = set_affinity(); if (cpuid == -1) { fprintf(stderr, "Main thread: Can't set affinity.\n"); exit(1); } /* run matrix mult operation sequentially */ curdat = &sdat; curdat->index = iterations-1; printf("\nRunning sequential operations\n"); start = rt_gettime(); for (i = 0; i < iterations; i++) matrix_mult_record(MATRIX_SIZE, i); end = rt_gettime(); delta = (long)((end - start)/NS_PER_US); savg = delta/iterations; /* don't use the stats record, use the total time recorded */ smin = stats_min(&sdat); smax = stats_max(&sdat); printf("Min: %ld us\n", smin); printf("Max: %ld us\n", smax); printf("Avg: %.4f us\n", savg); printf("StdDev: %.4f us\n", stats_stddev(&sdat)); if ( stats_hist(&shist, &sdat) || stats_container_save("sequential", "Matrix Multiplication Sequential Execution Runtime Scatter Plot", "Iteration", "Runtime (us)", &sdat, "points") || stats_container_save("sequential_hist", "Matrix Multiplicatoin Sequential Execution Runtime Histogram", "Runtime (us)", "Samples", &shist, "steps") ) { fprintf(stderr, "Warning: could not save sequential mults stats\n"); } pthread_barrier_init(&mult_start, NULL, numcpus+1); set_priority(PRIO); curdat = &cdat; curdat->index = iterations-1; online_cpu_id = -1; /* Redispatch cpus */ /* Create numcpus-1 concurrent threads */ for (j = 0; j < numcpus; j++) { tids[j] = create_fifo_thread(concurrent_thread, NULL, PRIO); if (tids[j] == -1) { printf("Thread creation failed (max threads exceeded?)\n"); exit(1); } } /* run matrix mult operation concurrently */ printf("\nRunning concurrent operations\n"); pthread_barrier_wait(&mult_start); start = rt_gettime(); join_threads(); end = rt_gettime(); delta = (long)((end - start)/NS_PER_US); cavg = delta/iterations; /* don't use the stats record, use the total time recorded */ cmin = stats_min(&cdat); cmax = stats_max(&cdat); printf("Min: %ld us\n", cmin); printf("Max: %ld us\n", cmax); printf("Avg: %.4f us\n", cavg); printf("StdDev: %.4f us\n", stats_stddev(&cdat)); if ( stats_hist(&chist, &cdat) || stats_container_save("concurrent", "Matrix Multiplication Concurrent Execution Runtime Scatter Plot", "Iteration", "Runtime (us)", &cdat, "points") || stats_container_save("concurrent_hist", "Matrix Multiplication Concurrent Execution Runtime Histogram", "Iteration", "Runtime (us)", &chist, "steps") ) { fprintf(stderr, "Warning: could not save concurrent mults stats\n"); } printf("\nConcurrent Multipliers:\n"); printf("Min: %.4f\n", (float)smin/cmin); printf("Max: %.4f\n", (float)smax/cmax); printf("Avg: %.4f\n", (float)savg/cavg); ret = 1; if (savg > (cavg * criteria)) ret = 0; printf("\nCriteria: %.2f * average concurrent time < average sequential time\n", criteria); printf("Result: %s\n", ret ? "FAIL" : "PASS"); return; }
void *signal_receiving_thread(void *arg) { int i, ret, sig; long delta; long max, min; sigset_t set, oset; stats_container_t dat; stats_container_t hist; stats_quantiles_t quantiles; stats_record_t rec; stats_container_init(&dat, ITERATIONS); stats_container_init(&hist, HIST_BUCKETS); stats_quantiles_init(&quantiles, (int)log10(ITERATIONS)); debug(DBG_DEBUG, "Signal receiving thread running\n"); if ((sigaddset(&set, SIGNALNUMBER))) { perror("sigaddset:"); exit(1); } if ((ret = pthread_sigmask(SIG_BLOCK, &set, &oset))) { printf("pthread_sigmask returned %d\n", ret); exit(1); } /* Let the sending thread know that receiver is ready */ atomic_set(1, &flag); debug(DBG_DEBUG, "Signal receiving thread ready to receive\n"); if (latency_threshold) { latency_trace_enable(); latency_trace_start(); } /* Warm up */ for (i = 0; i < 5; i++) { sigwait(&set, &sig); atomic_set(1, &flag); } max = min = 0; fail = 0; debug(DBG_INFO, "\n\n"); for (i = 0; i < ITERATIONS; i++) { sigwait(&set, &sig); end = rt_gettime(); delta = (end - begin)/NS_PER_US; rec.x = i; rec.y = delta; stats_container_append(&dat, rec); if (i == 0 || delta < min) min = delta; if (delta > max) max = delta; if (delta > pass_criteria) fail++; debug(DBG_INFO, "Iteration %d: Took %ld us. Max = %ld us, " "Min = %ld us\n", i, delta, max, min); fflush(stdout); buffer_print(); if (latency_threshold && (delta > latency_threshold)) { atomic_set(2, &flag); break; } atomic_set(1, &flag); } if (latency_threshold) { latency_trace_stop(); if (i != ITERATIONS) { printf("Latency threshold (%luus) exceeded at iteration %d\n", latency_threshold, i); fflush(stdout); buffer_print(); latency_trace_print(); stats_container_resize(&dat, i + 1); } } stats_hist(&hist, &dat); stats_container_save("samples", "pthread_kill Latency Scatter Plot", "Iteration", "Latency (us)", &dat, "points"); stats_container_save("hist", "pthread_kill Latency Histogram", "Latency (us)", "Samples", &hist, "steps"); printf("\n"); printf("Min: %lu us\n", stats_min(&dat)); printf("Max: %lu us\n", stats_max(&dat)); printf("Avg: %.4f us\n", stats_avg(&dat)); printf("StdDev: %.4f us\n", stats_stddev(&dat)); printf("Quantiles:\n"); stats_quantiles_calc(&dat, &quantiles); stats_quantiles_print(&quantiles); printf("Failures: %d\n", fail); printf("Criteria: Time < %d us\n", (int)pass_criteria); printf("Result: %s", fail ? "FAIL" : "PASS"); printf("\n\n"); return NULL; }