/* * main.c * * Created on: Feb 24, 2009 * Author: Thanh */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include /* gettimeofday() */ //time diff struct typedef struct { int secs; int usecs; } TIME_DIFF; typedef struct rusage RUsage; typedef struct fiboargs { int n; TIME_DIFF * difference; } FiboArgs; typedef struct threads{ pthread_t thread; FiboArgs *args; int index; } MyThreads; typedef struct arguments { int cpu; void *(*function)(void*); void *arg; int policy; int priority; } Arguments; MyThreads* ThreadsList[20] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; TIME_DIFF * my_difftime (struct timeval * start, struct timeval * end) { TIME_DIFF * diff = (TIME_DIFF *) malloc ( sizeof (TIME_DIFF) ); if (start->tv_sec == end->tv_sec) { diff->secs = 0; diff->usecs = end->tv_usec - start->tv_usec; } else { diff->usecs = 1000000 - start->tv_usec; diff->secs = end->tv_sec - (start->tv_sec + 1); diff->usecs += end->tv_usec; if (diff->usecs >= 1000000) { diff->usecs -= 1000000; diff->secs += 1; } } return diff; } void fibonacci(FiboArgs *arg) { int i =0; unsigned long result = 1; unsigned long n1 = 1 ,n2 = 1; RUsage usage_start, usage_end; getrusage (1, &usage_start); for (i = 2; i < arg->n; i++) { result = n1 + n2; n1 = n2; n2 = result; } getrusage (1, &usage_end); struct timeval stopTime; stopTime = usage_end.ru_utime; struct timeval startTime; startTime = usage_start.ru_utime; TIME_DIFF * difference; difference = my_difftime (&startTime, &stopTime); arg->difference = difference; pthread_exit (NULL); } void printHelp() { printf("Usage: multithread \n"); printf(" In which mode the process has to run\n"); printf(" 'fifo'\n"); printf(" 'rr'.\n"); printf(" 'others'.\n"); printf(" = 0 .. 99 - the priority for the process\n"); printf(" = 1 .. 20 - Amounts of threads to run\n"); } int getPolicy(char *text) { if (strcmp(text,"fifo") == 0) { return SCHED_FIFO; } else if (strcmp(text,"rr") == 0) { return SCHED_RR; } else if (strcmp(text,"batch") == 0) { return SCHED_BATCH; } else { return SCHED_OTHER; } } //this is the wrapper thread which will set its affinity to the given core. void wrapperThread(Arguments *arg) { pthread_t thisThread; cpu_set_t cpuset; thisThread = pthread_self(); CPU_ZERO(&cpuset); CPU_SET(arg->cpu,&cpuset); pthread_setaffinity_np(thisThread,sizeof(cpu_set_t),&cpuset); arg->function(arg->arg); free(arg); } pthread_t runThread(int core, int policy, int priority, void *(*function)(void*), void *arg) { int rc; pthread_attr_t attr; pthread_t thread; if (core == -1) { pthread_create(&thread, NULL, function, arg); } else { Arguments *args = malloc(sizeof(Arguments)); args->cpu = core; args->function = function; args->arg = arg; args->policy = policy; args->priority = priority; pthread_attr_init(&attr); pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); rc = pthread_create(&thread, &attr, (void*)wrapperThread, (void*)args); if (rc){ printf("ERROR; return code from pthread_create() is %d\n", rc); } } return thread; } /* * The program has to be executed with super user privilege. * 3 arguments are required * policy : can be "fifo" "rr" "other" "batch" * priority : has to be 0 when policy is other and between 1 and 99 when fifo or other * amount of thread : between 1 and 20 */ int main( int argc, char** argv ) { int times; int policy,prior,threadsNr; MyThreads *t1; TIME_DIFF * difference; struct sched_param param; if (argc == 1) { printHelp(); } else if (argc == 4) { policy = getPolicy(argv[1]); prior = atoi(argv[2]); threadsNr = atoi(argv[3]); if (prior < 0 || prior > 99) { printf("Priority is wrong\n"); exit(1); } if (threadsNr < 1 || threadsNr > 20) { printf("The amount of threads can only be from 1 to 20\n"); exit(1); } param.__sched_priority = prior; if (sched_setscheduler(0,policy,¶m) != 0) { printf("Could not set scheduler priority!\nGiven priority is not correct\n"); exit(1); } struct timeval myTVstart, myTVend; gettimeofday (&myTVstart, NULL); for (times = 0; times < threadsNr; times++) { //create our argument for our thread. t1 = malloc(sizeof(MyThreads)); t1->args = malloc(sizeof(FiboArgs)); t1->args->n = 1000000000; //To make sure it takes a considerable time to calculate it. t1->args->difference = NULL; t1->index = times; t1->thread = runThread(-1,policy,prior,(void*)fibonacci,t1->args); ThreadsList[times] = t1; } for (times = 0; times < threadsNr; times++) { pthread_join ( ThreadsList[times]->thread, NULL ); } gettimeofday (&myTVend, NULL); for (times = 0; times < threadsNr; times++) { printf(" Thread [%d] CPU usage time %3d.%06d secs\n",ThreadsList[times]->index,ThreadsList[times]->args->difference->secs,ThreadsList[times]->args->difference->usecs); free(ThreadsList[times]->args->difference); free(ThreadsList[times]->args); free(ThreadsList[times]); } difference = my_difftime (&myTVstart, &myTVend); printf ("Wall time: %3d.%06d secs.\n", difference->secs, difference->usecs); free(difference); } else { printf("3 arguments are required!\n"); } return 0; }