rt_benchs/communication_techniques/src/main.c

189 lines
4.5 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
#include <string.h>
/* Non standards includes */
#include <papihighlevel.h>
#include <common_comm.h>
#include <specific_comm.h>
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;
}