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 <[email protected]>
---
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