When multiple object (.o) files, who include api.h, are linked together into an executable, you might see build errors at lower optimization levels like this: make[1]: Entering directory 'perfbook/CodeSamples/defer' ... cc -g -O0 -Wall -o route_hazptr route_hazptr.c hazptr.c ../lib/random.c -lpthread /usr/bin/ld: /tmp/xxx.o:perfbook/CodeSamples/defer/../api.h:278: multiple definition of `__thread_id_map'; /tmp/xxx.o:perfbook/CodeSamples/defer/../api.h:278: first defined here /usr/bin/ld: /tmp/xxx.o:perfbook/CodeSamples/defer/../api.h:279: multiple definition of `__thread_id_map_mutex'; /tmp/xxx.o:perfbook/CodeSamples/defer/../api.h:279: first defined here ... collect2: error: ld returned 1 exit status make[1]: *** [Makefile:132: route_hazptr] Error 1 This is due exported symbols of: o __thread_id_map[] o __thread_id_map_mutex o thread_id_key o smp_processor_id defined in api.h. Avoid such duplicates by guarding their declarations by "#ifndef SUBOBJ" and put external reference in their #else cases. Take care of HP in hazptr.h similarly. In Makefiles, add recipes for building objects who don't have their own main() with the -DSUBOBJ flag appended. Signed-off-by: Akira Yokosawa <akiyks@xxxxxxxxx> --- CodeSamples/api-pthreads/api-pthreads.h | 14 ++++++++++++++ CodeSamples/datastruct/Issaquah/Makefile | 14 ++++++++++---- CodeSamples/datastruct/hash/Makefile | 7 +++++-- CodeSamples/defer/Makefile | 7 +++++-- CodeSamples/defer/hazptr.h | 6 +++++- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/CodeSamples/api-pthreads/api-pthreads.h b/CodeSamples/api-pthreads/api-pthreads.h index 3e21fdb9..8edbad4e 100644 --- a/CodeSamples/api-pthreads/api-pthreads.h +++ b/CodeSamples/api-pthreads/api-pthreads.h @@ -159,8 +159,14 @@ typedef pthread_t thread_id_t; #define __THREAD_ID_MAP_EMPTY 0 #define __THREAD_ID_MAP_WAITING 1 + +#ifndef SUBOBJ thread_id_t __thread_id_map[NR_THREADS]; spinlock_t __thread_id_map_mutex; +#else +extern thread_id_t __thread_id_map[NR_THREADS]; +extern spinlock_t __thread_id_map_mutex; +#endif #define for_each_thread(t) \ for (t = 0; t < NR_THREADS; t++) @@ -175,7 +181,11 @@ spinlock_t __thread_id_map_mutex; if ((((tid) = __thread_id_map[t]) != __THREAD_ID_MAP_EMPTY) && \ ((tid) != __THREAD_ID_MAP_WAITING)) +#ifndef SUBOBJ pthread_key_t thread_id_key; +#else +extern pthread_key_t thread_id_key; +#endif static __inline__ int num_online_threads(void) { @@ -368,7 +378,11 @@ static __inline__ long long get_microseconds(void) } __per_cpu_##name[NR_CPUS] #define DECLARE_PER_CPU(type, name) extern DEFINE_PER_CPU(type, name) +#ifndef SUBOBJ DEFINE_PER_THREAD(int, smp_processor_id); +#else +DECLARE_PER_THREAD(int, smp_processor_id); +#endif static __inline__ int smp_processor_id(void) { diff --git a/CodeSamples/datastruct/Issaquah/Makefile b/CodeSamples/datastruct/Issaquah/Makefile index 6a51ff90..ca379b3e 100644 --- a/CodeSamples/datastruct/Issaquah/Makefile +++ b/CodeSamples/datastruct/Issaquah/Makefile @@ -45,11 +45,17 @@ LURCU_SIG := $(shell pkg-config --libs liburcu-signal 2>/dev/null) # -DUSE_JEMALLOC # Verify by using the nm command and searching output for malloc. -existence_test: existence.c existence_test.c - cc $(GCC_ARGS) -o existence_test existence.c existence_test.c -lpthread -lurcu $(LURCU_SIG) +existence_sub.o: existence.c existence.h ../../api.h + cc $(GCC_ARGS) -o existence_sub.o -c -DSUBOBJ existence.c -treetorture: tree.c existence.c spinlockmult.c $(LIB)/random.c ../../api.h treetorture.h treetorturetrace.h $(LIB)/random.h existence.h tree.h - cc $(GCC_ARGS) -o treetorture tree.c existence.c spinlockmult.c $(LIB)/random.c -lpthread -lurcu $(LURCU_SIG) +existence_test: existence_sub.o existence_test.c ../../api.h + cc $(GCC_ARGS) -o existence_test existence_sub.o existence_test.c -lpthread -lurcu $(LURCU_SIG) + +spinlockmult_sub.o: spinlockmult.c spinlockmult.h ../../api.h + cc $(GCC_ARGS) -o spinlockmult_sub.o -c -DSUBOBJ spinlockmult.c + +treetorture: tree.c existence_sub.o spinlockmult_sub.o $(LIB)/random.c ../../api.h treetorture.h treetorturetrace.h $(LIB)/random.h existence.h tree.h + cc $(GCC_ARGS) -o treetorture tree.c existence_sub.o spinlockmult_sub.o $(LIB)/random.c -lpthread -lurcu $(LURCU_SIG) clean: rm -f $(PROGS) diff --git a/CodeSamples/datastruct/hash/Makefile b/CodeSamples/datastruct/hash/Makefile index 7f244e09..5f3d740c 100644 --- a/CodeSamples/datastruct/hash/Makefile +++ b/CodeSamples/datastruct/hash/Makefile @@ -47,8 +47,11 @@ hash_bkt_qsbr: hash_bkt_rcu.c ../../api.h hashtorture.h hash_bkt_rcu: hash_bkt_rcu.c ../../api.h hashtorture.h cc $(GCC_ARGS) -DTEST_HASH -o hash_bkt_rcu hash_bkt_rcu.c $(LIB)/random.c -lpthread -lurcu $(LURCU_SIG) -hash_bkt_hazptr: hash_bkt_hazptr.c ../../defer/hazptr.c ../../defer/hazptr.h ../../api.h hashtorture.h - cc $(GCC_ARGS) -DTEST_HASH -o hash_bkt_hazptr hash_bkt_hazptr.c ../../defer/hazptr.c $(LIB)/random.c -lpthread +../../defer/hazptr_sub.o: ../../defer/hazptr.c ../../defer/hazptr.h ../../api.h + $(MAKE) -C ../../defer hazptr_sub.o + +hash_bkt_hazptr: hash_bkt_hazptr.c ../../defer/hazptr_sub.o ../../api.h hashtorture.h + cc $(GCC_ARGS) -DTEST_HASH -o hash_bkt_hazptr hash_bkt_hazptr.c ../../defer/hazptr_sub.o $(LIB)/random.c -lpthread hash_global: hash_global.c ../../api.h hashtorture.h cc $(GCC_ARGS) -DTEST_HASH -o hash_global hash_global.c $(LIB)/random.c -lpthread diff --git a/CodeSamples/defer/Makefile b/CodeSamples/defer/Makefile index abfbe202..0cb77122 100644 --- a/CodeSamples/defer/Makefile +++ b/CodeSamples/defer/Makefile @@ -128,8 +128,11 @@ rcu_sig: rcu_sig.c rcu_sig.h ../api.h rcutorture.h rcu_ts: rcu_ts.c rcu_ts.h ../api.h rcutorture.h cc $(GCC_ARGS) -o rcu_ts -DTEST rcu_ts.c -lpthread -route_hazptr: route_hazptr.c hazptr.c hazptr.h ../api.h ../lib/random.h ../lib/random.c routetorture.h - cc $(GCC_ARGS) -o route_hazptr route_hazptr.c hazptr.c ../lib/random.c -lpthread +hazptr_sub.o: hazptr.c hazptr.h ../api.h + cc $(GCC_ARGS) -o hazptr_sub.o -c -DSUBOBJ hazptr.c + +route_hazptr: route_hazptr.c hazptr_sub.o ../api.h ../lib/random.h ../lib/random.c routetorture.h + cc $(GCC_ARGS) -o route_hazptr route_hazptr.c hazptr_sub.o ../lib/random.c -lpthread route_rcu: route_rcu.c ../api.h ../lib/random.h ../lib/random.c routetorture.h cc $(GCC_ARGS) -o route_rcu route_rcu.c ../lib/random.c -lpthread -lurcu $(LURCU_SIG) diff --git a/CodeSamples/defer/hazptr.h b/CodeSamples/defer/hazptr.h index e061303d..bdeb5c15 100644 --- a/CodeSamples/defer/hazptr.h +++ b/CodeSamples/defer/hazptr.h @@ -52,8 +52,12 @@ typedef struct hazard_pointer_s { } hazard_pointer; /* Must be dynamically initialized to be an array of size H. */ +#ifndef SUBOBJ hazard_pointer *HP; - +#else +extern hazard_pointer *HP; +#endif + void hazptr_init(void); void hazptr_thread_exit(void); void hazptr_scan(); -- 2.34.1