Created
April 8, 2013 06:47
-
-
Save wmealing/5334730 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------------------------------------- | |
* Semaphore timing test. | |
* | |
* gcc -m64 -g -O3 -lm -o sema-test sema-test.c | |
* | |
* Based on schedulertest | |
* Version 1. | |
------------------------------------------------------------------------- */ | |
#include <math.h> | |
#include <sys/types.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <sys/time.h> | |
#include <sys/mman.h> | |
#include <errno.h> | |
#include <sys/stat.h> | |
#include <dirent.h> | |
#include <pthread.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <ctype.h> | |
#include <stdint.h> | |
#include <math.h> | |
/* Stop after KLOOPS * 1000 iterations */ | |
#define KLOOPS 1000 | |
/* YOU WILL NEED TO MODIFY THESE */ | |
#define TEST_MIN_TIME_MAX 100 /* miliseconds - sanity check */ | |
#define TEST_AVG_TIME_MAX 500 /* miliseconds - sanity check */ | |
#define TEST_MAX_TIME_MAX 1000 /* miliseconds - sanity check */ | |
#define TEST_STD_DEV_MAX 11 | |
#define PRIORITY 1 | |
#define handle_error_en(en, msg) \ | |
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) | |
#define handle_error(msg) \ | |
do { perror(msg); exit(EXIT_FAILURE); } while (0) | |
struct thread_info { /* Used as argument to thread_start() */ | |
pthread_t thread_id; /* ID returned by pthread_create() */ | |
pthread_mutex_t *thread_mutex; /* Mutex we're going to all spin around */ | |
int thread_num; /* Application-defined thread # */ | |
int64_t time_elapsed; | |
}; | |
static void * | |
thread_start(void *arg) | |
{ | |
struct thread_info *tinfo = (struct thread_info *) arg; | |
int id = tinfo->thread_num; | |
int loop_iter=0; | |
time_t time_n; | |
struct timeval tm_start,tm_end; | |
unsigned times[KLOOPS * 1000]; | |
long total_time=0; | |
long minimum_time=0xFFFFFF; | |
long maximum_time=0; | |
float mean_time=0; | |
float standard_deviation=0; | |
/* This is the test to run for KLOOPS loops */ | |
for (loop_iter=0;(loop_iter/1000)<KLOOPS;loop_iter++) | |
{ | |
gettimeofday(&tm_start,NULL); | |
pthread_mutex_lock(tinfo->thread_mutex); | |
pthread_mutex_unlock(tinfo->thread_mutex); | |
gettimeofday(&tm_end,NULL); | |
time_n = ((tm_end.tv_sec * 1000000L)+tm_end.tv_usec)-((tm_start.tv_sec*1000000L)+tm_start.tv_usec); | |
/* | |
* Store timings for each iteration to calculate std. dev | |
* and also keep track of minimum and maximum times | |
* incase they're useful later | |
*/ | |
times[loop_iter] = time_n/1000; | |
total_time += times[loop_iter]; | |
if (times[loop_iter] < minimum_time) | |
minimum_time = times[loop_iter]; | |
if (times[loop_iter] > maximum_time) | |
maximum_time = times[loop_iter]; | |
if ((loop_iter % 1000) == 0) | |
fprintf(stderr,"."); | |
} | |
mean_time = total_time / (KLOOPS * 1000); | |
for(loop_iter=0;loop_iter < (KLOOPS * 1000);loop_iter++) | |
standard_deviation += (times[loop_iter] - mean_time) * (times[loop_iter] - mean_time); | |
standard_deviation = sqrtf( standard_deviation / (KLOOPS * 1000) ); | |
printf("\n\n(TID: %d) Min Time (ms): %ld\n", id, minimum_time); | |
printf("(TID: %d) Avg. Time (ms): %0.4f\n", id , mean_time); | |
printf("(TID: %d) Max Time (ms): %ld\n", id, maximum_time); | |
printf("(TID: %d) Std Dev (ms): %0.4f\n",id, standard_deviation); | |
/* report results as exit code */ | |
if ( (minimum_time > TEST_MIN_TIME_MAX) || (mean_time > TEST_AVG_TIME_MAX) || | |
(maximum_time > TEST_MAX_TIME_MAX) ) { | |
printf("Min/Max/Avg times are outside window.\n"); | |
} else if (standard_deviation > TEST_STD_DEV_MAX) { | |
printf("Standard deviation exceeds %d\n", TEST_STD_DEV_MAX); | |
} | |
return (void *) tinfo; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int s, tnum, opt; | |
struct thread_info *tinfo; | |
void *res; | |
int num_threads = 12; | |
int64_t times[num_threads]; | |
pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER; | |
/* Allocate memory for pthread_create() arguments */ | |
tinfo = calloc(num_threads, sizeof(struct thread_info)); | |
if (tinfo == NULL) | |
handle_error("calloc"); | |
for (tnum = 0; tnum < num_threads; tnum++) { | |
tinfo[tnum].thread_num = tnum + 1; | |
tinfo[tnum].thread_mutex = &thread_mutex; | |
/* The pthread_create() call stores the thread ID into | |
corresponding element of tinfo[] */ | |
s = pthread_create(&tinfo[tnum].thread_id, NULL, | |
&thread_start, &tinfo[tnum]); | |
if (s != 0) | |
handle_error_en(s, "pthread_create"); | |
} | |
/* Now join with each thread, and log its returned value */ | |
for (tnum = 0; tnum < num_threads; tnum++) { | |
s = pthread_join(tinfo[tnum].thread_id, &res); | |
if (s != 0) | |
handle_error_en(s, "pthread_join"); | |
struct thread_info *returned_tinfo = (struct thread_info *)res; | |
times[tnum] = returned_tinfo[tnum].time_elapsed; | |
/* | |
printf("Joined with thread %d; returned value was %d\n", tinfo[tnum].thread_num, returned_tinfo->thread_num); | |
printf("Joined with thread %d; time elapsed was %d\n", tinfo[tnum].thread_num, times[tnum]); | |
*/ | |
} | |
free(tinfo); | |
exit(EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment