diff --git a/communication_techniques/.gitignore b/communication_techniques/.gitignore index 8e16f6e..798d385 100644 --- a/communication_techniques/.gitignore +++ b/communication_techniques/.gitignore @@ -1 +1,2 @@ include/specific_comm.h +logs/* diff --git a/communication_techniques/Makefile b/communication_techniques/Makefile index 65c4781..d14a4b1 100644 --- a/communication_techniques/Makefile +++ b/communication_techniques/Makefile @@ -1,60 +1,83 @@ # Directories -OBJDIR=obj -BINDIR=bin -SRCDIR=src -INCDIR=include -LIBDIR=lib -LOCALDIR=$(HOME)/local -PAPIHIGHLEVELLIBDIR=lib -PAPIHIGHLEVELINCDIR=include +OBJDIR:=obj +BINDIR:=bin +SRCDIR:=src +INCDIR:=include +LIBDIR:=lib +LOGDIR:=logs +LOCALDIR:=$(HOME)/local + +# PHL stands for PAPI High Level +PHL_LIB_INSTALLDIR:=lib +PHL_INC_INSTALLDIR:=lib +PHL_LIBDIR:=lib +PHL_INCDIR:=include +PHLDIR:=../papihighlevel +PAPI_LIB_INSTALLDIR:=lib +PAPIDIR:=$(PHLDIR)/papi +PAPI_LIBDIR:=src +PAPI_PFMDIR:=$(PAPI_LIBDIR)/libpfm-3.y/lib +CALCDIR:=calculation +COMMDIR:=communication # Compilation flags # I know -finline-functions and -finline-functions-called-once are enabled by # -O3 but I did this in case gcc behaviour change one day -CFLAGS=-g -O3 -finline-functions -finline-functions-called-once -Wall -Werror -LDFLAGS=-L$(LIBDIR) -L$(LOCALDIR)/$(PAPIHIGHLEVELLIBDIR) -Wl,-rpath-link,$(HOME)/local/lib -lpthread -lpapihighlevel +CFLAGS:=-c -O3 -finline-functions -finline-functions-called-once -Wall -Werror +LDFLAGS:=-L$(LIBDIR) -L$(LOCALDIR)/$(PHL_LIB_INSTALLDIR) -L$(PHLDIR)/$(PHL_LIBDIR) +LDFLAGS:=$(LDFLAGS) -Wl,-rpath-link,$(LOCALDIR)/$(PAPI_LIB_INSTALLDIR):$(PAPIDIR)/$(PAPI_LIBDIR):$(PAPIDIR)/$(PAPI_PFMDIR) +LDFLAGS:=$(LDFLAGS) -lpthread -lpapihighlevel -ldl # Executables CC=gcc # Files -BINNAMES=asm_cache_comm c_cache_comm pipe_comm shared_mem_comm shared_mem_opt_comm jikes_barrier_comm fake_comm -BINS=$(patsubst %, $(BINDIR)/%, $(BINNAMES)) -MAIN_OBJS=main.o common.o -COMMON_LIB_OBJS=common.o +BINNAMES:=asm_cache_comm c_cache_comm pipe_comm shared_mem_comm shared_mem_opt_comm jikes_barrier_comm fake_comm +CALCLIBSNAMES:=calc_mat calc_useless_loop +BINS:=$(patsubst %,$(BINDIR)/%,$(BINNAMES)) +CALCLIBS:=$(patsubst %,$(LIBDIR)/$(CALCDIR)/lib%.so.1,$(CALCLIBSNAMES)) +MAIN_OBJS:=main.o +COMMON_LIB_OBJS:=common.o -.PHONY: all tidy clean distclean symlink +.PHONY: all tidy clean distclean .SECONDARY: .SUFFIXES: .c .o -default: $(BINS) - -ifneq (,$(findstring $(MAKECMDGOALS),$(BINS))) -BASE_TARGET=$(patsubst $(BINDIR)/%_comm,%,$(MAKECMDGOALS)) +default: $(BINS) $(CALCLIBS) # Compilation of binary -$(BINDIR)/$(BASE_TARGET)_comm: $(patsubst %,$(OBJDIR)/$(BASE_TARGET)_%,$(MAIN_OBJS)) $(LIBDIR)/lib$(BASE_TARGET).a +$(BINDIR)/%_comm: $(patsubst %,$(OBJDIR)/\%/%,$(MAIN_OBJS)) $(LIBDIR)/$(COMMDIR)/lib%.a if [ ! -d $(BINDIR) ] ; then mkdir $(BINDIR) ; fi $(CC) -o $@ $^ $(LDFLAGS) -# Compilation of library -$(LIBDIR)/lib$(BASE_TARGET).a: $(OBJDIR)/$(BASE_TARGET).o $(patsubst %,$(OBJDIR)/$(BASE_TARGET)_%,$(COMMON_LIB_OBJS)) +# Creation of comm library +$(LIBDIR)/$(COMMDIR)/lib%.a: $(OBJDIR)/$(COMMDIR)/%.o $(patsubst %,$(OBJDIR)/$(COMMDIR)/\%/%,$(COMMON_LIB_OBJS)) if [ ! -d $(LIBDIR) ] ; then mkdir $(LIBDIR) ; fi + if [ ! -d $(LIBDIR)/$(COMMDIR) ] ; then mkdir $(LIBDIR)/$(COMMDIR) ; fi $(AR) -rcus $@ $^ -# Compile common source files -$(OBJDIR)/$(BASE_TARGET)_%.o: $(SRCDIR)/%.c symlink - if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ; fi - $(CC) $(CFLAGS) -I$(INCDIR) -I$(LOCALDIR)/$(PAPIHIGHLEVELINCDIR) -c $< -o $@ -endif +# Creation of calc library +$(LIBDIR)/$(CALCDIR)/libcalc_%.so.1: $(OBJDIR)/$(CALCDIR)/calc_%.o + if [ ! -d $(LIBDIR) ] ; then mkdir $(LIBDIR) ; fi + if [ ! -d $(LIBDIR)/$(CALCDIR) ] ; then mkdir $(LIBDIR)/$(CALCDIR) ; fi + $(CC) -shared -Wl,-soname,libcalc_$*.so.1 -o $@ $< + cd $(@D) ; ln -sf libcalc_$*.so.1 libcalc_$*.so -# Compile non common source files -$(OBJDIR)/%.o: $(SRCDIR)/%.c symlink +# Compile lib specific source files +$(OBJDIR)/$(COMMDIR)/%.o: $(SRCDIR)/$(COMMDIR)/%.c $(INCDIR)/%_comm.h $(INCDIR)/commtech.h if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ; fi - $(CC) $(CFLAGS) -I$(INCDIR) -c $< -o $@ + if [ ! -d $(OBJDIR)/$(COMMDIR) ] ; then mkdir $(OBJDIR)/$(COMMDIR) ; fi + cd $(INCDIR) ; ln -sfT $*_comm.h specific_comm.h + $(CC) $(CFLAGS) -I$(INCDIR) $< -o $@ -symlink: - ln -sfT $(BASE_TARGET)_comm.h $(INCDIR)/specific_comm.h +# Rule for compiling common source files using libcomm is at the end of +# this file, after the .SECONDEXPANSION target + +# Compile source files not using libcomm +$(OBJDIR)/$(CALCDIR)/%.o: $(SRCDIR)/$(CALCDIR)/%.c + if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ; fi + if [ ! -d $(OBJDIR)/$(CALCDIR) ] ; then mkdir $(OBJDIR)/$(CALCDIR) ; fi + $(CC) $(CFLAGS) -I$(INCDIR) $< -o $@ #.%.d: %.c # gcc $(CFLAGS) -MM $^ | sed -e 's/\([^:]*\):\(.*\)/\1 $@: \2 Makefile/' > $@ @@ -66,6 +89,9 @@ clean: rm -f $(INCDIR)/specific_comm.h rm -rf $(OBJDIR) +logclean: + rm -rf $(LOGDIR) + distclean: clean rm -rf $(BINDIR) $(LIBDIR) @@ -78,3 +104,19 @@ distclean: clean #endif #endif #endif + +.SECONDEXPANSION: + +# Compile common source files using libcomm +$(OBJDIR)/$(COMMDIR)/%.o: $(SRCDIR)/$(COMMDIR)/$$(*F).c $(INCDIR)/$$(*D)_comm.h $(INCDIR)/commtech.h + if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ; fi + if [ ! -d $(OBJDIR)/$(COMMDIR) ] ; then mkdir $(OBJDIR)/$(COMMDIR) ; fi + if [ ! -d $(OBJDIR)/$(COMMDIR)/$(*D) ] ; then mkdir $(OBJDIR)/$(COMMDIR)/$(*D) ; fi + cd $(INCDIR) ; ln -sfT $(*D)_comm.h specific_comm.h + $(CC) $(CFLAGS) -I$(INCDIR) $< -o $@ + +$(OBJDIR)/%.o: $(SRCDIR)/$$(*F).c $(INCDIR)/$$(*D)_comm.h $(INCDIR)/commtech.h + if [ ! -d $(OBJDIR) ] ; then mkdir $(OBJDIR) ; fi + if [ ! -d $(OBJDIR)/$(*D) ] ; then mkdir $(OBJDIR)/$(*D) ; fi + cd $(INCDIR) ; ln -sfT $(*D)_comm.h specific_comm.h + $(CC) $(CFLAGS) -I$(INCDIR) -I$(LOCALDIR)/$(PHL_INCDIR) -I../$(PHLDIR)/$(PHL_INCDIR) $< -o $@ diff --git a/communication_techniques/TODO b/communication_techniques/TODO new file mode 100644 index 0000000..48d5d19 --- /dev/null +++ b/communication_techniques/TODO @@ -0,0 +1 @@ +- move init_thread_library in papihighlevel.c in init_library (the constructor is only called once) diff --git a/communication_techniques/include/asm_cache_comm.h b/communication_techniques/include/asm_cache_comm.h index 16b8871..19a75ca 100644 --- a/communication_techniques/include/asm_cache_comm.h +++ b/communication_techniques/include/asm_cache_comm.h @@ -1,37 +1,36 @@ #ifndef _SPECIFIC_COMM_H_ #define _SPECIFIC_COMM_H_ 1 -#include - /* Non standard include */ -#include +#include /* This is not an error, we need this two-macro system */ #define toString(x) doStringification(x) #define doStringification(x) #x -struct communication_channel +__BEGIN_DECLS + +struct comm_channel { - void *buf[2 * BUF_SIZE / sizeof(void *)] __attribute__ ((aligned (CACHE_LINE_SIZE))); - int state __attribute__ ((aligned (CACHE_LINE_SIZE))); + volatile void *buf[2 * BUF_SIZE / sizeof(void *)] __attribute__ ((aligned (CACHE_LINE_SIZE))); + volatile int state __attribute__ ((aligned (CACHE_LINE_SIZE))); int idx __attribute__ ((aligned (CACHE_LINE_SIZE))); }; -struct communication_assoc +struct thread_comm { - struct communication_assoc *next; - struct communication_assoc *prev; - pthread_t tid; - struct communication_channel *channel; + struct comm_channel *channel; int receiver_idx; + int unused; }; -extern struct communication_assoc assoc_root; +extern struct thread_comm *tcomms; +extern int swap_buffer; -__BEGIN_DECLS - -struct communication_assoc *create_comm_assoc(void); -static inline void send(void **addr) { +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); +static inline void send(void **addr) +{ asm volatile("mov %%gs:channel@NTPOFF + 2 *" toString(BUF_SIZE) " + " toString(CACHE_LINE_SIZE) ", %%eax\n\t" "mov %0, %%gs:channel@NTPOFF(%%eax)\n\t" "addl $4, %%eax\n\t" diff --git a/communication_techniques/include/c_cache_comm.h b/communication_techniques/include/c_cache_comm.h new file mode 100644 index 0000000..c11ce07 --- /dev/null +++ b/communication_techniques/include/c_cache_comm.h @@ -0,0 +1,44 @@ +#ifndef _SPECIFIC_COMM_H_ +#define _SPECIFIC_COMM_H_ 1 + +/* Non standard include */ +#include + +/* This is not an error, we need this two-macro system */ +#define toString(x) doStringification(x) +#define doStringification(x) #x + +struct comm_channel +{ + volatile void *buf[2 * BUF_SIZE / sizeof(void *)] __attribute__ ((aligned (CACHE_LINE_SIZE))); + volatile int state __attribute__ ((aligned (CACHE_LINE_SIZE))); + int idx __attribute__ ((aligned (CACHE_LINE_SIZE))); +}; + +struct thread_comm +{ + struct comm_channel *channel; + int receiver_idx; +}; + +extern struct thread_comm *tcomms; +extern __thread struct comm_channel channel; + +__BEGIN_DECLS + +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); +static inline void send(void **addr) +{ + channel.buf[channel.idx++] = addr; + channel.idx %= 2 * BUF_SIZE / sizeof(void *); + if (!(channel.idx % (BUF_SIZE / sizeof(void *)))) + { + while (channel.state); + channel.state = 1; + } +} + +__END_DECLS + +#endif diff --git a/communication_techniques/include/common_comm.h b/communication_techniques/include/commtech.h similarity index 51% rename from communication_techniques/include/common_comm.h rename to communication_techniques/include/commtech.h index 2f5d17b..f0deb87 100644 --- a/communication_techniques/include/common_comm.h +++ b/communication_techniques/include/commtech.h @@ -1,7 +1,5 @@ -#ifndef _COMMON_COMM_H_ -#define _COMMON_COMM_H_ 1 - -#include +#ifndef _COMMTECH_H_ +#define _COMMTECH_H_ 1 #define CACHE_LINE_SIZE 128 #define BUF_SIZE CACHE_LINE_SIZE @@ -10,16 +8,15 @@ #define unlikely(x) __builtin_expect(!!(x), 0) extern volatile int cont; +extern long nb_prod; __BEGIN_DECLS -void add_sender(void); -void remove_sender(void); -volatile int *init_comm(void); +int init_library(void); +int end_library(void); +int init_producer_thread(void); +int end_producer_thread(void); void reception(void (*)(void *)); -extern int swap_buffer; -void wait_initialization(void); -void discover_new_producers(void); __END_DECLS diff --git a/communication_techniques/include/fake_comm.h b/communication_techniques/include/fake_comm.h index 90c2e95..ac9f3c2 100644 --- a/communication_techniques/include/fake_comm.h +++ b/communication_techniques/include/fake_comm.h @@ -1,27 +1,21 @@ -#ifndef __COMM_H_ -#define __COMM_H_ 1 - -#include - -/* Non standard include */ -#include +#ifndef _SPECIFIC_COMM_H_ +#define _SPECIFIC_COMM_H_ 1 #define FAKE_NURSERY_START 1 -struct communication_assoc +struct thread_comm { - struct communication_assoc *next; - struct communication_assoc *prev; - pthread_t tid; + int unused; }; -extern struct communication_assoc assoc_root; +extern struct thread_comm *tcomms; +extern __thread void ** volatile store_var; __BEGIN_DECLS -struct communication_assoc *create_comm_assoc(void); +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); static inline void send(void **addr) { - static __thread void **store_var = NULL; store_var = addr; } diff --git a/communication_techniques/include/jikes_barrier_comm.h b/communication_techniques/include/jikes_barrier_comm.h index 536060e..803482d 100644 --- a/communication_techniques/include/jikes_barrier_comm.h +++ b/communication_techniques/include/jikes_barrier_comm.h @@ -1,32 +1,29 @@ -#ifndef __COMM_H_ -#define __COMM_H_ 1 +#ifndef _SPECIFIC_COMM_H_ +#define _SPECIFIC_COMM_H_ 1 #include -/* Non standard include */ -#include - #define FAKE_NURSERY_START 1 -#define REALLY_FAKE_NURSERY_START ((uintptr_t) -1) +#define ANOTHER_FAKE_NURSERY_START ((uintptr_t) -1) -struct communication_assoc +struct thread_comm { - struct communication_assoc *next; - struct communication_assoc *prev; - pthread_t tid; + int unused; }; -extern struct communication_assoc assoc_root; +extern struct thread_comm *tcomms; __BEGIN_DECLS -struct communication_assoc *create_comm_assoc(void); +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); void insert(void *); -static inline void send(void **addr) { +static inline void send(void **addr) +{ void *ptd_addr; ptd_addr = *addr; /* NOTE: Not done in real jikes barrier */ - if (!((uintptr_t) addr >= REALLY_FAKE_NURSERY_START) && ((uintptr_t) ptd_addr >= FAKE_NURSERY_START)) + if (!((uintptr_t) addr >= ANOTHER_FAKE_NURSERY_START) && ((uintptr_t) ptd_addr >= FAKE_NURSERY_START)) insert(addr); } diff --git a/communication_techniques/include/pipe_comm.h b/communication_techniques/include/pipe_comm.h index fd2d49e..f5e4150 100644 --- a/communication_techniques/include/pipe_comm.h +++ b/communication_techniques/include/pipe_comm.h @@ -1,31 +1,23 @@ -#ifndef __COMM_H_ -#define __COMM_H_ 1 +#ifndef _SPECIFIC_COMM_H_ +#define _SPECIFIC_COMM_H_ 1 -#include #include -/* Non standart include */ -#include - #define READ_IDX 0 #define WRITE_IDX 1 -struct communication_assoc +struct thread_comm { - struct communication_assoc *next; - struct communication_assoc *prev; - pthread_t tid; int *pipefd; - struct communication_channel *channel; - int receiver_idx; }; __BEGIN_DECLS extern __thread int pipefd[]; -extern struct communication_assoc assoc_root; +extern struct thread_comm *tcomms; -struct communication_assoc *create_comm_assoc(void); +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); static inline void send(void **addr) { write(pipefd[WRITE_IDX], &addr, sizeof(void *)); } diff --git a/communication_techniques/include/private_common.h b/communication_techniques/include/private_common.h new file mode 100644 index 0000000..ab27b64 --- /dev/null +++ b/communication_techniques/include/private_common.h @@ -0,0 +1,10 @@ +#ifndef _PRIVATE_COMMON_H_ +#define _PRIVATE_COMMON_H_ 1 + +__BEGIN_DECLS + +void wait_initialization(void); + +__END_DECLS + +#endif diff --git a/communication_techniques/include/shared_mem_comm.h b/communication_techniques/include/shared_mem_comm.h index 8bc88b9..0bee7d7 100644 --- a/communication_techniques/include/shared_mem_comm.h +++ b/communication_techniques/include/shared_mem_comm.h @@ -1,33 +1,29 @@ -#ifndef __COMM_H_ -#define __COMM_H_ 1 - -#include +#ifndef _SPECIFIC_COMM_H_ +#define _SPECIFIC_COMM_H_ 1 /* Non standard include */ -#include +#include #define SHARED_SPACE_SIZE (2 * BUF_SIZE) #define SHARED_SPACE_VOIDPTR (SHARED_SPACE_SIZE / sizeof(void *)) -struct communication_assoc +struct thread_comm { - struct communication_assoc *next; - struct communication_assoc *prev; - pthread_t tid; - void **shared_space; + volatile void **shared_space; volatile int *cons_idx; volatile int *prod_idx; }; -extern struct communication_assoc assoc_root; +extern struct thread_comm *tcomms; __BEGIN_DECLS -extern __thread void **shared_space; +extern __thread volatile void **shared_space; extern __thread volatile int prod_idx; extern __thread volatile int cons_idx; -struct communication_assoc *create_comm_assoc(void); +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); static inline void send(void **addr) { while ((prod_idx + 1) % SHARED_SPACE_VOIDPTR == cons_idx); shared_space[prod_idx] = addr; diff --git a/communication_techniques/include/shared_mem_opt_comm.h b/communication_techniques/include/shared_mem_opt_comm.h index 5cabe9c..5184c73 100644 --- a/communication_techniques/include/shared_mem_opt_comm.h +++ b/communication_techniques/include/shared_mem_opt_comm.h @@ -1,33 +1,29 @@ -#ifndef __COMM_H_ -#define __COMM_H_ 1 - -#include +#ifndef _SPECIFIC_COMM_H_ +#define _SPECIFIC_COMM_H_ 1 /* Non standard include */ -#include +#include #define SHARED_SPACE_SIZE (2 * BUF_SIZE) #define SHARED_SPACE_VOIDPTR (SHARED_SPACE_SIZE / sizeof(void *)) -struct communication_assoc +struct thread_comm { - struct communication_assoc *next; - struct communication_assoc *prev; - pthread_t tid; - void **shared_space; + volatile void **shared_space; volatile int *cons_idx; volatile int *prod_idx; }; -extern struct communication_assoc assoc_root; +extern struct thread_comm *tcomms; __BEGIN_DECLS -extern __thread void **shared_space; +extern __thread volatile void **shared_space; extern __thread volatile int prod_idx; extern __thread volatile int cons_idx; -struct communication_assoc *create_comm_assoc(void); +int init_thread_comm(struct thread_comm *); +int end_thread_comm(void); static inline void send(void **addr) { static __thread int local_cons_idx = 0; diff --git a/communication_techniques/lancement.sh b/communication_techniques/lancement.sh new file mode 100755 index 0000000..5954686 --- /dev/null +++ b/communication_techniques/lancement.sh @@ -0,0 +1,139 @@ +#! /bin/bash + +set -u + +# Files and directories +binDir="bin" +calcDir="calculation" +PHLDir="../papihighlevel" +PHLLibDir="lib" +PAPIDir="${PHLDir}/papi" +PAPILibDir="src" +PAPIPFMDir="libpfm-3.y/lib" + +# Param +binList="asm_cache_comm c_cache_comm pipe_comm shared_mem_comm shared_mem_opt_comm jikes_barrier_comm fake_comm" # Type de communication +nbProdList="1" # Nombre de cores producteurs +typeProdList="none matrice useless_loop" # Methode pour produire les valeurs +typeCacheList="L2 Memory" # Niveau de cache partage + +# Const +nbIter="5000000" # Nb de lignes produites +sizeBuf="1" # En nombre de lignes de cache + +# Nom generique des fichiers de log +logFileName="\$perfDirName/cache_\$typeCache-nbProd_\$nbProd-typeProd_\$typeProd-argTypeProd_\$argTypeProd-nbIter_\$nbIter-\$bin.log" +expDirName="logs" +perfDirName="$expDirName/perfCommMulti-`date +'%F-%Hh%Mm%S'`" + +LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}${LD_LIBRARY_PATH:+:}${PHLDir}/${PHLLibDir}:${PAPIDir}/${PAPILibDir}:${PAPIDir}/${PAPILibDir}/${PAPIPFMDir}" + +PAPILibPresent="" +PFMLibPresent="" +papiHighLevelLibPresent="" +LD_LIBRARY_PATH_LEFT="${LD_LIBRARY_PATH}:" +while [ -n "${LD_LIBRARY_PATH_LEFT}" ] +do + aLibDir="${LD_LIBRARY_PATH_LEFT%%:*}" + if [ -x ${aLibDir}/libpapi.so.3 ] + then + PAPILibPresent="1"; + fi + if [ -x ${aLibDir}/libpfm.so.3 ] + then + PHLLibPresent="1"; + fi + if [ -x ${aLibDir}/libpapihighlevel.so ] + then + PHLLibPresent="1"; + fi + if [ -n "${PAPILibPresent}" -a -n "${PHLLibPresent}" -a -n "${PFMLibPresent}" ] + then + break + fi + LD_LIBRARY_PATH_LEFT="${LD_LIBRARY_PATH_LEFT#*:}" +done +if [ -z "${PAPILibPresent}" -o -z "${PHLLibPresent}" ] +then + echo "Libraries needed for this bench not accessible by \$LD_LIBRARY_PATH" > /dev/stderr # Is there a better way to display something on stderr ? + exit 1 +fi + +unset PAPILibPresent +unset PHLLibPresent +unset LD_LIBRARY_PATH_LEFT +export LD_LIBRARY_PATH + +[ -d "$expDirName" ] || mkdir "$expDirName" +[ -d "$perfDirName" ] || mkdir "$perfDirName" + +function_run () { + case $typeProd in + "none" ) optTypeProd="" ;; + "matrice" ) optTypeProd="-c lib/${calcDir}/libcalc_mat.so 16" ;; + "useless_loop" ) optTypeProd="-c lib/${calcDir}/libcalc_useless_loop.so ${argTypeProd}" ;; + * ) exit 1 ;; + esac + case $typeCache in + "Memory" ) optTypeCache="" ;; + "L2" ) optTypeCache="-s" ;; + * ) exit 1 ;; + esac + + make $binDir/$bin + echo "On lance : \"${bin##*/} $optTypeCache $optTypeProd -p $nbProd -n $nbIter\"" + beginingDate=`date +%s` + + ( $binDir/$bin $optTypeCache $optTypeProd -p $nbProd -n $nbIter || echo "echec experience" ) | eval tee $logFileName + endDate=`date +%s` + duration_sec=`expr \( $endDate - $beginingDate \) % 60` + duration_min=`expr \( $endDate - $beginingDate \) / 60` + duration_hrs=`expr $duration_min / 60` + duration_min=`expr $duration_min % 60` + + echo "Fin de l'experience : `date +'%H:%M:%S (%d/%m/%y)'`" + echo "La duree est de : ${duration_hrs}hrs ${duration_min}min ${duration_sec}sec" + echo "" +} + + + +echo -e "On commence les perfs\n" +globalBeginingDate=`date +%s` + +for nbProd in $nbProdList ; do + for typeProd in $typeProdList; do + for typeCache in $typeCacheList ; do + for bin in $binList ; do + case $typeProd in + "useless_loop" ) + case $bin in + "jikes_barrier_comm" | "asm_cache_comm" | "c_cache_comm" ) + for argTypeProd in 1 `seq 5 5 50` ; do + function_run ; + done ;; + * ) + argTypeProd=1 ; + function_run ;; + esac ;; + "matrice" ) + argTypeProd=16 ; + function_run ;; + * ) + argTypeProd=1 ; + function_run ;; + esac + done + done + done +done + +globalEndDate=`date +%s` +globalDuration_sec=`expr \( $globalEndDate - $globalBeginingDate \) % 60` +globalDuration_min=`expr \( $globalEndDate - $globalBeginingDate \) / 60` +globalDuration_hrs=`expr $globalDuration_min / 60` +globalDuration_min=`expr $globalDuration_min % 60` + +echo "Fin de la serie d'experience : `date +'%H:%M:%S (%d/%m/%y)'`" +echo "La duree totale est de : ${globalDuration_hrs}hrs ${globalDuration_min}min ${globalDuration_sec}sec" + diff --git a/communication_techniques/parsing.sh b/communication_techniques/parsing.sh new file mode 100755 index 0000000..1da8dbb --- /dev/null +++ b/communication_techniques/parsing.sh @@ -0,0 +1,330 @@ +#! /bin/bash + +set -u + +#barriereList="jikes_barrier asm_cache c_cache fake" +barriereList="jikes_barrier asm_cache c_cache" +communicationList="asm_cache c_cache shared_mem shared_mem_opt pipe" +comList=`ls *.log | perl -ni -e '/-([^-]+)_comm/; $a{$1}=""; END { foreach ( sort keys %a ) {print "$_ "}}'` +cacheList=`ls *log | perl -ni -e '/cache_([^-]+)-/; $a{$1}=""; END { foreach ( sort keys %a ) {print "$_ "}}'` +prodList=`ls *.log | perl -ni -e '/typeProd_([^-]+)-/; $a{$1}=""; END { foreach ( sort keys %a ) {print "$_ "}}'` +barriereCommaList=`echo $barriereList | sed "s/ /,/g"` +argTypeProdList=`eval ls *typeProd_useless_loop*{$barriereCommaList}_comm.log | perl -ni -e '/argTypeProd_([\d]+)-/; $a{$1}=""; END { foreach ( sort { $a <=> $b } keys %a ) {print "$_ "}}'` + +metriqueList="cache_hits cache_miss cycles total_time" + +echo "set style data histogram" > multicores.gnuplot +echo "set style histogram cluster gap 1" >> multicores.gnuplot +echo "set style fill solid border -1" >> multicores.gnuplot +echo "set boxwidth 0.9" >> multicores.gnuplot +echo "set xtic rotate by -45" >> multicores.gnuplot +echo "set bmargin 5" >> multicores.gnuplot +echo "set terminal postscript landscape color" >> multicores.gnuplot + +use_histo () +{ + local prod bench + prod="$1" + bench="$2" + + [ "$bench" = "communication" -o "$prod" != "useless_loop" ] + return $? +} + +create_dat_header () +{ + local prod bench metrique + prod="$1" + bench="$2" + metrique="$3" + + # Create file + > bench_$bench-prod_$prod-metrique_$metrique.dat + + # Only one point per com and cache + if use_histo "$prod" "$bench" + then + for i in 1 2 3 # 1: total, 2: by loop, 3: by write + do + if [ $i -ne 1 ] + then + echo >> bench_$bench-prod_$prod-metrique_$metrique.dat + fi + echo -ne "Method\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat + for cache in $cacheList + do + echo -ne "\t$cache" >> bench_$bench-prod_$prod-metrique_$metrique.dat + done + done + # Several points per com and cache (one per calc argument) + else + for i in 1 2 + do + if [ $i -ne 1 ] + then + echo >> bench_$bench-prod_$prod-metrique_$metrique.dat + fi + for j in 1 2 3 # 1: total, 2: by loop, 3: by write + do + echo -ne "argTypeProd\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat + for com in $barriereList + do + echo -ne "\t$com" >> bench_$bench-prod_$prod-metrique_$metrique.dat + done + echo >> bench_$bench-prod_$prod-metrique_$metrique.dat + done + done + fi +} + +get_metric_values () +{ + local prod com cache argTypeProd logFile + prod="$1" + com="$2" + cache="$3" + argTypeProd="$4" + metriquePattern="$5" + + logFile=cache_$cache-*-typeProd_$prod-argTypeProd_$argTypeProd-*-${com}_comm.log + perl -n -e "print \"\$1 \$2 \$3 \" if /$metriquePattern.* (\S+) \/ (\S+) \/ (\S+)/" $logFile +} + +create_simple_dat_body () +{ + local prod bench metrique argTypeProd + prod="$1" + bench="$2" + metrique="$3" + argTypeProd="$4" + + for com in `eval echo \\\$\${bench}List` + do + for i in 1 2 3 # 1: total, 2: by loop, 3: by write + do + echo -ne "\n$com\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat + for cache in $cacheList + do + if [ $i -eq 1 ] + then + valuetmp=`get_metric_values "$prod" "$com" "$cache" "$argTypeProd" "$metriquePattern"` + eval value$cache=\"$valuetmp\" + fi + eval echo -ne "\${value$cache}" | sed -r "s/^([^ ]+ ){$((i-1))}([^ ]+).*/\t\2/" >> bench_$bench-prod_$prod-metrique_$metrique.dat + done + done + done +} + +create_complex_dat_body () +{ + local prod bench metrique + prod="$1" + bench="$2" + metrique="$3" + + for argTypeProd in $argTypeProdList + do + for cache in $cacheList + do + if [ $cache != ${cacheList%% *} -o $argTypeProd != ${argTypeProdList%% *} ] + then + echo "" >> bench_$bench-prod_$prod-metrique_$metrique.dat + fi + for i in 1 2 3 # 1: total, 2: by loop, 3: by write + do + echo -ne "\n$argTypeProd\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat + for com in `eval echo \\\$\${bench}List` + do + if [ $i -eq 1 ] + then + valuetmp=`get_metric_values "$prod" "$com" "$cache" "$argTypeProd" "$metriquePattern"` + eval value$com=\"$valuetmp\" + fi + eval echo -ne "\${value$com}" | sed -r "s/^([^ ]+ ){$((i-1))}([^ ]+).*/\t\2/" >> bench_$bench-prod_$prod-metrique_$metrique.dat + done + done + done + done +} + +create_dat_body () +{ + local prod bench metrique argTypeProd + prod="$1" + bench="$2" + metrique="$3" + argTypeProd="$4" + + if use_histo "$prod" "$bench" + then + create_simple_dat_body "$prod" "$bench" "$metrique" "$argTypeProd" "$metriquePattern" + else + create_complex_dat_body "$prod" "$bench" "$metrique" "$argTypeProd" "$metriquePattern" + fi +} + +create_gnuplot_header () +{ + local prod bench gnuplotFile + prod="$1" + bench="$2" + gnuplotFile="$3" + + echo "set style fill solid border -1" > $gnuplotFile + echo "set boxwidth 0.9" >> $gnuplotFile + echo "set xtic rotate by -45" >> $gnuplotFile + echo "set bmargin 5" >> $gnuplotFile + echo "set terminal postscript landscape color" >> $gnuplotFile + if use_histo "$prod" "$bench" + then + echo "set style data histogram" >> $gnuplotFile + echo "set style histogram cluster gap 1" >> $gnuplotFile + else + echo "set style data linespoints" >> $gnuplotFile + fi +} + +create_simple_gnuplot_body () +{ + local metrique ylabel yscale patternPlotFile datFile + ylabel="$1" + lineNum="$2" + datFile="$3" + patternPlotFile="$4" + + echo "set ylabel \"$ylabel\"" >> $patternPlotFile.gnuplot + echo "set output '$patternPlotFile.ps'" >> $patternPlotFile.gnuplot + echo "plot '$datFile' every 3::$lineNum using 2:xtic(1) title 2 , '' every 3::$lineNum u 3 ti 3" >> $patternPlotFile.gnuplot +} + +create_complex_gnuplot_body () +{ + local bench ylabel lineNum datFile patternPlotFile columnNo baseTitle + bench="$1" + ylabel="$2" + lineNum="$3" + datFile="$4" + patternPlotFile="$5" + columnNo=2 + + echo "set ylabel \"$ylabel\"" >> $patternPlotFile.gnuplot + echo "set output '$patternPlotFile.ps'" >> $patternPlotFile.gnuplot + for com in `eval echo \\\$\${bench}List` ; do + baseTitle=`head -1 $datFile | cut -f $((columnNo + 2))` + if [ $columnNo -ne 2 ] + then + echo -n ", '' " >> $patternPlotFile.gnuplot + else + echo -n "plot '$datFile' " >> $patternPlotFile.gnuplot + fi + echo -n "every :2:$lineNum:0:$lineNum using 1:$columnNo:xtic(1) title '$baseTitle (L2)'" >> $patternPlotFile.gnuplot + echo -n ", '' every :2:$lineNum:1:$lineNum using 1:$columnNo:xtic(1) title '$baseTitle (mem)'" >> $patternPlotFile.gnuplot + columnNo=$((columnNo + 1)) + done + echo >> $patternPlotFile.gnuplot +} + +create_gnuplot_body () +{ + local prod bench yscale ylabel lineNum datFile patternPlotFile + prod="$1" + bench="$2" + yscale="$3" + ylabel="$4" + lineNum="$5" + datFile="$6" + patternPlotFile="$7" + + echo "set $yscale y" >> $patternPlotFile.gnuplot + if [ "$yscale" = "nologscale" ] + then + echo "set yrange [0:*]" >> $patternPlotFile.gnuplot + else + echo "set yrange [*:*]" >> $patternPlotFile.gnuplot + fi + echo "set title \"Producteur : $prod\"" >> $patternPlotFile.gnuplot + if use_histo "$prod" "$bench" + then + create_simple_gnuplot_body "$ylabel" "$lineNum" "$datFile" "$patternPlotFile" + else + create_complex_gnuplot_body "$bench" "$ylabel" "$lineNum" "$datFile" "$patternPlotFile" + fi +} + +create_gnuplot_file () +{ + local prod bench metrique ylabel yscale avg lineNum + prod="$1" + bench="$2" + metrique="$3" + baseYlabel="$4" + + for yscale in "nologscale" "logscale" + do + for avg in total byLoop byWrite + do + case $avg in + total) + lineNum=0 + ylabel="$baseYlabel" ;; + byLoop) + lineNum=1 + ylabel="$baseYlabel par boucle" ;; + byWrite) + lineNum=2 + ylabel="$baseYlabel par ecriture" ;; + esac + datFile=bench_$bench-prod_$prod-metrique_$metrique.dat + patternPlotFile="bench_$bench-prod_$prod-$metrique-$avg-$yscale" # Name without extension of plot and ps files + create_gnuplot_header "$prod" "$bench" "$patternPlotFile.gnuplot" + if [ $metrique != "total_time" -o $yscale != "logscale" ] + then + create_gnuplot_body "$prod" "$bench" "$yscale" "$ylabel" "$lineNum" "$datFile" "$patternPlotFile" + fi + done + done +} + +for prod in $prodList ; do + case "$prod" in + matrice) argTypeProd=16 ;; + *) argTypeProd=1 ;; + esac + for bench in "communication" "barriere" ; do + # Create dat headers + for metrique in $metriqueList ; do + case "$metrique" in + cache_hits) + metriquePattern="cache hits" + ylabel="Nb cache hit" ;; + cache_miss) + metriquePattern="cache miss" + ylabel="Nb cache miss" ;; + cycles) + metriquePattern="cycles" + ylabel="Nb cycles" ;; + total_time) + metriquePattern="total_time" + ylabel="Secondes" ;; + *) + echo "Pas de pattern pour cette métrique : $metrique" + echo "Pas de label pour cette métrique : $metrique" + exit 1 ;; + esac + create_dat_header "$prod" "$bench" "$metrique" + create_dat_body "$prod" "$bench" "$metrique" "$argTypeProd" "$metriquePattern" + create_gnuplot_file "$prod" "$bench" "$metrique" "$ylabel" + done + done +done + +for gnuplotFile in *.gnuplot +do + gnuplot "$gnuplotFile" +done + +for psFile in *.ps +do + ps2pdf $psFile +done diff --git a/communication_techniques/src/calculation/calc_mat.c b/communication_techniques/src/calculation/calc_mat.c new file mode 100644 index 0000000..c7f2bd2 --- /dev/null +++ b/communication_techniques/src/calculation/calc_mat.c @@ -0,0 +1,58 @@ +#include +#include + + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + + +static int *mat, *vect; +static int li; +static int n, m; /* Size of the matrice: n lines, m columns */ +static int *mat_cell_ptr; + +int init_calc(int size) +{ + int i; + + n = size; + m = size; + srand(42); + mat = (int *) malloc(n * m * sizeof(int)); + if (mat == NULL) + { + fprintf(stderr, "calc_mat: Unable to allocate memory for matrice calculation\n"); + return -1; + } + vect = (int *) malloc(m * sizeof(int)); + if (vect == NULL) + { + free(mat); + fprintf(stderr, "calc_mat: Unable to allocate memory for matrice calculation\n"); + return -1; + } + for (i = 0; i < n * m; i++) + mat[i] = rand(); + li = 0; + return 0; +} + +void **do_calc(void) +{ + int co, p = 0; + + for (co = 0; co < m; co++) + p += mat[li * m + co] * vect[li]; + mat[li * m] = p; + if (unlikely(++li >= n)) + li = 0; + mat_cell_ptr = &mat[li * m]; + return (void **) &mat_cell_ptr; +} + +int end_calc(void) +{ + free(mat); + free(vect); + return 0; +} diff --git a/communication_techniques/src/calculation/calc_useless_loop.c b/communication_techniques/src/calculation/calc_useless_loop.c new file mode 100644 index 0000000..84865e8 --- /dev/null +++ b/communication_techniques/src/calculation/calc_useless_loop.c @@ -0,0 +1,28 @@ +#include +#include +#include + + +static int nb_loop = 0, prod = 0, *prod_ptr = ∏ +volatile int fourty_two = 42; +unsigned int seedp; + +int init_calc(int param_nb_loop) +{ + nb_loop = param_nb_loop; + return 0; +} + +void **do_calc(void) +{ + int i; + + for(i = 0; i < nb_loop; i++) + prod += fourty_two; + return (void **) &prod_ptr; +} + +int end_calc(void) +{ + return 0; +} diff --git a/communication_techniques/src/common.c b/communication_techniques/src/common.c deleted file mode 100644 index febfa5d..0000000 --- a/communication_techniques/src/common.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include -#include - -/* Non standard include */ -#include - - -struct communication_assoc assoc_root; -static pthread_mutex_t assoc_lock = PTHREAD_MUTEX_INITIALIZER; -static struct communication_assoc assoc_tmp; -static volatile int init = 0; -volatile int cont = 1; - -void initialize_library(void) -{ - assoc_tmp.prev = &assoc_tmp; - assoc_tmp.next = &assoc_tmp; - assoc_root.prev = &assoc_root; - assoc_root.next = &assoc_root; -} - -volatile int *init_comm(void) -{ - return &cont; -} - -void wait_initialization(void) -{ - while (!init); -} - -void add_sender(void) -{ - struct communication_assoc *assoc; - - assoc = create_comm_assoc(); - pthread_mutex_lock(&assoc_lock); - if (!init) - { - initialize_library(); - init = 1; - } - assoc->next = assoc_tmp.next; - assoc_tmp.next->prev = assoc; - assoc->prev = &assoc_tmp; - assoc_tmp.next = assoc; - pthread_mutex_unlock(&assoc_lock); -} - -void remove_sender() -{ - printf("remove_communication_channel: Not yet implemented\n"); -} - -void discover_new_producers(void) -{ - /* If there is some new thread for the write barrier */ - if(&assoc_tmp != assoc_tmp.next) - { - /* printf("Adding a new set of producers\n"); */ - pthread_mutex_lock(&assoc_lock); - /* - * list in assoc_tmp is inserted between assoc_root - * and the first elements of assoc_root list - */ - assoc_root.next->prev = assoc_tmp.prev; - assoc_tmp.prev->next = assoc_root.next; - assoc_root.next = assoc_tmp.next; - assoc_root.next->prev = &assoc_root; - /* - * assoc_tmp temporary list has been copied in - * assoc_root list. assoc_tmp is now alone and so - * double linked to itself - */ - assoc_tmp.prev = &assoc_tmp; - assoc_tmp.next = &assoc_tmp; - pthread_mutex_unlock(&assoc_lock); - } -} diff --git a/communication_techniques/src/asm_cache.c b/communication_techniques/src/communication/asm_cache.c similarity index 53% rename from communication_techniques/src/asm_cache.c rename to communication_techniques/src/communication/asm_cache.c index f4fffb9..4a49dad 100644 --- a/communication_techniques/src/asm_cache.c +++ b/communication_techniques/src/communication/asm_cache.c @@ -3,21 +3,25 @@ #include /* Non standard include */ -#include +#include +#include #include -__thread struct communication_channel channel; +__thread struct comm_channel channel; -struct communication_assoc *create_comm_assoc(void) +int init_thread_comm(struct thread_comm *comm) { - struct communication_assoc *assoc; + comm->receiver_idx = 0; + comm->channel = &channel; + comm->channel->state = 0; + comm->channel->idx = 0; + return 0; +} - assoc = (struct communication_assoc *) malloc(sizeof(struct communication_assoc)); - assoc->tid = pthread_self(); - assoc->receiver_idx = 0; - assoc->channel = &channel; - return assoc; +int end_thread_comm(void) +{ + return 0; } char *dstr="buffer transition\n"; @@ -39,17 +43,15 @@ void reception(void (*on_receive)(void *)) { wait_initialization(); /* printf("Activate the consumer...\n"); */ - while(cont) + while (cont) { - struct communication_assoc *cur; + int i; - discover_new_producers(); - cur = assoc_root.next; - while(cur != &assoc_root) + for (i = 0; i < nb_prod; i++) { - struct communication_channel *channel = cur->channel; - if(channel->state) + if(tcomms[i].channel->state) { + int j, n; /* * cur->receiver_idx point to the last cache * line we have read. We go to the next cache @@ -59,14 +61,19 @@ void reception(void (*on_receive)(void *)) * line we correct the pointer to point to * the first one (this is done by the modulo) */ - int i = cur->receiver_idx; - int n = cur->receiver_idx + (BUF_SIZE / sizeof(void *)); - cur->receiver_idx = n % ((2 * BUF_SIZE) / sizeof(void *)); - for(; ibuf[i]); - channel->state = 0; + j = tcomms[i].receiver_idx; + n = tcomms[i].receiver_idx + (BUF_SIZE / sizeof(void *)); + tcomms[i].receiver_idx = n % ((2 * BUF_SIZE) / sizeof(void *)); + for(; jbuf[j]); + } + tcomms[i].channel->state = 0; } - cur = cur->next; } } } diff --git a/communication_techniques/src/communication/c_cache.c b/communication_techniques/src/communication/c_cache.c new file mode 100644 index 0000000..b310595 --- /dev/null +++ b/communication_techniques/src/communication/c_cache.c @@ -0,0 +1,66 @@ +#include +#include +#include + +/* Non standard include */ +#include +#include +#include + + +__thread struct comm_channel channel; + +int init_thread_comm(struct thread_comm *comm) +{ + comm->receiver_idx = 0; + comm->channel = &channel; + comm->channel->state = 0; + comm->channel->idx = 0; + return 0; +} + +int end_thread_comm(void) +{ + return 0; +} + +char *dstr="buffer transition\n"; + +void reception(void (*on_receive)(void *)) +{ + wait_initialization(); + /* printf("Activate the consumer...\n"); */ + while (cont) + { + int i; + + for (i = 0; i < nb_prod; i++) + { + if(tcomms[i].channel->state) + { + int j, n; + /* + * cur->receiver_idx point to the last cache + * line we have read. We go to the next cache + * line "+ (CACHE_LINE_SIZE >> 2)" (because + * the line is full of integer (2^2 octets) + * and then if we are after the second cache + * line we correct the pointer to point to + * the first one (this is done by the modulo) + */ + j = tcomms[i].receiver_idx; + n = tcomms[i].receiver_idx + (BUF_SIZE / sizeof(void *)); + tcomms[i].receiver_idx = n % ((2 * BUF_SIZE) / sizeof(void *)); + for(; jbuf[j]); + } + tcomms[i].channel->state = 0; + } + } + } +} diff --git a/communication_techniques/src/communication/common.c b/communication_techniques/src/communication/common.c new file mode 100644 index 0000000..03f02dd --- /dev/null +++ b/communication_techniques/src/communication/common.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +/* Non standard include */ +#include +#include + + +struct thread_comm *tcomms; +volatile int cont = 1; +static int init = 0; +static int error = 0; +static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER; + +int init_library(void) +{ + tcomms = (struct thread_comm *) malloc(nb_prod * sizeof(struct thread_comm)); + if (tcomms == NULL) + { + fprintf(stderr, "Failed to allocate %lu bytes needed by the library to work\n", nb_prod * sizeof(struct thread_comm)); + return -1; + } + return 0; +} + +int end_library(void) +{ + free(tcomms); + return 0; +} + +int get_thread_number(void) +{ + static int i = 0; + static pthread_mutex_t i_lock = PTHREAD_MUTEX_INITIALIZER; + int i_local; + + pthread_mutex_lock(&i_lock); + i_local = i; + i++; + pthread_mutex_unlock(&i_lock); + return i_local; +} + +int init_producer_thread(void) +{ + int thread_num; + + thread_num = get_thread_number(); + if (init_thread_comm(&tcomms[thread_num])) + { + pthread_mutex_lock(&init_lock); + error = 1; + pthread_cond_signal(&init_cond); + pthread_mutex_unlock(&init_lock); + return -1; + } + if (thread_num == nb_prod - 1) + { + pthread_mutex_lock(&init_lock); + init = 1; + pthread_cond_signal(&init_cond); + pthread_mutex_unlock(&init_lock); + } + return 0; +} + +int end_producer_thread(void) +{ + return end_thread_comm(); +} + +int wait_initialization(void) +{ + pthread_mutex_lock(&init_lock); + if (!init && !error) + pthread_cond_wait(&init_cond, &init_lock); + pthread_mutex_unlock(&init_lock); + if (error) + return -1; + return 0; +} diff --git a/communication_techniques/src/communication/fake.c b/communication_techniques/src/communication/fake.c new file mode 100644 index 0000000..ffd72c3 --- /dev/null +++ b/communication_techniques/src/communication/fake.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +/* Non standard include */ +#include +#include +#include + + +__thread void ** volatile store_var = NULL; + + +int init_thread_comm(struct thread_comm *comm) +{ + return 0; +} + +int end_thread_comm(void) +{ + return 0; +} + +void reception(void (*on_receive)(void *)) +{ + wait_initialization(); /* Not needed but here for equity with others techniques */ + /* printf("Activate the consumer...\n"); */ + while (cont); +} diff --git a/communication_techniques/src/jikes_barrier.c b/communication_techniques/src/communication/jikes_barrier.c similarity index 74% rename from communication_techniques/src/jikes_barrier.c rename to communication_techniques/src/communication/jikes_barrier.c index 314b83e..6e0772f 100644 --- a/communication_techniques/src/jikes_barrier.c +++ b/communication_techniques/src/communication/jikes_barrier.c @@ -4,7 +4,8 @@ #include /* Non standard include */ -#include +#include +#include #include @@ -32,18 +33,24 @@ static struct double_linked_list *global_head = NULL; static int bufsenqueued = 0; static unsigned int lock = 0; -struct communication_assoc *create_comm_assoc(void) +int init_thread_comm(struct thread_comm *comm) { - struct communication_assoc *assoc; void **new_buffer; - new_buffer = (void **) malloc(BUFFER_SIZE); + if (posix_memalign((void *) &new_buffer, CACHE_LINE_SIZE, BUFFER_SIZE)) + { + fprintf(stderr, "Failed to allocate a new buffer for the thread\n"); + return -1; + } local_tail = new_buffer + (USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS - - (USABLE_BUFFER_BYTES % (1 << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS; // The second parenthesis is equal to 0 + (USABLE_BUFFER_BYTES % (1 << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS; /* The second parenthesis is equal to 0 */ local_tail_buffer_end = local_tail; - assoc = (struct communication_assoc *) malloc(sizeof(struct communication_assoc)); - assoc->tid = pthread_self(); - return assoc; + return 0; +} + +int end_thread_comm(void) +{ + return 0; } void set_next(struct double_linked_list *list, struct double_linked_list *next) @@ -85,7 +92,7 @@ static void spin_unlock(unsigned int *lock) : "memory", "cc"); } -void enqueue(struct double_linked_list *list, int arity, int to_tail) // Insert in the shared buffer: tail here is the tail of the shared buffer +void enqueue(struct double_linked_list *list, int arity, int to_tail) /* Insert in the shared buffer: tail here is the tail of the shared buffer */ { spin_lock(&lock); if (to_tail) @@ -127,34 +134,39 @@ void **normalizeTail(int arity) src++; buffer_start++; } - return last; // Return the buffer address of the last address (if address goes from 0 to n then it's &buf[n] + return last; /* Return the buffer address of the last address (if address goes from 0 to n then it's &buf[n] */ } void closeAndEnqueueTail(int arity) { void **last; - if ((((uintptr_t) local_tail) & BUFFER_MASK) != 0) // prematurely closed, won't pass here if it comes from insert + if ((((uintptr_t) local_tail) & BUFFER_MASK) != 0) /* prematurely closed, won't pass here if it comes from insert */ last = normalizeTail(arity); - else // a full tail buffer - last = local_tail_buffer_end - BYTES_IN_ADDRESS; // last space in the buffer before the 8/16 bytes of metadata of the buffer + else /* a full tail buffer */ + last = local_tail_buffer_end - BYTES_IN_ADDRESS; /* last space in the buffer before the 8/16 bytes of metadata of the buffer */ enqueue((struct double_linked_list *) ((uintptr_t) last + BYTES_IN_ADDRESS), arity, 1); } void checkForAsyncCollection(void) { + if (bufsenqueued >= 262144) /* We use more than 1 Go */ + { + fprintf(stderr, "We use 1.5 Go. Program terminated before kernel panic\n"); + exit(1); + } } void tailOverflow(int arity) { void *new_buffer; if (local_tail != NULL) - closeAndEnqueueTail(arity); // Add the buffer to the tail of the shared buffer + closeAndEnqueueTail(arity); /* Add the buffer to the tail of the shared buffer */ if (posix_memalign(&new_buffer, BUFFER_SIZE, BUFFER_SIZE)) fprintf(stderr, "Failed to allocate space for queue. Is metadata virtual memory exhausted?"); local_tail = (void **) ((uintptr_t) new_buffer + (USABLE_BUFFER_BYTES - BYTES_IN_ADDRESS - - (USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS); // The second parenthesis is equal to 0 + (USABLE_BUFFER_BYTES % (arity << LOG_BYTES_IN_ADDRESS))) + BYTES_IN_ADDRESS); /* The second parenthesis is equal to 0 */ local_tail_buffer_end = local_tail; - checkForAsyncCollection(); // possible side-effect of alloc() + checkForAsyncCollection(); /* possible side-effect of posix_memalign() */ } void insert(void *addr) @@ -167,9 +179,10 @@ void insert(void *addr) void reception(void (*on_receive)(void *)) { - struct double_linked_list *list_cur; void **buf_start, **buf_ptr; - wait_initialization(); + struct double_linked_list *list_cur = NULL; + + wait_initialization(); /* Not needed but here for equity with others techniques */ /* printf("Activate the consumer...\n"); */ while (cont && (global_head == NULL)); if (!cont) @@ -182,4 +195,12 @@ void reception(void (*on_receive)(void *)) on_receive(*buf_ptr); while (cont && (list_cur->next == NULL)); } while (cont); + while (global_head != NULL) + { + void *tmp; + + tmp = (void *) ((uintptr_t) global_head & ~BUFFER_MASK); + global_head = global_head->next; + free(tmp); + } } diff --git a/communication_techniques/src/communication/pipe.c b/communication_techniques/src/communication/pipe.c new file mode 100644 index 0000000..e903954 --- /dev/null +++ b/communication_techniques/src/communication/pipe.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include + +/* Non standard include */ +#include +#include +#include + + +__thread int pipefd[2]; + +int init_thread_comm(struct thread_comm *comm) +{ + int flags; + + if (pipe(pipefd)) + { + fprintf(stderr, "Unable to create a pipe for pipe communication\n"); + return -1; + } + flags = fcntl(pipefd[READ_IDX], F_GETFL); + fcntl(pipefd[READ_IDX], F_SETFL, flags | O_NONBLOCK); + comm->pipefd = pipefd; + return 0; +} + +int end_thread_comm(void) +{ + return 0; +} + +void reception(void (*on_receive)(void *)) +{ + wait_initialization(); /* Not needed but here for equity with others techniques */ + /* printf("Activate the consumer...\n"); */ + while(cont) + { + int i; + + for (i = 0; i < nb_prod; i++) + { + int nb_read; + + for(nb_read = 0; nb_read < BUF_SIZE / sizeof(void *); nb_read++) + { + int j, n; + void *tmp_buf[BUF_SIZE / sizeof(void *)]; + + j = nb_read / sizeof(void *); + n = read(tcomms[i].pipefd[READ_IDX], (void *) ((uintptr_t) tmp_buf + nb_read), BUF_SIZE - nb_read); + if (n > 0) + { + nb_read += n; + for (; j + sizeof(void *) <= nb_read / sizeof(void *); j += sizeof(void *)) + on_receive(tmp_buf[j]); + } + } + } + } +} diff --git a/communication_techniques/src/communication/shared_mem.c b/communication_techniques/src/communication/shared_mem.c new file mode 100644 index 0000000..0ca39d1 --- /dev/null +++ b/communication_techniques/src/communication/shared_mem.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +/* Non standard include */ +#include +#include +#include + + +__thread volatile void **shared_space; +__thread volatile int cons_idx = 0; +__thread volatile int prod_idx = 0; + +int init_thread_comm(struct thread_comm *comm) +{ + if (posix_memalign((void *) &shared_space, CACHE_LINE_SIZE, SHARED_SPACE_SIZE)) + { + fprintf(stderr, "Unable to allocate space for shared mem communication\n"); + return -1; + } + comm->shared_space = shared_space; + comm->cons_idx = &cons_idx; + comm->prod_idx = &prod_idx; + return 0; +} + +int end_thread_comm(void) +{ + return 0; +} + +void reception(void (*on_receive)(void *)) +{ + wait_initialization(); + /* printf("Activate the consumer...\n"); */ + while(cont) + { + int i; + + for (i = 0; i < nb_prod; i++) + { + int cons_idx; + + for(cons_idx = *tcomms[i].cons_idx; cons_idx != *tcomms[i].prod_idx; cons_idx = (cons_idx + 1) % SHARED_SPACE_VOIDPTR, *tcomms[i].cons_idx = cons_idx) + { + /* + * The behaviour of this is not documented but we know + * the values inside buf won't change during this affectation + */ + on_receive((void *) tcomms[i].shared_space[cons_idx]); + } + } + } +} diff --git a/communication_techniques/src/communication/shared_mem_opt.c b/communication_techniques/src/communication/shared_mem_opt.c new file mode 100644 index 0000000..64e58ad --- /dev/null +++ b/communication_techniques/src/communication/shared_mem_opt.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +/* Non standard include */ +#include +#include +#include + + +__thread volatile void **shared_space; +__thread volatile int cons_idx = 0; +__thread volatile int prod_idx = 0; + +int init_thread_comm(struct thread_comm *comm) +{ + if (posix_memalign((void *) &shared_space, CACHE_LINE_SIZE, SHARED_SPACE_SIZE)) + { + fprintf(stderr, "Unable to allocate space for shared mem communication\n"); + return -1; + } + comm->shared_space = shared_space; + comm->cons_idx = &cons_idx; + comm->prod_idx = &prod_idx; + return 0; +} + +int end_thread_comm(void) +{ + return 0; +} + +void reception(void (*on_receive)(void *)) +{ + wait_initialization(); + /* printf("Activate the consumer...\n"); */ + while(cont) + { + int i; + + for( i = 0; i < nb_prod; i++) + { + int cons_idx, prod_idx; + + cons_idx = *tcomms[i].cons_idx; + do + { + prod_idx = *tcomms[i].prod_idx; + for(; cons_idx != prod_idx; cons_idx = (cons_idx + 1) % SHARED_SPACE_VOIDPTR) + { + /* + * The behaviour of this is not documented but we know + * the values inside buf won't change during this affectation + */ + on_receive((void *) tcomms[i].shared_space[cons_idx]); + } + } while (prod_idx != *tcomms[i].prod_idx); + *tcomms[i].cons_idx = cons_idx; + } + } +} diff --git a/communication_techniques/src/fake.c b/communication_techniques/src/fake.c deleted file mode 100644 index a47de81..0000000 --- a/communication_techniques/src/fake.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include -#include - -/* Non standard include */ -#include -#include - - -struct communication_assoc *create_comm_assoc(void) -{ - struct communication_assoc *assoc; - - assoc = (struct communication_assoc *) malloc(sizeof(struct communication_assoc)); - assoc->tid = pthread_self(); - return assoc; -} - -void reception(void (*on_receive)(void *)) -{ - wait_initialization(); - /* printf("Activate the consumer...\n"); */ - while (cont); -} diff --git a/communication_techniques/src/main.c b/communication_techniques/src/main.c index 1cdada4..f080331 100644 --- a/communication_techniques/src/main.c +++ b/communication_techniques/src/main.c @@ -9,72 +9,127 @@ #include #include #include +#include +#include /* Non standards includes */ #include -#include +#include #include -static long nb_cache_lines = 0; -static long nb_prod = 0; -static long size_buf = 1; -static char *calculation_lib = NULL; -static int shared = 0; + +#define toString(x) doStringification(x) +#define doStringification(x) #x +#define WORDS_PER_BUF (BUF_SIZE / sizeof(uintptr_t)) +#define DIV_SEC(secs, div) ((unsigned ) (((unsigned) secs) / (unsigned long) (div))) +#define DIV_USEC(nsecs, nusecs, div) ((unsigned) (((unsigned) (nusecs) + 1000000 * \ + ((unsigned ) (nsecs) % (div))) / (unsigned long) (div))) + + +static long nb_bufs_sent = 0; +long nb_prod = 0; +static int (*init_calc)(int) = NULL; +static void **(*do_calc)(void) = NULL; +static int (*end_calc)(void) = NULL; +static int shared = 0; /* We are not shared by default */ pthread_cond_t cond_cons_has_finished = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex_cons_has_finished = PTHREAD_MUTEX_INITIALIZER; static int consumer_has_finished = 0; static int producers_ended = 0; +static int init_calc_arg = 0; 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" + "-n nb_buffer_sent\t\tNumber of buffer to send to another core\n" + "\t\t\t\tBuffer size is " toString(BUF_SIZE) " bytes\n" + "-p nb_producers\t\t\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"; + "-h\t\t\t\tPrint this help\n" + "-s \t\t\tShare the same L cache or not\n" + "\t\t\t\tIf level is:\n" + "\t\t\t\t\t> 0, then the same L must be shared\n" + "\t\t\t\t\t< 0, then different L must be used\n" + "\t\t\t\t\t= 0, then no constraint is given, only main memory (RAM) is guaranteed to be shared\n" + "-c calculation_libname arg\tLibrary to use for calculation with its argument\n" + "\t\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 do_noinit(int unused) +{ + return 0; +} + +void **do_nocalc(void) +{ + static int an_int, *an_int_ptr = &an_int; + + return (void **) &an_int_ptr; +} + +int do_noend(void) +{ + return 0; +} + int analyse_options(int argc, char *argv[]) { int opt; opterr = 0; - while ((opt = getopt(argc, argv, ":hsc:n:p:b:")) != -1) + while ((opt = getopt(argc, argv, ":hs::c:n:p:")) != -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)) + void *dl_descriptor; + + if (stat(optarg, &file_stat)) { - printf("%s: %s\n", optarg, strerror(errno)); + fprintf(stderr, "%s: %s\n", optarg, strerror(errno)); return -1; } + dl_descriptor = dlopen(optarg, RTLD_LAZY | RTLD_LOCAL); + if (dl_descriptor == NULL) + { + fprintf(stderr, "dlopen error: %s\n", dlerror()); + return -1; + } + init_calc = (int (*)(int)) dlsym(dl_descriptor, "init_calc"); + do_calc = (void ** (*)(void)) dlsym(dl_descriptor, "do_calc"); + end_calc = (int (*)(void)) dlsym(dl_descriptor, "end_calc"); + if ((init_calc == NULL) || (do_calc == NULL) || (end_calc == NULL)) + { + fprintf(stderr, "A symbol cannot be loaded: %s\n", dlerror()); + return -1; + } + if ((optind == argc) || (*argv[optind] == '-')) + { + fprintf(stderr, "Missing argument for -c option\n"); + return -1; + } + { + char *inval; + init_calc_arg = strtol(argv[optind], &inval, 10); + if ((*argv[optind] == '\0') || (*inval != '\0')) + { + fprintf(stderr, "Option '-c' needs also an integer argument\n"); + return -1; + } + if ((init_calc_arg <= 0) || ((init_calc_arg == LONG_MAX) && errno == ERANGE)) + { + fprintf(stderr, "Number of useless loop to be done between 2 send must be" + " between 1 and %ld, both inclusive\n", LONG_MAX); + return -1; + } + } + optind++; } break; case 'h' : @@ -83,13 +138,13 @@ int analyse_options(int argc, char *argv[]) case 'n' : { char *inval; - nb_cache_lines = strtol(optarg, &inval, 10); + nb_bufs_sent = 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)) + if ((nb_bufs_sent <= 0) || ((nb_bufs_sent == 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; @@ -105,7 +160,7 @@ int analyse_options(int argc, char *argv[]) fprintf(stderr, "Option '-p' needs an integer argument\n"); return -1; } - if ((nb_cache_lines <= 0) || ((nb_cache_lines == LONG_MAX) && errno == ERANGE)) + if ((nb_prod <= 0) || ((nb_prod == LONG_MAX) && errno == ERANGE)) { fprintf(stderr, "Number of producers must be between 1 and %ld, both inclusive\n", LONG_MAX); return -1; @@ -113,8 +168,28 @@ int analyse_options(int argc, char *argv[]) } break; case 's' : - shared = 1; - /* TODO: shared L2 cache */ + if ((optind != argc) && (*argv[optind] != '-')) + { + int share_level; + char *inval; + share_level = strtol(argv[optind], &inval, 10); + if ((*argv[optind] == '\0') || (*inval != '\0')) + { + fprintf(stderr, "Option '-p' needs an integer argument\n"); + return -1; + } + if ((share_level == LONG_MIN) || ((share_level == LONG_MAX) && errno == ERANGE)) + { + fprintf(stderr, "Shared memory level must be between %ld and %ld, both inclusive\n", LONG_MIN, LONG_MAX); + return -1; + } + /* TODO: Real management of shared memory level */ + if (share_level <= 0) /* -x: We wan't level x not to be shared; 0 do as we want, only memory is guaranteed to be shared */ + shared = 0; + else + shared = 1; + optind++; + } break; case '?' : fprintf(stderr, "Option inconnue\n"); @@ -127,7 +202,7 @@ int analyse_options(int argc, char *argv[]) return -1; } } - if (!nb_cache_lines) + if (!nb_bufs_sent) { fprintf(stderr, "You must give the number of cache lines to be sent\n"); return -1; @@ -142,16 +217,36 @@ int analyse_options(int argc, char *argv[]) fprintf(stderr, "Too many producers to fit with the consumer in processors which share a same cache\n"); return -1; } + if (do_calc == NULL) + { + init_calc = do_noinit; + do_calc = do_nocalc; + end_calc = do_noend; + } return 0; } -void *producer(void *cont_ptr_void) +void wait_consumer(void) +{ + pthread_mutex_lock(&mutex_cons_has_finished); + if (++producers_ended == nb_prod) + cont = 0; + if (!consumer_has_finished) + pthread_cond_wait(&cond_cons_has_finished, &mutex_cons_has_finished); + pthread_mutex_unlock(&mutex_cons_has_finished); +} + +void *producer(void *unused) { int i, j; - void *k; - volatile int *cont; + struct timeval tv1, tv2, tv_result; - cont = *((volatile int **) cont_ptr_void); + if (init_producer_thread()) + { + fprintf(stderr, "Initialization of thread has failed\n"); + wait_consumer(); + return &nb_prod; /* &nb_prod can't be NULL, whatever NULL is bound to */ + } if (shared) { pthread_t tid; @@ -163,7 +258,8 @@ void *producer(void *cont_ptr_void) if (pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset)) { perror("pthread_setaffinity_np"); - return NULL; + wait_consumer(); + return &nb_prod; /* &nb_prod can't be NULL, whatever NULL is bound to */ } } else @@ -177,33 +273,58 @@ void *producer(void *cont_ptr_void) if (pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset)) { perror("pthread_setaffinity_np"); - return NULL; + wait_consumer(); + return &nb_prod; /* &nb_prod can't be NULL, whatever NULL is bound to */ } } - printf("Registering: %p !\n", (void*) pthread_self()); - add_sender(); - k = cont_ptr_void; + if (init_calc(init_calc_arg)) + { + fprintf(stderr, "Initialization of calculation has failed\n"); + wait_consumer(); + return &nb_prod; /* nb_prod can't be NULL, whatever NULL is bound to */ + } + gettimeofday(&tv1, NULL); 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); + for(i = 0; i < nb_bufs_sent; i++) { + //printf("[%p] Send %d new CACHE_LINE\n", (void *) pthread_self(), BUF_SIZE / CACHE_LINE_SIZE); + for(j = 0; j < WORDS_PER_BUF; j++) + send(do_calc()); } - print_results(); + print_results(WORDS_PER_BUF, nb_bufs_sent); + } + gettimeofday(&tv2, NULL); + tv_result.tv_sec = tv2.tv_sec - tv1.tv_sec; + if (tv2.tv_usec < tv1.tv_usec) + { + tv_result.tv_usec = tv1.tv_usec - tv2.tv_usec; + tv_result.tv_sec--; + } + else + tv_result.tv_usec = tv2.tv_usec - tv1.tv_usec; + printf("total_time: %u.%06u / %u.%06u / %u.%06u\n", (unsigned) tv_result.tv_sec, + (unsigned) tv_result.tv_usec, + DIV_SEC(tv_result.tv_sec, nb_bufs_sent), + DIV_USEC(tv_result.tv_sec, tv_result.tv_usec, nb_bufs_sent), + DIV_SEC(tv_result.tv_sec, nb_bufs_sent * WORDS_PER_BUF), + DIV_USEC(tv_result.tv_sec, tv_result.tv_usec, nb_bufs_sent * WORDS_PER_BUF)); + if (end_calc()) + { + fprintf(stderr, "uninitialization of calculation has failed\n"); + wait_consumer(); + return &nb_prod; /* &nb_prod can't be NULL, whatever NULL is bound to */ } printf("[%p] Producer finished !\n", (void*) pthread_self()); - remove_sender(); /* * When a producer end its thread-local storage vanished. Thus, * producers must finish only after consumer has stopped using them */ - pthread_mutex_lock(&mutex_cons_has_finished); - if (++producers_ended == nb_prod) - *cont = 0; - if (!consumer_has_finished) - pthread_cond_wait(&cond_cons_has_finished, &mutex_cons_has_finished); - pthread_mutex_unlock(&mutex_cons_has_finished); + wait_consumer(); + if (end_producer_thread()) + { + fprintf(stderr, "Uninitialization of thread has failed\n"); + return &nb_prod; /* &nb_prod can't be NULL, whatever NULL is bound to */ + } return NULL; } @@ -238,21 +359,34 @@ void *receptor(void *a) int main(int argc, char *argv[]) { - int i; - volatile int *cont; + int i, global_return_value = EXIT_SUCCESS; void *return_value; pthread_t *tid; if (analyse_options(argc, argv)) return EXIT_FAILURE; + if (init_library()) + return EXIT_FAILURE; tid = (pthread_t *) malloc((nb_prod + 1) * sizeof(pthread_t)); - cont = init_comm(); + if (tid == NULL) + { + fprintf(stderr, "Failed to allocate %lu bytes needed for thread creation\n", (nb_prod + 1) * sizeof(pthread_t)); + return EXIT_FAILURE; + } for(i = 0; i < nb_prod; i++) - pthread_create(&tid[i], NULL, producer, &cont); + 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); + if (return_value != NULL) + global_return_value = EXIT_FAILURE; + } pthread_join(tid[i], &return_value); + if (return_value != NULL) + global_return_value = EXIT_FAILURE; free(tid); - return EXIT_SUCCESS; + if (end_library()) + return EXIT_FAILURE; + return global_return_value; } diff --git a/communication_techniques/src/pipe.c b/communication_techniques/src/pipe.c deleted file mode 100644 index d41b091..0000000 --- a/communication_techniques/src/pipe.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include -#include - -/* Non standard include */ -#include -#include - - -__thread int pipefd[2]; - -struct communication_assoc *create_comm_assoc(void) -{ - struct communication_assoc *assoc; - - pipe(pipefd); - assoc = (struct communication_assoc *) malloc(sizeof(struct communication_assoc)); - assoc->tid = pthread_self(); - assoc->pipefd = pipefd; - return assoc; -} - -void reception(void (*on_receive)(void *)) -{ - wait_initialization(); - /* printf("Activate the consumer...\n"); */ - while(cont) - { - struct communication_assoc *cur; - - discover_new_producers(); - cur = assoc_root.next; - while(cur != &assoc_root) - { - int i; - - for(i = 0; i < BUF_SIZE / sizeof(void *); i++) - { - void *tmp; - read(cur->pipefd[READ_IDX], &tmp, sizeof(void *)); - on_receive(tmp); - } - cur = cur->next; - } - } -} diff --git a/communication_techniques/src/shared_mem.c b/communication_techniques/src/shared_mem.c deleted file mode 100644 index 9e16140..0000000 --- a/communication_techniques/src/shared_mem.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include - -/* Non standard include */ -#include -#include - - -__thread void **shared_space; -__thread volatile int cons_idx = 0; -__thread volatile int prod_idx = 0; - -struct communication_assoc *create_comm_assoc(void) -{ - struct communication_assoc *assoc; - - shared_space = (void **) malloc(SHARED_SPACE_SIZE); - assoc = (struct communication_assoc *) malloc(sizeof(struct communication_assoc)); - assoc->tid = pthread_self(); - assoc->shared_space = shared_space; - assoc->cons_idx = &cons_idx; - assoc->prod_idx = &prod_idx; - return assoc; -} - -void reception(void (*on_receive)(void *)) -{ - wait_initialization(); - /* printf("Activate the consumer...\n"); */ - while(cont) - { - struct communication_assoc *cur; - - discover_new_producers(); - cur = assoc_root.next; - while(cur != &assoc_root) - { - int cons_idx; - - for(cons_idx = *cur->cons_idx; cons_idx != *cur->prod_idx; cons_idx = (cons_idx + 1) % SHARED_SPACE_VOIDPTR, *cur->cons_idx = cons_idx) - { - void *tmp; - tmp = cur->shared_space[cons_idx]; - on_receive(tmp); - } - cur = cur->next; - } - } -} diff --git a/communication_techniques/src/shared_mem_opt.c b/communication_techniques/src/shared_mem_opt.c deleted file mode 100644 index 4b26f34..0000000 --- a/communication_techniques/src/shared_mem_opt.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include - -/* Non standard include */ -#include -#include - - -__thread void **shared_space; -__thread volatile int cons_idx = 0; -__thread volatile int prod_idx = 0; - -struct communication_assoc *create_comm_assoc(void) -{ - struct communication_assoc *assoc; - - shared_space = (void **) malloc(SHARED_SPACE_SIZE); - assoc = (struct communication_assoc *) malloc(sizeof(struct communication_assoc)); - assoc->tid = pthread_self(); - assoc->shared_space = shared_space; - assoc->cons_idx = &cons_idx; - assoc->prod_idx = &prod_idx; - return assoc; -} - -void reception(void (*on_receive)(void *)) -{ - wait_initialization(); - /* printf("Activate the consumer...\n"); */ - while(cont) - { - struct communication_assoc *cur; - - discover_new_producers(); - cur = assoc_root.next; - while(cur != &assoc_root) - { - int cons_idx, prod_idx; - - cons_idx = *cur->cons_idx; - do - { - prod_idx = *cur->prod_idx; - for(; cons_idx != prod_idx; cons_idx = (cons_idx + 1) % SHARED_SPACE_VOIDPTR) - { - void *tmp; - tmp = cur->shared_space[cons_idx]; - on_receive(tmp); - } - } while (prod_idx != *cur->prod_idx); - *cur->cons_idx = cons_idx; - cur = cur->next; - } - } -} diff --git a/papihighlevel b/papihighlevel index 6d51173..16449c5 160000 --- a/papihighlevel +++ b/papihighlevel @@ -1 +1 @@ -Subproject commit 6d5117308f78e2ca984691d4440b6a1aa45857b9 +Subproject commit 16449c571f7363d0a6dc8293df8f0aaec40b492a