#include #include #include #include #include #include #include #include #include /* Non standards includes */ #include #include #include static long nb_cache_lines = 0; static long nb_prod = 0; static long size_buf = 1; static char *calculation_lib = NULL; void usage(char *argv[]) { char format[] = "-n [options]"; char options[] = "Required options :\n" "-n nb_cache_lines\tNumber of cache lines to send to another core\n" "-p nb_producers\tNumber of producers which send data to another core\n" "Facultative options :\n" "-h\t\t\tPrint this help\n" "-s\t\t\tShare the same L2 cache or not\n" "-c calculation_lib\tLibrary to use for calculation\n" "\t\t\tThis library must implement functions in calc.h\n"; printf("Usage : %s %s\n", argv[0], format); printf("Options :\n"); printf("%s\n", options); } int analyse_options(int argc, char *argv[]) { int opt; opterr = 0; while ((opt = getopt(argc, argv, ":hsc:n:p:b:")) != -1) { switch (opt) { case 'b' : { char *inval; size_buf = strtol(optarg, &inval, 10); if ((*optarg == '\0') || (*inval != '\0')) { fprintf(stderr, "Option '-b' needs an integer argument\n"); return -1; } if ((nb_cache_lines <= 0) || ((nb_cache_lines == LONG_MAX) && errno == ERANGE)) { fprintf(stderr, "Number of cache lines for each buffer must be between 1 and %ld, both inclusive\n", LONG_MAX); return -1; } } break; case 'c' : calculation_lib = optarg; { struct stat file_stat; if (stat(calculation_lib, &file_stat)) { printf("%s: %s\n", optarg, strerror(errno)); return -1; } } break; case 'h' : usage(argv); exit(EXIT_SUCCESS); case 'n' : { char *inval; nb_cache_lines = strtol(optarg, &inval, 10); if ((*optarg == '\0') || (*inval != '\0')) { fprintf(stderr, "Option '-n' needs an integer argument\n"); return -1; } if ((nb_cache_lines <= 0) || ((nb_cache_lines == LONG_MAX) && errno == ERANGE)) { fprintf(stderr, "Number of cache lines to be sent must be between 1 and %ld, both inclusive\n", LONG_MAX); return -1; } } break; case 'p' : { char *inval; nb_prod = strtol(optarg, &inval, 10); if ((*optarg == '\0') || (*inval != '\0')) { fprintf(stderr, "Option '-p' needs an integer argument\n"); return -1; } if ((nb_cache_lines <= 0) || ((nb_cache_lines == LONG_MAX) && errno == ERANGE)) { fprintf(stderr, "Number of producers must be between 1 and %ld, both inclusive\n", LONG_MAX); return -1; } } break; case 's' : /* TODO: shared L2 cache */ break; case '?' : fprintf(stderr, "Option inconnue\n"); return -1; case ':' : fprintf(stderr, "Option %s needs an argument\n", argv[optind]); return -1; default : fprintf(stderr, "Error while analysing command line options\n"); return -1; } } if (!nb_cache_lines) { fprintf(stderr, "You must give the number of cache lines to be sent\n"); return -1; } if (!nb_prod) { fprintf(stderr, "You must give the number of producers\n"); return -1; } return 0; } void *producer(void *unused) { int i, j, k; printf("Registering: %p !\n", (void*) pthread_self()); add_sender(); k = (uintptr_t) pthread_self(); if (initialize_papi() != -1) { for(i = 0; i < nb_cache_lines; i++) { //printf("[%p] Send a new CACHE_LINE\n", (void *) pthread_self()); for(j = 0; j < (CACHE_LINE_SIZE / sizeof(uintptr_t)); j++) send(k++); } print_results(); } printf("[%p] Producer finished !\n", (void*) pthread_self()); remove_sender(); /* Threads must wait the consumer because of thread-local storages */ return NULL; } void onMessage(uintptr_t val) { //printf("Receive value: %p\n", (void *) val); } void *receptor(void *a) { reception(onMessage); return NULL; } int main(int argc, char *argv[]) { int i; volatile int *cont; void *return_value; pthread_t *tid; if (analyse_options(argc, argv)) return EXIT_FAILURE; tid = (pthread_t *) malloc((nb_prod + 1) * sizeof(pthread_t)); cont = init_comm(); for(i = 0; i < nb_prod; i++) pthread_create(&tid[i], NULL, producer, NULL); pthread_create(&tid[i], NULL, receptor, NULL); for(i = 0; i < nb_prod; i++) pthread_join(tid[i], &return_value); *cont = 0; pthread_join(tid[i], &return_value); free(tid); return EXIT_SUCCESS; }