Skip to contentSkip to conversation

CodeSamples: Cleanups and fixes

RFC PATCH Superseded Akira Yokosawa 3 participants 18 messages May 29, 2017 – Jun 1, 2017

lore
Share & tools
lore
#0 lore raw

cover CodeSamples: Cleanups and fixes

From fd5fb9afb6b99b15370a9823b42fa2a92342b92a Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 06:52:40 +0900
Subject: [RFC PATCH 0/4] CodeSamples: Cleanups and fixes

Hi Paul,

While I was looking around CodeSamples, I encountered several warnings in build and an infinite loop in one of sample codes. Also, I found that CodeSamples/api.h and CodeSamples/Makefile.arch can be removed from repository if their recipe are properly written in Makefiles.

Patch 1 adds rules to generate Makefile.arch and api.h that suit the architecture of you host. As I don't have ppc64 or arm host environment, I tested it only on x86_32 and x86_64. I'd like to know if it works on ppc64 and arm.

Patch 2 removes the redundant files.

Patch 3 and 4 are fixes of warnings and infinite loops.

Thoughts?

Thanks, Akira

Signature · 35 lines
Akira Yokosawa (4):
  CodeSamples: Add rule to generate Makefile.arch and api.h
  CodeSamples: Remove generated files from repository
  CodeSamples: Use 'intptr_t' to be compatible with 'void *'
  CodeSamples/defer: Add compiler barriers in gettimestampmp.c

 CodeSamples/.gitignore                         |   4 +-
 CodeSamples/Makefile                           |  18 +
 CodeSamples/Makefile.arch                      |   6 -
 CodeSamples/SMPdesign/Makefile                 |   3 +
 CodeSamples/SMPdesign/matmul.c                 |  13 +-
 CodeSamples/SMPdesign/smpalloc.c               |  11 +-
 CodeSamples/advsync/Makefile                   |   3 +
 CodeSamples/api.h                              | 808 -------------------------
 CodeSamples/count/Makefile                     |   3 +
 CodeSamples/datastruct/Issaquah/Makefile       |   3 +
 CodeSamples/datastruct/Issaquah/existence_test | Bin 26359 -> 0 bytes
 CodeSamples/datastruct/hash/Makefile           |   3 +
 CodeSamples/datastruct/log/Makefile            |   3 +
 CodeSamples/datastruct/skiplist/Makefile       |   3 +
 CodeSamples/defer/Makefile                     |   3 +
 CodeSamples/defer/gettimestampmp.c             |   5 +-
 CodeSamples/depends.mk                         |  43 ++
 CodeSamples/intro/Makefile                     |   3 +
 CodeSamples/intro/threadcreate.c               |   7 +-
 CodeSamples/locking/Makefile                   |   3 +
 CodeSamples/toolsoftrade/Makefile              |   3 +
 21 files changed, 117 insertions(+), 831 deletions(-)
 delete mode 100644 CodeSamples/Makefile.arch
 delete mode 100644 CodeSamples/api.h
 delete mode 100755 CodeSamples/datastruct/Issaquah/existence_test
 create mode 100644 CodeSamples/depends.mk

-- 
2.7.4
#1 lore raw

RFC PATCH 1/4 CodeSamples: Add rule to generate Makefile.arch and api.h

From b4845ac3b17aaade7258528fa114def5f6554242 Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Sun, 28 May 2017 09:29:44 +0900
Subject: [RFC PATCH 1/4] CodeSamples: Add rule to generate Makefile.arch and api.h

To generate suitable Makefile.arch and api.h for host arch, describe the dependency in depends.mk and include it in Makefiles.

---
 CodeSamples/Makefile                     | 18 +++++++++++++
 CodeSamples/SMPdesign/Makefile           |  3 +++
 CodeSamples/advsync/Makefile             |  3 +++
 CodeSamples/count/Makefile               |  3 +++
 CodeSamples/datastruct/Issaquah/Makefile |  3 +++
 CodeSamples/datastruct/hash/Makefile     |  3 +++
 CodeSamples/datastruct/log/Makefile      |  3 +++
 CodeSamples/datastruct/skiplist/Makefile |  3 +++
 CodeSamples/defer/Makefile               |  3 +++
 CodeSamples/depends.mk                   | 43 ++++++++++++++++++++++++++++++++
 CodeSamples/intro/Makefile               |  3 +++
 CodeSamples/locking/Makefile             |  3 +++
 CodeSamples/toolsoftrade/Makefile        |  3 +++
 13 files changed, 94 insertions(+)
 create mode 100644 CodeSamples/depends.mk
CodeSamples/Makefile +18 -0
index f5461e9..4168220 100644
@@ -1,3 +1,7 @@
+.PHONY: all clean pthreads pthreads-x86 pthreads-ppc64 pthreads-arm
+
+top := .
+
 all:
 	(cd SMPdesign; make)
 	(cd advsync; make)
@@ -6,6 +10,17 @@ all:
 	(cd intro; make)
 	(cd toolsoftrade; make)
 
+include depends.mk
+
+api.h Makefile.arch:
+ifeq ($(strip $(target)),)
+	make pthreads
+	$(warning "Could not figure out which target to use (arch:$(arch)).\
+		   Used 'make pthreads' in CodeSamples/Makefile.")
+else
+	make pthreads-$(target)
+endif
+
 pthreads:
 	echo "#ifndef __PERFBOOK_API_H__" > api.h
 	echo "#define __PERFBOOK_API_H__" >> api.h
@@ -125,3 +140,6 @@ pthreads-arm:
 	echo "#endif /* #ifndef __PERFBOOK_API_H__ */" >> api.h
 	echo "# MECHANICALLY GENERATED, DO NOT EDIT!!!" > Makefile.arch
 	cat arch-arm/Makefile.arch >> Makefile.arch
+
+clean:
+	rm -f Makefile.arch api.h
CodeSamples/SMPdesign/Makefile +3 -0
index ae0cdd7..d03575c 100644
@@ -25,6 +25,9 @@ include ../Makefile.arch
 # http://www.ibm.com/developerworks/wikis/display/hpccentral/Tuning+options+to+consider+with+gcc#Tuningoptionstoconsiderwithgcc-mcpuandmtune
 # GCC_ARGS=-g -O3 -m64 -mcpu=power5 -mtune=power5
 
+top := ..
+include $(top)/depends.mk
+
 smpalloc: smpalloc.c ../api.h
 	cc $(GCC_ARGS) -g -o smpalloc -DTEST smpalloc.c -lpthread
 
CodeSamples/advsync/Makefile +3 -0
index b02ca37..bb4c8fc 100644
@@ -20,6 +20,9 @@ PROGS =	q singleq wfenqueue
 
 all: $(PROGS)
 
+top := ..
+include $(top)/depends.mk
+
 q: q.c q.h queuetorture.h ../api.h
 	cc $(GCC_ARGS) -o q -DTEST q.c -lpthread
 
CodeSamples/count/Makefile +3 -0
index 05fcf04..d3fbb83 100644
@@ -35,6 +35,9 @@ RCU_SRCS = ../defer/rcu_nest32.h ../defer/rcu_nest32.c
 
 all: $(PROGS)
 
+top := ..
+include $(top)/depends.mk
+
 count_atomic: count_atomic.c ../api.h counttorture.h
 	cc $(GCC_ARGS) $(CFLAGS) -o count_atomic count_atomic.c -lpthread
 
CodeSamples/datastruct/Issaquah/Makefile +3 -0
index 013738c..bb3d6a3 100644
@@ -21,6 +21,9 @@ LIB = ../../lib
 
 all: $(PROGS)
 
+top := ../..
+include $(top)/depends.mk
+
 # NOTE:  For decent scalability on update-side tests as of early 2015,
 #	 use something like jemalloc() instead of glibc malloc().
 #	 If you install jemalloc at /home/paulmck/jemalloc, you will
CodeSamples/datastruct/hash/Makefile +3 -0
index a87bdbb..85dfa5d 100644
@@ -20,6 +20,9 @@ PROGS =	hash_bkt hash_bkt_hazptr hash_bkt_rcu hash_global hash_resize
 
 all: $(PROGS)
 
+top := ../..
+include $(top)/depends.mk
+
 hash_bkt: hash_bkt.c ../../api.h hashtorture.h
 	cc $(GCC_ARGS) -DTEST_HASH -o hash_bkt hash_bkt.c -lpthread
 
CodeSamples/datastruct/log/Makefile +3 -0
index f225c92..cd2c571 100644
@@ -21,6 +21,9 @@ LIB = ../../lib
 
 all: $(PROGS)
 
+top := ../..
+include $(top)/depends.mk
+
 log_glock: log_glock.c ../../api.h logtorture.h log.h
 	cc $(GCC_ARGS) -DTEST_LOG -I $(LIB) -g -o log_glock log_glock.c $(LIB)/random.c -lpthread
 
CodeSamples/datastruct/skiplist/Makefile +3 -0
index 7289979..ab6f524 100644
@@ -21,6 +21,9 @@ LIB = ../../lib
 
 all: $(PROGS)
 
+top := ../..
+include $(top)/depends.mk
+
 skiplist: skiplist.c ../../api.h skiplisttorture.h skiplist.h
 	cc $(GCC_ARGS) -DTEST_SKIPLIST -I $(LIB) -g -o skiplist skiplist.c $(LIB)/random.c -lpthread -lurcu -lurcu-signal
 
CodeSamples/defer/Makefile +3 -0
index 35db164..5e0f1e7 100644
@@ -46,6 +46,9 @@ PROGS =	bug_rcu_dp \
 
 all: $(PROGS)
 
+top := ..
+include $(top)/depends.mk
+
 # Note that bug_srcu_a is disabled until completed.
 bug_srcu_a: bug_srcu_a.c srcu.c ../api.h
 	cc $(GCC_ARGS) -o bug_srcu_a -DTEST bug_srcu_a.c -lurcu -lpthread
CodeSamples/depends.mk new file +43 -0

43 lines not on this page · raw message

CodeSamples/intro/Makefile +3 -0
index e323834..ba2f257 100644
@@ -2,6 +2,9 @@ PROGS = initrace initraceperf lockinc nakedinc perthreadinc threadcreate
 
 all: $(PROGS)
 
+top := ..
+include $(top)/depends.mk
+
 initrace: initrace.c ../api.h
 	cc -g -Wall -o initrace initrace.c -lpthread
 
CodeSamples/locking/Makefile +3 -0
index 15cf8f1..5862448 100644
@@ -2,6 +2,9 @@ PROGS = locked_list xchglock
 
 all: $(PROGS)
 
+top := ..
+include $(top)/depends.mk
+
 locked_list: locked_list.c ../api.h
 	cc -g -Wall -o locked_list locked_list.c
 
CodeSamples/toolsoftrade/Makefile +3 -0
index 4b7f219..b6216e8 100644
@@ -26,6 +26,9 @@ PROGS =	forkjoin \
 
 all: $(PROGS)
 
+top := ..
+include $(top)/depends.mk
+
 forkjoin: forkjoin.c ../api.h
 	cc $(GCC_ARGS) -o forkjoin forkjoin.c
 
Signature · 1 line
2.7.4
#2 lore raw

RFC PATCH 2/4 CodeSamples: Remove generated files from repository

In reply to Akira Yokosawa

From 10024f2b41c129e5e7e892c60946c8dd5dd58007 Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Sun, 28 May 2017 09:40:21 +0900
Subject: [RFC PATCH 2/4] CodeSamples: Remove generated files from repository

Now, as Makefile.arch and api.h are generated when necessary, they are no longer necessary in the repository.

Also fix entry for gprof-helper.c in .gitignore and remove an executable file sneaked into repository under datastruct/Issaquah/.

---
 CodeSamples/.gitignore                         |   4 +-
 CodeSamples/Makefile.arch                      |   6 -
 CodeSamples/api.h                              | 808 -------------------------
 CodeSamples/datastruct/Issaquah/existence_test | Bin 26359 -> 0 bytes
 4 files changed, 3 insertions(+), 815 deletions(-)
 delete mode 100644 CodeSamples/Makefile.arch
 delete mode 100644 CodeSamples/api.h
 delete mode 100755 CodeSamples/datastruct/Issaquah/existence_test
CodeSamples/.gitignore +3 -1
index 9e3642f..e116055 100644
@@ -1 +1,3 @@
-./gprof-helper.c
+/gprof-helper.c
+/Makefile.arch
+/api.h
CodeSamples/Makefile.arch deleted +0 -6
deleted file mode 100644
index 07a4b33..0000000
@@ -1,6 +0,0 @@
-# MECHANICALLY GENERATED, DO NOT EDIT!!!
-
-# For use on 64-bit systems, add -m32.  You might also need to install
-# g++-multilib (thanks to [email protected]).
-
-GCC_ARGS=-g -O3 -Wall
CodeSamples/api.h deleted +0 -808

808 lines not on this page · raw message

CodeSamples/datastruct/Issaquah/existence_test deleted binary +0 -0
deleted file mode 100755
index a3ef38115581c15944e82e5d57ddc86e8da4afb9..0000000000000000000000000000000000000000
GIT binary patch
Signature · 1 line
2.7.4
#3 lore raw

RFC PATCH 3/4 CodeSamples: Use 'intptr_t' to be compatible with 'void *'

In reply to Akira Yokosawa

From e325a5ff132d8e4a79dfe465b18f573b97da75db Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Sun, 28 May 2017 12:38:27 +0900
Subject: [RFC PATCH 3/4] CodeSamples: Use 'intptr_t' to be compatible with 'void *'

On x86_64, casting between "int" and "void *" in threadcreate.c causes GCC to emit warnings such as:

warning: cast from pointer to integer of different size
warning: cast from integer to pointer of different size

Let's adopt C99 way of writing portable code.

Also do the same changes where appropriate. (Other than threadcreate.c, no warnings were observed on x86_64, but we can remove a few casts to "long".)

---
 CodeSamples/SMPdesign/matmul.c     | 13 +++++++------
 CodeSamples/SMPdesign/smpalloc.c   | 11 ++++++-----
 CodeSamples/defer/gettimestampmp.c |  2 +-
 CodeSamples/intro/threadcreate.c   |  7 ++++---
 4 files changed, 18 insertions(+), 15 deletions(-)
CodeSamples/SMPdesign/matmul.c +7 -6
index 6a07730..9f0b250 100644
@@ -18,12 +18,13 @@
  * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
  */
 
+#include <inttypes.h>
 #include "../api.h"
 
 float *a;
 float *b;
 float *c;
-long dim = 1000;
+intptr_t dim = 1000;
 int nthread = 1;
 
 #define GOFLAG_INIT     0
@@ -38,8 +39,8 @@ atomic_t nstarted;
 
 void *matmul_thread(void *me_in)
 {
-	long me = (long)me_in;
-	int i, j, k;
+	intptr_t me = (intptr_t)me_in;
+	intptr_t i, j, k;
 
 	atomic_inc(&nstarted);
 	while (goflag == GOFLAG_INIT)
@@ -58,7 +59,7 @@ void *matmul_thread(void *me_in)
 
 int main(int argc, char *argv[])
 {
-	int i, j;
+	intptr_t i, j;
 	long long startcreatetime;
 	long long starttime;
 	long long endtime;
@@ -87,7 +88,7 @@ int main(int argc, char *argv[])
 	goflag = GOFLAG_INIT;
 	startcreatetime = get_microseconds();
 	for (i = 0; i < nthread; i++)
-		create_thread(matmul_thread, (void *)(long)i);
+		create_thread(matmul_thread, (void *)i);
 	while (atomic_read(&nstarted) != nthread)
 		barrier();
 	starttime = get_microseconds();
@@ -95,7 +96,7 @@ int main(int argc, char *argv[])
 	while (atomic_read(&ndone) != nthread)
 		poll(NULL, 0, 1);
 	endtime = get_microseconds();
-	printf("dim = %ld, nthread = %d, duration = %lld : %lld us\n",
+	printf("dim = %" PRIdPTR ", nthread = %d, duration = %lld : %lld us\n",
 	       dim, nthread, endtime - startcreatetime, endtime - starttime);
 	return 0;
 }
CodeSamples/SMPdesign/smpalloc.c +6 -5
index 95b21a1..0882f63 100644
@@ -19,6 +19,7 @@
  * Copyright (c) 2006 Paul E. McKenney, IBM Corporation.
  */
 
+#include <inttypes.h>
 #include "../api.h"
 
 #define TARGET_POOL_SIZE 3
@@ -123,7 +124,7 @@ void *memblock_test(void *arg)
 	long cnt = 0;
 	long cntfail = 0;
 	int i;
-	int runlength = (int)(long)arg;
+	intptr_t runlength = (intptr_t)arg;
 	struct memblock *p[MAX_RUN];
 
 	if (runlength > MAX_RUN)
@@ -159,7 +160,7 @@ int main(int argc, char *argv[])
 	long long nc;
 	long long nf;
 	int nkids = 1;
-	int runlength = 1;
+	intptr_t runlength = 1;
 	int totbefore;
 
 	smp_init();
@@ -176,12 +177,12 @@ int main(int argc, char *argv[])
 	if (argc > 2) {
 		runlength = strtoul(argv[2], NULL, 0);
 		if (runlength > MAX_RUN) {
-			fprintf(stderr, "nkids = %d too large, max = %d\n",
+			fprintf(stderr, "nkids = %" PRIdPTR " too large, max = %d\n",
 				runlength, MAX_RUN);
 			usage(argv[0]);
 		}
 	}
-	printf("%d %d ", nkids, runlength);
+	printf("%d %" PRIdPTR, nkids, runlength);
 
 	init_per_thread(results, 0L);
 	init_per_thread(failures, 0L);
@@ -189,7 +190,7 @@ int main(int argc, char *argv[])
 
 	goflag = 1;
 	for (i = 0; i < nkids; i++)
-		create_thread(memblock_test, (void *)(long)runlength);
+		create_thread(memblock_test, (void *)runlength);
 
 	sleep(1);
 	goflag = 0;
CodeSamples/defer/gettimestampmp.c +1 -1
index bc0b9ea..e794e82 100644
@@ -29,7 +29,7 @@ long curtimestamp = 0;
 
 void *collect_timestamps(void *mask_in)
 {
-	long mask = (long)mask_in;
+	intptr_t mask = (intptr_t)mask_in;
 
 	while (curtimestamp < MAX_TIMESTAMPS) {
 		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
CodeSamples/intro/threadcreate.c +4 -3
index 26b7ba9..470bb11 100644
@@ -18,13 +18,14 @@
  * Copyright (c) 2006 Paul E. McKenney, IBM Corporation.
  */
 
+#include <inttypes.h>
 #include "../api.h"
 
 void *thread_test(void *arg)
 {
-	int myarg = (int)arg;
+	intptr_t myarg = (intptr_t)arg;
 
-	printf("child thread %d: smp_thread_id() = %d\n",
+	printf("child thread %" PRIdPTR ": smp_thread_id() = %d\n",
 	       myarg, smp_thread_id());
 	return NULL;
 }
@@ -38,7 +39,7 @@ void usage(char *progname)
 
 int main(int argc, char *argv[])
 {
-	int i;
+	intptr_t i;
 	int nkids = 1;
 
 	smp_init();
Signature · 1 line
2.7.4
#4 lore raw

Re: [RFC PATCH 3/4] CodeSamples: Use 'intptr_t' to be compatible with 'void *'

Quoted 31 lines · Akira Yokosawa
Quoted 1 line

From e325a5ff132d8e4a79dfe465b18f573b97da75db Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Sun, 28 May 2017 12:38:27 +0900
Subject: [RFC PATCH 3/4] CodeSamples: Use 'intptr_t' to be compatible with 'void *'

On x86_64, casting between "int" and "void *" in threadcreate.c causes GCC to emit warnings such as:

warning: cast from pointer to integer of different size
warning: cast from integer to pointer of different size

Let's adopt C99 way of writing portable code.

Also do the same changes where appropriate. (Other than threadcreate.c, no warnings were observed on x86_64, but we can remove a few casts to "long".)

---
 CodeSamples/SMPdesign/matmul.c     | 13 +++++++------
 CodeSamples/SMPdesign/smpalloc.c   | 11 ++++++-----
 CodeSamples/defer/gettimestampmp.c |  2 +-
 CodeSamples/intro/threadcreate.c   |  7 ++++---
 4 files changed, 18 insertions(+), 15 deletions(-)
CodeSamples/SMPdesign/matmul.c +0 -0
index 6a07730..9f0b250 100644
@@ -18,12 +18,13 @@
  * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.

CodeSamples/SMPdesign/matmul.c line 27

Quoted 10 lines
CodeSamples/SMPdesign/matmul.c +2 -1
  */
 
+#include <inttypes.h>
 #include "../api.h"
 
 float *a;
 float *b;
 float *c;
-long dim = 1000;
+intptr_t dim = 1000;

This really is an int, used only for array index calculations. I don't see how it helps to make it be an intptr_t. What am I missing?

CodeSamples/SMPdesign/matmul.c atomic_t nstarted; · line 43

Quoted 11 lines
CodeSamples/SMPdesign/matmul.c +2 -2
 int nthread = 1;
 
 #define GOFLAG_INIT     0
@@ -38,8 +39,8 @@ atomic_t nstarted;
 
 void *matmul_thread(void *me_in)
 {
-	long me = (long)me_in;
-	int i, j, k;
+	intptr_t me = (intptr_t)me_in;
+	intptr_t i, j, k;

Hmmm... Now "me" is a long and used as such, but the conversion from a pointer on 32-bit systems could get warnings on some systems. But it is guaranteed to be a small integer. Would something like this work?

	int me = (int)(long)me_in;

Or this?

	int me = (intptr_t)me_in;

Or even this?

	int me = ((intptr_t)me_in) & 0xffffffff;

I suppose that the painfully correct way to do this would be to pass in a pointer to a structure containing a lone int. Any other approaches that work?

The variables i, j, and k, like dim, are used only as int to compute array indexes.

I have similar concerns about the remaining cases. I am not inalterably opposed, but it seems better to keep intptr_t usage more confined.

Thanx, Paul

Quoted 135 lines
CodeSamples/SMPdesign/matmul.c +3 -3
 	atomic_inc(&nstarted);
 	while (goflag == GOFLAG_INIT)
@@ -58,7 +59,7 @@ void *matmul_thread(void *me_in)
 
 int main(int argc, char *argv[])
 {
-	int i, j;
+	intptr_t i, j;
 	long long startcreatetime;
 	long long starttime;
 	long long endtime;
@@ -87,7 +88,7 @@ int main(int argc, char *argv[])
 	goflag = GOFLAG_INIT;
 	startcreatetime = get_microseconds();
 	for (i = 0; i < nthread; i++)
-		create_thread(matmul_thread, (void *)(long)i);
+		create_thread(matmul_thread, (void *)i);
 	while (atomic_read(&nstarted) != nthread)
 		barrier();
 	starttime = get_microseconds();
@@ -95,7 +96,7 @@ int main(int argc, char *argv[])
 	while (atomic_read(&ndone) != nthread)
 		poll(NULL, 0, 1);
 	endtime = get_microseconds();
-	printf("dim = %ld, nthread = %d, duration = %lld : %lld us\n",
+	printf("dim = %" PRIdPTR ", nthread = %d, duration = %lld : %lld us\n",
 	       dim, nthread, endtime - startcreatetime, endtime - starttime);
 	return 0;
 }
CodeSamples/SMPdesign/smpalloc.c +6 -5
index 95b21a1..0882f63 100644
@@ -19,6 +19,7 @@
  * Copyright (c) 2006 Paul E. McKenney, IBM Corporation.
  */
 
+#include <inttypes.h>
 #include "../api.h"
 
 #define TARGET_POOL_SIZE 3
@@ -123,7 +124,7 @@ void *memblock_test(void *arg)
 	long cnt = 0;
 	long cntfail = 0;
 	int i;
-	int runlength = (int)(long)arg;
+	intptr_t runlength = (intptr_t)arg;
 	struct memblock *p[MAX_RUN];
 
 	if (runlength > MAX_RUN)
@@ -159,7 +160,7 @@ int main(int argc, char *argv[])
 	long long nc;
 	long long nf;
 	int nkids = 1;
-	int runlength = 1;
+	intptr_t runlength = 1;
 	int totbefore;
 
 	smp_init();
@@ -176,12 +177,12 @@ int main(int argc, char *argv[])
 	if (argc > 2) {
 		runlength = strtoul(argv[2], NULL, 0);
 		if (runlength > MAX_RUN) {
-			fprintf(stderr, "nkids = %d too large, max = %d\n",
+			fprintf(stderr, "nkids = %" PRIdPTR " too large, max = %d\n",
 				runlength, MAX_RUN);
 			usage(argv[0]);
 		}
 	}
-	printf("%d %d ", nkids, runlength);
+	printf("%d %" PRIdPTR, nkids, runlength);
 
 	init_per_thread(results, 0L);
 	init_per_thread(failures, 0L);
@@ -189,7 +190,7 @@ int main(int argc, char *argv[])
 
 	goflag = 1;
 	for (i = 0; i < nkids; i++)
-		create_thread(memblock_test, (void *)(long)runlength);
+		create_thread(memblock_test, (void *)runlength);
 
 	sleep(1);
 	goflag = 0;
CodeSamples/defer/gettimestampmp.c +1 -1
index bc0b9ea..e794e82 100644
@@ -29,7 +29,7 @@ long curtimestamp = 0;
 
 void *collect_timestamps(void *mask_in)
 {
-	long mask = (long)mask_in;
+	intptr_t mask = (intptr_t)mask_in;
 
 	while (curtimestamp < MAX_TIMESTAMPS) {
 		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
CodeSamples/intro/threadcreate.c +4 -3
index 26b7ba9..470bb11 100644
@@ -18,13 +18,14 @@
  * Copyright (c) 2006 Paul E. McKenney, IBM Corporation.
  */
 
+#include <inttypes.h>
 #include "../api.h"
 
 void *thread_test(void *arg)
 {
-	int myarg = (int)arg;
+	intptr_t myarg = (intptr_t)arg;
 
-	printf("child thread %d: smp_thread_id() = %d\n",
+	printf("child thread %" PRIdPTR ": smp_thread_id() = %d\n",
 	       myarg, smp_thread_id());
 	return NULL;
 }
@@ -38,7 +39,7 @@ void usage(char *progname)
 
 int main(int argc, char *argv[])
 {
-	int i;
+	intptr_t i;
 	int nkids = 1;
 
 	smp_init();
Signature · 7 lines
2.7.4


--
To unsubscribe from this list: send the line "unsubscribe perfbook" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#5 lore raw

RFC PATCH 4/4 CodeSamples/defer: Add compiler barriers in gettimestampmp.c

In reply to Akira Yokosawa

From fd5fb9afb6b99b15370a9823b42fa2a92342b92a Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Sun, 28 May 2017 15:42:45 +0900
Subject: [RFC PATCH 4/4] CodeSamples/defer: Add compiler barriers in gettimestampmp.c

They ensure curtimestamp is read and written once in every iteration.

---
 CodeSamples/defer/gettimestampmp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
CodeSamples/defer/gettimestampmp.c +2 -1
index e794e82..7012caa 100644
@@ -32,7 +32,7 @@ void *collect_timestamps(void *mask_in)
 	intptr_t mask = (intptr_t)mask_in;
 
 	while (curtimestamp < MAX_TIMESTAMPS) {
-		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
+		while ((READ_ONCE(curtimestamp) & CURTIMESTAMP_MASK) != mask)
 			continue;
 		if (curtimestamp >= MAX_TIMESTAMPS)
 			break;
@@ -40,6 +40,7 @@ void *collect_timestamps(void *mask_in)
 		/* Don't need memory barrier -- no other shared vars!!! */
 
 		ts[curtimestamp++] = get_timestamp();
+		barrier();
 	}
 	smp_mb();
 	return (NULL);
Signature · 1 line
2.7.4
#6 lore raw

Re: [RFC PATCH 4/4] CodeSamples/defer: Add compiler barriers in gettimestampmp.c

Quoted 9 lines · Akira Yokosawa
Quoted 1 line

From fd5fb9afb6b99b15370a9823b42fa2a92342b92a Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Sun, 28 May 2017 15:42:45 +0900
Subject: [RFC PATCH 4/4] CodeSamples/defer: Add compiler barriers in gettimestampmp.c

They ensure curtimestamp is read and written once in every iteration.

I was actually more or less OK with this one, but it does not apply cleanly without 3/4.

Nevertheless, given that it needs change anyway, would it be better to replace the ++ with a WRITE_ONCE and capture the value in the "while" expression?

Thanx, Paul

Quoted 29 lines
---
 CodeSamples/defer/gettimestampmp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
CodeSamples/defer/gettimestampmp.c +2 -1
index e794e82..7012caa 100644
@@ -32,7 +32,7 @@ void *collect_timestamps(void *mask_in)
 	intptr_t mask = (intptr_t)mask_in;
 
 	while (curtimestamp < MAX_TIMESTAMPS) {
-		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
+		while ((READ_ONCE(curtimestamp) & CURTIMESTAMP_MASK) != mask)
 			continue;
 		if (curtimestamp >= MAX_TIMESTAMPS)
 			break;
@@ -40,6 +40,7 @@ void *collect_timestamps(void *mask_in)
 		/* Don't need memory barrier -- no other shared vars!!! */
 
 		ts[curtimestamp++] = get_timestamp();
+		barrier();
 	}
 	smp_mb();
 	return (NULL);
Signature · 1 line
2.7.4
#7 lore raw
In reply to Akira Yokosawa
Quoted 13 lines · Akira Yokosawa
Quoted 1 line

From fd5fb9afb6b99b15370a9823b42fa2a92342b92a Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 06:52:40 +0900
Subject: [RFC PATCH 0/4] CodeSamples: Cleanups and fixes

Hi Paul,

While I was looking around CodeSamples, I encountered several warnings in build and an infinite loop in one of sample codes. Also, I found that CodeSamples/api.h and CodeSamples/Makefile.arch can be removed from repository if their recipe are properly written in Makefiles.

Quoted 6 lines

Patch 1 adds rules to generate Makefile.arch and api.h that suit the architecture of you host. As I don't have ppc64 or arm host environment, I tested it only on x86_32 and x86_64. I'd like to know if it works on ppc64 and arm.

Patch 2 removes the redundant files.

I took the first two, and it is nice to just be able to type "make" in the CodeSamples directory! ;-)

Quoted 1 line

Patch 3 and 4 are fixes of warnings and infinite loops.

I have some concerns here, and will reply to the patches.

Thanx, Paul

Quoted 40 lines

Thoughts?

Thanks, Akira

Signature · 35 lines
Akira Yokosawa (4):
  CodeSamples: Add rule to generate Makefile.arch and api.h
  CodeSamples: Remove generated files from repository
  CodeSamples: Use 'intptr_t' to be compatible with 'void *'
  CodeSamples/defer: Add compiler barriers in gettimestampmp.c

 CodeSamples/.gitignore                         |   4 +-
 CodeSamples/Makefile                           |  18 +
 CodeSamples/Makefile.arch                      |   6 -
 CodeSamples/SMPdesign/Makefile                 |   3 +
 CodeSamples/SMPdesign/matmul.c                 |  13 +-
 CodeSamples/SMPdesign/smpalloc.c               |  11 +-
 CodeSamples/advsync/Makefile                   |   3 +
 CodeSamples/api.h                              | 808 -------------------------
 CodeSamples/count/Makefile                     |   3 +
 CodeSamples/datastruct/Issaquah/Makefile       |   3 +
 CodeSamples/datastruct/Issaquah/existence_test | Bin 26359 -> 0 bytes
 CodeSamples/datastruct/hash/Makefile           |   3 +
 CodeSamples/datastruct/log/Makefile            |   3 +
 CodeSamples/datastruct/skiplist/Makefile       |   3 +
 CodeSamples/defer/Makefile                     |   3 +
 CodeSamples/defer/gettimestampmp.c             |   5 +-
 CodeSamples/depends.mk                         |  43 ++
 CodeSamples/intro/Makefile                     |   3 +
 CodeSamples/intro/threadcreate.c               |   7 +-
 CodeSamples/locking/Makefile                   |   3 +
 CodeSamples/toolsoftrade/Makefile              |   3 +
 21 files changed, 117 insertions(+), 831 deletions(-)
 delete mode 100644 CodeSamples/Makefile.arch
 delete mode 100644 CodeSamples/api.h
 delete mode 100755 CodeSamples/datastruct/Issaquah/existence_test
 create mode 100644 CodeSamples/depends.mk

-- 
2.7.4
#8 lore raw

2017/05/30 9:02、Paul E. McKenney <[email protected]> のメッセージ:

Quoted 19 lines · Akira Yokosawa
Quoted 18 lines
Quoted 1 line

From fd5fb9afb6b99b15370a9823b42fa2a92342b92a Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 06:52:40 +0900
Subject: [RFC PATCH 0/4] CodeSamples: Cleanups and fixes

Hi Paul,

While I was looking around CodeSamples, I encountered several warnings in build and an infinite loop in one of sample codes. Also, I found that CodeSamples/api.h and CodeSamples/Makefile.arch can be removed from repository if their recipe are properly written in Makefiles.

Patch 1 adds rules to generate Makefile.arch and api.h that suit the architecture of you host. As I don't have ppc64 or arm host environment, I tested it only on x86_32 and x86_64. I'd like to know if it works on ppc64 and arm.

Quoted 4 lines
Quoted 1 line

Patch 2 removes the redundant files.

I took the first two, and it is nice to just be able to type "make" in the CodeSamples directory! ;-)

Does this work on ppc64 and arm (whatever arm
platform you have access to)?

Quoted 5 lines
Quoted 2 lines

Patch 3 and 4 are fixes of warnings and infinite loops.

I have some concerns here, and will reply to the patches.

I see your points. I'll respin.

Thanks, Akira
(from mobile, might be QP encoded)

Quoted 43 lines

Thanx, Paul

Quoted 40 lines

Thoughts?

Thanks, Akira

Signature · 35 lines
Akira Yokosawa (4):
 CodeSamples: Add rule to generate Makefile.arch and api.h
 CodeSamples: Remove generated files from repository
 CodeSamples: Use 'intptr_t' to be compatible with 'void *'
 CodeSamples/defer: Add compiler barriers in gettimestampmp.c

CodeSamples/.gitignore                         |   4 +-
CodeSamples/Makefile                           |  18 +
CodeSamples/Makefile.arch                      |   6 -
CodeSamples/SMPdesign/Makefile                 |   3 +
CodeSamples/SMPdesign/matmul.c                 |  13 +-
CodeSamples/SMPdesign/smpalloc.c               |  11 +-
CodeSamples/advsync/Makefile                   |   3 +
CodeSamples/api.h                              | 808 -------------------------
CodeSamples/count/Makefile                     |   3 +
CodeSamples/datastruct/Issaquah/Makefile       |   3 +
CodeSamples/datastruct/Issaquah/existence_test | Bin 26359 -> 0 bytes
CodeSamples/datastruct/hash/Makefile           |   3 +
CodeSamples/datastruct/log/Makefile            |   3 +
CodeSamples/datastruct/skiplist/Makefile       |   3 +
CodeSamples/defer/Makefile |   3 +
CodeSamples/defer/gettimestampmp.c             |   5 +-
CodeSamples/depends.mk                         |  43 ++
CodeSamples/intro/Makefile                     |   3 +
CodeSamples/intro/threadcreate.c               |   7 +-
CodeSamples/locking/Makefile                   |   3 +
CodeSamples/toolsoftrade/Makefile              |   3 +
21 files changed, 117 insertions(+), 831 deletions(-)
delete mode 100644 CodeSamples/Makefile.arch
delete mode 100644 CodeSamples/api.h
delete mode 100755 CodeSamples/datastruct/Issaquah/existence_test
create mode 100644 CodeSamples/depends.mk

-- 
2.7.4
#9 lore raw

v2 cover CodeSamples: Cleanups and fixes

In reply to Akira Yokosawa

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Thanks, Akira

Signature · 12 lines
Akira Yokosawa (2):
  CodeSamples: Use 'intptr_t' to be compatible with 'void *'
  CodeSamples/defer: Add compiler barriers in gettimestampmp.c

 CodeSamples/SMPdesign/matmul.c     | 4 ++--
 CodeSamples/SMPdesign/smpalloc.c   | 4 ++--
 CodeSamples/defer/gettimestampmp.c | 7 ++++---
 CodeSamples/intro/threadcreate.c   | 4 ++--
 4 files changed, 10 insertions(+), 9 deletions(-)

-- 
2.7.4
#10 lore raw

RFC PATCH v2 1/2 CodeSamples: Use 'intptr_t' to be compatible with 'void *'

From 177ee2891184f0a97b66d748763dbc7af75033ff Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:21:41 +0900
Subject: [RFC PATCH v2 1/2] CodeSamples: Use 'intptr_t' to be compatible with 'void *'

On x86_64, casting between "int" and "void *" in threadcreate.c causes GCC to emit warnings such as:

warning: cast from pointer to integer of different size
warning: cast from integer to pointer of different size

Let's adopt C99 way of writing portable code.

Also do the same changes where appropriate. (Other than threadcreate.c, no warnings were observed on x86_64.)

[Revised according to Paul's suggestion to keep intptr_t usage
confined.]

---
 CodeSamples/SMPdesign/matmul.c     | 4 ++--
 CodeSamples/SMPdesign/smpalloc.c   | 4 ++--
 CodeSamples/defer/gettimestampmp.c | 2 +-
 CodeSamples/intro/threadcreate.c   | 4 ++--
 4 files changed, 7 insertions(+), 7 deletions(-)
CodeSamples/SMPdesign/matmul.c +2 -2
index 6a07730..3f70807 100644
@@ -38,7 +38,7 @@ atomic_t nstarted;
 
 void *matmul_thread(void *me_in)
 {
-	long me = (long)me_in;
+	long me = (intptr_t)me_in;
 	int i, j, k;
 
 	atomic_inc(&nstarted);
@@ -87,7 +87,7 @@ int main(int argc, char *argv[])
 	goflag = GOFLAG_INIT;
 	startcreatetime = get_microseconds();
 	for (i = 0; i < nthread; i++)
-		create_thread(matmul_thread, (void *)(long)i);
+		create_thread(matmul_thread, (void *)(intptr_t)i);
 	while (atomic_read(&nstarted) != nthread)
 		barrier();
 	starttime = get_microseconds();
CodeSamples/SMPdesign/smpalloc.c +2 -2
index 95b21a1..454846b 100644
@@ -123,7 +123,7 @@ void *memblock_test(void *arg)
 	long cnt = 0;
 	long cntfail = 0;
 	int i;
-	int runlength = (int)(long)arg;
+	int runlength = (intptr_t)arg;
 	struct memblock *p[MAX_RUN];
 
 	if (runlength > MAX_RUN)
@@ -189,7 +189,7 @@ int main(int argc, char *argv[])
 
 	goflag = 1;
 	for (i = 0; i < nkids; i++)
-		create_thread(memblock_test, (void *)(long)runlength);
+		create_thread(memblock_test, (void *)(intptr_t)runlength);
 
 	sleep(1);
 	goflag = 0;
CodeSamples/defer/gettimestampmp.c +1 -1
index bc0b9ea..2abade4 100644
@@ -29,7 +29,7 @@ long curtimestamp = 0;
 
 void *collect_timestamps(void *mask_in)
 {
-	long mask = (long)mask_in;
+	long mask = (intptr_t)mask_in;
 
 	while (curtimestamp < MAX_TIMESTAMPS) {
 		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
CodeSamples/intro/threadcreate.c +2 -2
index 26b7ba9..94cde89 100644
@@ -22,7 +22,7 @@
 
 void *thread_test(void *arg)
 {
-	int myarg = (int)arg;
+	int myarg = (intptr_t)arg;
 
 	printf("child thread %d: smp_thread_id() = %d\n",
 	       myarg, smp_thread_id());
@@ -54,7 +54,7 @@ int main(int argc, char *argv[])
 	printf("Parent thread spawning %d threads.\n", nkids);
 
 	for (i = 0; i < nkids; i++)
-		create_thread(thread_test, (void *)i);
+		create_thread(thread_test, (void *)(intptr_t)i);
 
 	wait_all_threads();
 
Signature · 1 line
2.7.4
#11 lore raw

RFC PATCH v2 2/2 CodeSamples/defer: Add compiler barriers in gettimestampmp.c

In reply to Akira Yokosawa

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:40:04 +0900
Subject: [RFC PATCH v2 2/2] CodeSamples/defer: Add compiler barriers in gettimestampmp.c

They ensure curtimestamp is read and written once in every iteration.

[Revised according to Paul's suggestion to use WRITE_ONCE()]

---
 CodeSamples/defer/gettimestampmp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
CodeSamples/defer/gettimestampmp.c +3 -2
index 2abade4..fc5718d 100644
@@ -32,14 +32,15 @@ void *collect_timestamps(void *mask_in)
 	long mask = (intptr_t)mask_in;
 
 	while (curtimestamp < MAX_TIMESTAMPS) {
-		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
+		while ((READ_ONCE(curtimestamp) & CURTIMESTAMP_MASK) != mask)
 			continue;
 		if (curtimestamp >= MAX_TIMESTAMPS)
 			break;
 
 		/* Don't need memory barrier -- no other shared vars!!! */
 
-		ts[curtimestamp++] = get_timestamp();
+		ts[curtimestamp] = get_timestamp();
+		WRITE_ONCE(curtimestamp, curtimestamp + 1);
 	}
 	smp_mb();
 	return (NULL);
Signature · 1 line
2.7.4
#12 lore raw
In reply to Akira Yokosawa
Quoted 10 lines · Akira Yokosawa
Quoted 1 line

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

Quoted 7 lines

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Wow, that loop is old code!!! My current compiler creates an infinite
loop for it, so yes, there is more required. Plus there are confusing
and redundant comparisons, so that it is not entirely clear to me that the loop is guaranteed to terminate properly.

So I took both patches, but rewrote the loop in the second patch as shown below.

If you are OK with this rewrite, I will push them.

Thanx, Paul

------------------------------------------------------------------------

commit 8a54d9aeeeefa1909db062dc893705ff8fefd702

Author: Akira Yokosawa <[email protected]>
Date:   Tue May 30 20:40:04 2017 +0900

CodeSamples/defer: Rework loop in gettimestampmp.c

Add READ_ONCE() and WRITE_ONCE() ensure curtimestamp is read and written once in every iteration. The READ_ONCE() is not optional, as modern compilers can (and do) emit an infinite loop for the earlier code.

[ paulmck: Rework loop to eliminate redundant fetches and comparisons. ]
CodeSamples/defer/gettimestampmp.c +8 -5
index 2abade42e233..8780b71f33d7 100644
@@ -30,16 +30,19 @@ long curtimestamp = 0;
 void *collect_timestamps(void *mask_in)
 {
 	long mask = (intptr_t)mask_in;
+	long cts;
 
-	while (curtimestamp < MAX_TIMESTAMPS) {
-		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
-			continue;
-		if (curtimestamp >= MAX_TIMESTAMPS)
+	for (;;) {
+		cts = READ_ONCE(curtimestamp);
+		if (cts >= MAX_TIMESTAMPS)
 			break;
+		if ((cts & CURTIMESTAMP_MASK) != mask)
+			continue;
 
 		/* Don't need memory barrier -- no other shared vars!!! */
 
-		ts[curtimestamp++] = get_timestamp();
+		ts[cts] = get_timestamp();
+		WRITE_ONCE(curtimestamp, cts + 1);
 	}
 	smp_mb();
 	return (NULL);
#13 lore raw
Quoted 15 lines · Paul E. McKenney
Quoted 14 lines · Akira Yokosawa
Quoted 1 line

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

Quoted 6 lines
Quoted 3 lines

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Wow, that loop is old code!!! My current compiler creates an infinite loop for it, so yes, there is more required.

You mean on GCC for ppc64?

Quoted 8 lines

Plus there are confusing
and redundant comparisons, so that it is not entirely clear to me that the loop is guaranteed to terminate properly

So I took both patches, but rewrote the loop in the second patch as shown below.

If you are OK with this rewrite, I will push them.

I'm OK with this, but it is a whole rewrite of the code, so

looks appropriate in this case.
It's up to you which tag to use.

Thanks, Akira

Quoted 50 lines

Thanx, Paul

------------------------------------------------------------------------

commit 8a54d9aeeeefa1909db062dc893705ff8fefd702

Author: Akira Yokosawa <[email protected]>
Date:   Tue May 30 20:40:04 2017 +0900

CodeSamples/defer: Rework loop in gettimestampmp.c

Add READ_ONCE() and WRITE_ONCE() ensure curtimestamp is read and written once in every iteration. The READ_ONCE() is not optional, as modern compilers can (and do) emit an infinite loop for the earlier code.

[ paulmck: Rework loop to eliminate redundant fetches and comparisons. ]
CodeSamples/defer/gettimestampmp.c +8 -5
index 2abade42e233..8780b71f33d7 100644
@@ -30,16 +30,19 @@ long curtimestamp = 0;
 void *collect_timestamps(void *mask_in)
 {
 	long mask = (intptr_t)mask_in;
+	long cts;
 
-	while (curtimestamp < MAX_TIMESTAMPS) {
-		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
-			continue;
-		if (curtimestamp >= MAX_TIMESTAMPS)
+	for (;;) {
+		cts = READ_ONCE(curtimestamp);
+		if (cts >= MAX_TIMESTAMPS)
 			break;
+		if ((cts & CURTIMESTAMP_MASK) != mask)
+			continue;
 
 		/* Don't need memory barrier -- no other shared vars!!! */
 
-		ts[curtimestamp++] = get_timestamp();
+		ts[cts] = get_timestamp();
+		WRITE_ONCE(curtimestamp, cts + 1);
 	}
 	smp_mb();
 	return (NULL);
#14 lore raw
Quoted 16 lines · Akira Yokosawa
Quoted 15 lines · Paul E. McKenney
Quoted 14 lines · Akira Yokosawa
Quoted 1 line

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Wow, that loop is old code!!! My current compiler creates an infinite loop for it, so yes, there is more required.

You mean on GCC for ppc64?

No, x86 GCC on the code before you changed it. ;-)

Which reminds me... How about if I get you direct access to some ppc64 machines? If you are at all interested, please let me know and also please sign up here:

http://osuosl.org/services/powerdev/request_hosting/

I believe that there is also similar access to ARM systems, so please let me know if you are interested.

Quoted 7 lines
Quoted 7 lines

Plus there are confusing
and redundant comparisons, so that it is not entirely clear to me that the loop is guaranteed to terminate properly

So I took both patches, but rewrote the loop in the second patch as shown below.

Quoted 8 lines
Quoted 1 line

If you are OK with this rewrite, I will push them.

I'm OK with this, but it is a whole rewrite of the code, so

looks appropriate in this case.
It's up to you which tag to use.

I will stick with what I have. Lazy and all that. ;-)

Thanx, Paul

Quoted 53 lines

Thanks, Akira

Quoted 50 lines

Thanx, Paul

------------------------------------------------------------------------

commit 8a54d9aeeeefa1909db062dc893705ff8fefd702

Author: Akira Yokosawa <[email protected]>
Date:   Tue May 30 20:40:04 2017 +0900

CodeSamples/defer: Rework loop in gettimestampmp.c

Add READ_ONCE() and WRITE_ONCE() ensure curtimestamp is read and written once in every iteration. The READ_ONCE() is not optional, as modern compilers can (and do) emit an infinite loop for the earlier code.

[ paulmck: Rework loop to eliminate redundant fetches and comparisons. ]
CodeSamples/defer/gettimestampmp.c +8 -5
index 2abade42e233..8780b71f33d7 100644
@@ -30,16 +30,19 @@ long curtimestamp = 0;
 void *collect_timestamps(void *mask_in)
 {
 	long mask = (intptr_t)mask_in;
+	long cts;
 
-	while (curtimestamp < MAX_TIMESTAMPS) {
-		while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
-			continue;
-		if (curtimestamp >= MAX_TIMESTAMPS)
+	for (;;) {
+		cts = READ_ONCE(curtimestamp);
+		if (cts >= MAX_TIMESTAMPS)
 			break;
+		if ((cts & CURTIMESTAMP_MASK) != mask)
+			continue;
 
 		/* Don't need memory barrier -- no other shared vars!!! */
 
-		ts[curtimestamp++] = get_timestamp();
+		ts[cts] = get_timestamp();
+		WRITE_ONCE(curtimestamp, cts + 1);
 	}
 	smp_mb();
 	return (NULL);
#15 lore raw
In reply to Paul E. McKenney

Hi Paul and Akira,

The code looks clear and easy to understand now :-).

While checking the patch, I have one question. Are there any technical reason that we prefer for(;;) instead of while(1) in CodeSamples? Just out of curiosity :-)

Thanks

Quoted 81 lines · Paul E. McKenney
Quoted 10 lines · Akira Yokosawa
Quoted 1 line

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

Quoted 7 lines

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Wow, that loop is old code!!! My current compiler creates an infinite
loop for it, so yes, there is more required. Plus there are confusing
and redundant comparisons, so that it is not entirely clear to me that the loop is guaranteed to terminate properly.

So I took both patches, but rewrote the loop in the second patch as shown below.

If you are OK with this rewrite, I will push them.

Thanx, Paul

------------------------------------------------------------------------

commit 8a54d9aeeeefa1909db062dc893705ff8fefd702

Author: Akira Yokosawa <[email protected]>
Date:   Tue May 30 20:40:04 2017 +0900

CodeSamples/defer: Rework loop in gettimestampmp.c

Add READ_ONCE() and WRITE_ONCE() ensure curtimestamp is read and written once in every iteration. The READ_ONCE() is not optional, as modern compilers can (and do) emit an infinite loop for the earlier code.

[ paulmck: Rework loop to eliminate redundant fetches and comparisons. ]
CodeSamples/defer/gettimestampmp.c +8 -6
index 2abade42e233..8780b71f33d7 100644
@@ -30,16 +30,19 @@ long curtimestamp = 0;
 void *collect_timestamps(void *mask_in)
 {
        long mask = (intptr_t)mask_in;
+       long cts;
 
-       while (curtimestamp < MAX_TIMESTAMPS) {
-               while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
-                       continue;
-               if (curtimestamp >= MAX_TIMESTAMPS)
+       for (;;) {
+               cts = READ_ONCE(curtimestamp);
+               if (cts >= MAX_TIMESTAMPS)
                        break;
+               if ((cts & CURTIMESTAMP_MASK) != mask)
+                       continue;
 
                /* Don't need memory barrier -- no other shared vars!!! */
 
-               ts[curtimestamp++] = get_timestamp();
+               ts[cts] = get_timestamp();
+               WRITE_ONCE(curtimestamp, cts + 1);
        }
        smp_mb();
        return (NULL);
 
--

To unsubscribe from this list: send the line "unsubscribe perfbook" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#16 lore raw
Quoted 3 lines · Junchang Wang

Hi Paul and Akira,

The code looks clear and easy to understand now :-).

Glad you like it! I am sure that other code in there could use similar help.

Quoted 3 lines

While checking the patch, I have one question. Are there any technical reason that we prefer for(;;) instead of while(1) in CodeSamples? Just out of curiosity :-)

No. Just thirty-five years of habit plus the preferences of the Linux kernel community. And the latter are probably because "while (1)" has one more character than does "for (;;)". ;-)

Thanx, Paul

Quoted 86 lines

Thanks

Quoted 81 lines · Paul E. McKenney
Quoted 10 lines · Akira Yokosawa
Quoted 1 line

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

Quoted 7 lines

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Wow, that loop is old code!!! My current compiler creates an infinite
loop for it, so yes, there is more required. Plus there are confusing
and redundant comparisons, so that it is not entirely clear to me that the loop is guaranteed to terminate properly.

So I took both patches, but rewrote the loop in the second patch as shown below.

If you are OK with this rewrite, I will push them.

Thanx, Paul

------------------------------------------------------------------------

commit 8a54d9aeeeefa1909db062dc893705ff8fefd702

Author: Akira Yokosawa <[email protected]>
Date:   Tue May 30 20:40:04 2017 +0900

CodeSamples/defer: Rework loop in gettimestampmp.c

Add READ_ONCE() and WRITE_ONCE() ensure curtimestamp is read and written once in every iteration. The READ_ONCE() is not optional, as modern compilers can (and do) emit an infinite loop for the earlier code.

[ paulmck: Rework loop to eliminate redundant fetches and comparisons. ]
CodeSamples/defer/gettimestampmp.c +8 -6
index 2abade42e233..8780b71f33d7 100644
@@ -30,16 +30,19 @@ long curtimestamp = 0;
 void *collect_timestamps(void *mask_in)
 {
        long mask = (intptr_t)mask_in;
+       long cts;
 
-       while (curtimestamp < MAX_TIMESTAMPS) {
-               while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
-                       continue;
-               if (curtimestamp >= MAX_TIMESTAMPS)
+       for (;;) {
+               cts = READ_ONCE(curtimestamp);
+               if (cts >= MAX_TIMESTAMPS)
                        break;
+               if ((cts & CURTIMESTAMP_MASK) != mask)
+                       continue;
 
                /* Don't need memory barrier -- no other shared vars!!! */
 
-               ts[curtimestamp++] = get_timestamp();
+               ts[cts] = get_timestamp();
+               WRITE_ONCE(curtimestamp, cts + 1);
        }
        smp_mb();
        return (NULL);
 
--

To unsubscribe from this list: send the line "unsubscribe perfbook" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#17 lore raw
Quoted 7 lines · Paul E. McKenney
Quoted 3 lines · Junchang Wang

Hi Paul and Akira,

The code looks clear and easy to understand now :-).

Glad you like it! I am sure that other code in there could use similar help.

I would be very happy to gradually go through these sections this summer. :-)

Quoted 9 lines
Quoted 4 lines

While checking the patch, I have one question. Are there any technical reason that we prefer for(;;) instead of while(1) in CodeSamples? Just out of curiosity :-)

No. Just thirty-five years of habit plus the preferences of the Linux kernel community. And the latter are probably because "while (1)" has one more character than does "for (;;)". ;-)

Got you :-) Thanks.

--Jason

Quoted 89 lines

Thanx, Paul

Quoted 86 lines

Thanks

Quoted 81 lines · Paul E. McKenney
Quoted 10 lines · Akira Yokosawa
Quoted 1 line

From 489b5e3bdeba2f9b733dbe3d85390368dd159174 Mon Sep 17 00:00:00 2001

From: Akira Yokosawa <[email protected]>
Date: Tue, 30 May 2017 20:44:52 +0900
Subject: [RFC PATCH v2 0/2] CodeSamples: Cleanups and fixes

Hi Paul,

This is the respin of the latter two patches of v1. I'm keeping RFC because of some questions.

Quoted 7 lines

"long" -> "intptr_t" changes in Patch 1 have no effect on a platform where "long" and "intptr_t" have the same width, but I think they are good in portability POV.

WRITE_ONCE() in Patch 2 is placed under the assignment to the array because I could not translate post increment in any other way. Does the WRITE_ONCE() ensure the outer "while" capture the value?

Wow, that loop is old code!!! My current compiler creates an infinite
loop for it, so yes, there is more required. Plus there are confusing
and redundant comparisons, so that it is not entirely clear to me that the loop is guaranteed to terminate properly.

So I took both patches, but rewrote the loop in the second patch as shown below.

If you are OK with this rewrite, I will push them.

Thanx, Paul

------------------------------------------------------------------------

commit 8a54d9aeeeefa1909db062dc893705ff8fefd702

Author: Akira Yokosawa <[email protected]>
Date:   Tue May 30 20:40:04 2017 +0900

CodeSamples/defer: Rework loop in gettimestampmp.c

Add READ_ONCE() and WRITE_ONCE() ensure curtimestamp is read and written once in every iteration. The READ_ONCE() is not optional, as modern compilers can (and do) emit an infinite loop for the earlier code.

[ paulmck: Rework loop to eliminate redundant fetches and comparisons. ]
CodeSamples/defer/gettimestampmp.c +8 -6
index 2abade42e233..8780b71f33d7 100644
@@ -30,16 +30,19 @@ long curtimestamp = 0;
 void *collect_timestamps(void *mask_in)
 {
        long mask = (intptr_t)mask_in;
+       long cts;
 
-       while (curtimestamp < MAX_TIMESTAMPS) {
-               while ((curtimestamp & CURTIMESTAMP_MASK) != mask)
-                       continue;
-               if (curtimestamp >= MAX_TIMESTAMPS)
+       for (;;) {
+               cts = READ_ONCE(curtimestamp);
+               if (cts >= MAX_TIMESTAMPS)
                        break;
+               if ((cts & CURTIMESTAMP_MASK) != mask)
+                       continue;
 
                /* Don't need memory barrier -- no other shared vars!!! */
 
-               ts[curtimestamp++] = get_timestamp();
+               ts[cts] = get_timestamp();
+               WRITE_ONCE(curtimestamp, cts + 1);
        }
        smp_mb();
        return (NULL);
 
--

To unsubscribe from this list: send the line "unsubscribe perfbook" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html