Created
March 18, 2013 22:54
-
-
Save Pacifist117/5191661 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
/* | |
* Tests context switching times based on a semaphore in the RTAI kernel. | |
* Author: Rob Lyerly | |
* | |
* This test has been modified to increase scalability in this way: | |
* | |
* - The number of threads is correlated to the number of cores, each core gets two threads | |
* - Each core gets one mutex and a locker and unlocker thread | |
* - This version does not require a barrier | |
* - The "threads" variable does NOT include main | |
* | |
* Author: Kevin Burns | |
*/ | |
#include <pthread.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#include <sched.h> | |
#include <sys/sysinfo.h> | |
#include <sys/time.h> | |
#include <sys/mman.h> | |
#include <librttest.h> | |
#include "barrier.h" | |
#include <librttest.h> | |
#include "blocktime_mutex.h" | |
#define THREAD_PRIORITY 99 | |
/* Integer to affine a task to all CPUs */ | |
#define ALL_CPUS 0x00ffffff | |
#define NUM_CORES 24 | |
/* Memory buffer used to record statistics */ | |
static long** statistics; | |
/* Variables used to synchronize/time/perform the context switch */ | |
static sem mutexes[NUM_CORES]; //Kevin: made single pointer rather than double | |
/* Thread parameters used to setup the thread */ | |
typedef struct _threadparam { | |
int numLoops; | |
int threadnum; | |
int numThreads; | |
} thread_param; | |
#define DEBUG 1 | |
void debug_msg(char * msg) { | |
#if DEBUG==1 | |
printf("%s\n",msg); | |
#endif | |
} | |
static void* unlock_thread(void* param) { | |
int i = 0; | |
thread_param * my_param = (thread_param *)param; | |
printf("top of unlock_thread for %d\n",my_param->threadnum); | |
//for (i=0;i<my_param->numLoops;i++) { | |
for (i=0;i<10;i++) { | |
//while (!librt_sem_trywait(&mutexes[(my_param->threadnum)/2])) { | |
//do nothing | |
//} | |
//get before time here | |
printf("unlocking in thread: %d\n",my_param->threadnum); | |
librt_sem_post(&mutexes[(my_param->threadnum-1)/2]); | |
sleep(1); | |
} | |
return NULL; | |
} | |
static void* lock_thread(void* param) { | |
int i = 0; | |
thread_param * my_param = (thread_param *)param; | |
printf("top of lock_thread for %d\n",my_param->threadnum); | |
//for (i=0;i<my_param->numLoops;i++) { | |
for (i=0;i<10;i++) { | |
//while (librt_sem_trywait(&mutexes[(my_param->threadnum-1)/2])) { | |
//do nothing | |
//} | |
printf("locking lock %d in thread: %d\n",(my_param->threadnum)/2,my_param->threadnum); | |
librt_sem_wait(&mutexes[(my_param->threadnum)/2]); | |
//get time after here | |
} | |
return NULL; | |
} | |
int switchtest(int threads, int loops, int affinity, int policy, char* fn) { | |
thread_param* param; | |
int i = 0, j = 0, ret = 0; | |
int argc; | |
char * argv; | |
//Initialize the RT parameters | |
if (rt_init("", parse_args, argc, &argv)) | |
printf("rt_init failed\n"); | |
else | |
printf("rt_init succeeded\n"); | |
//Allocate the statistics buffer | |
//The stats buffer will include the difference between unlock and lock for each thread pair | |
statistics = (long**)calloc(threads, sizeof(long)); | |
for(i = 0; i < threads; i++) | |
statistics[i] = (long*)calloc(loops, sizeof(long)); | |
//Start the requested number of threads | |
param = (thread_param*)calloc(2*(threads), sizeof(thread_param)); | |
//mutexes = (mutex**)calloc(threads - 1, sizeof(mutex*)); //array of mutexes | |
//before = (RTIME*)calloc(2*threads), sizeof(RTIME)); | |
task t = taskset_init((2*threads)); | |
//Kevin TODO 2) Create mutexes and lock them | |
//fill thread parameters -- merge with 3)? | |
for(i = 0; i < (2*threads); i++) { | |
param[i].numLoops = loops; | |
param[i].threadnum = i; | |
param[i].numThreads = threads; | |
} | |
for(i = 0; i < threads; i++) { | |
librt_sem_init(&mutexes[i]); | |
librt_sem_wait(&mutexes[i]); | |
} | |
debug_msg("2) mutexes are created and locked"); | |
char taskname_lock[7]; | |
char taskname_unlock[7]; | |
int cpus = 0; | |
//Kevin 3) Spawn RT threads | |
for (i = 0; i < (2*threads); i++, t++) { | |
//Set up lockers first | |
sprintf(taskname_lock, "%d",i); | |
t->func = lock_thread; | |
t->arg = (void *)&(param[i]); | |
t->prio = THREAD_PRIORITY; | |
t->name = taskname_lock; | |
t->stack_size = 0; | |
t->max_msg_size = 0; | |
t->policy = SCHED_FIFO; | |
#if KERN_RTAI | |
t->cpus_allowed = 1 << (i/2); | |
#else | |
cpus = 1 << (i/2); | |
CPU_SET(cpus,&t->cpus_allowed); | |
#endif | |
if ((ret = task_create(t)) < 0) { | |
printf("task%d failed", i); | |
exit(ret); | |
} else { | |
debug_msg("creating task"); | |
} | |
//increment counters | |
i++; | |
t++; | |
//Set up unlockers now | |
sprintf(taskname_unlock, "%d",i); //Kevin: taskname is the last iteration of i for every thread, do I even need it? | |
t->func = unlock_thread; | |
t->arg = (void *)&(param[i]); | |
t->prio = THREAD_PRIORITY; | |
t->name = taskname_unlock; | |
t->stack_size = 0; | |
t->max_msg_size = 0; | |
t->policy = SCHED_FIFO; | |
//cpus_allowed stays the same | |
if ((ret = task_create(t)) < 0) { | |
printf("task%d failed", i); | |
exit(ret); | |
} else { | |
debug_msg("creating task"); | |
} | |
} | |
debug_msg("3) threads are spawned"); | |
munlockall(); | |
task_join_all(); | |
debug_msg("threads joined"); | |
//Write statistics to file | |
char filename[40]; | |
char thread_string[5]; | |
sprintf(thread_string, "%d", (threads)); | |
strcpy(filename, "/data/"); | |
strcat(filename, fn); | |
strcat(filename, thread_string); | |
strcat(filename, ".dat"); | |
FILE* fp = fopen(filename, "a"); | |
for(i = 0; i < threads; i++) { | |
for(j = 0; j < loops; j++) { | |
fprintf(fp, "%ld\n", statistics[i][j]); | |
} | |
} | |
fclose(fp); | |
for(i = 0; i < threads; i++) { | |
free(statistics[i]); | |
librt_sem_destroy(&mutexes[i]); | |
} | |
free(statistics); | |
//free(thread); | |
free(param); | |
//free(mutexes); | |
//free(before); | |
//pthread_barrier_destroy(&barrier); | |
debug_msg("switchtest ended"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment