linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: dave.martin@linaro.org (Dave Martin)
To: linux-arm-kernel@lists.infradead.org
Subject: Git pull request: 64-bit atomic user helper
Date: Tue, 21 Jun 2011 17:17:39 +0100	[thread overview]
Message-ID: <20110621161739.GA2519@arm.com> (raw)
In-Reply-To: <alpine.LFD.2.00.1106202134510.2142@xanadu.home>

On Mon, Jun 20, 2011 at 09:54:07PM -0400, Nicolas Pitre wrote:
> Russell, please pull the following for the next merge window:
> 
> 	git://git.linaro.org/people/nico/linux.git cmpxchg64
> 
> This series cleans up the kuser documentation, then it adds 64-bit
> cmpxchg support as needed by some user space applications.
> 
> Tested with the initial libgcc patches relying on this, using a 
> kernel that has this series applied, and another without those 
> patches to verify that the test for the availability of the needed 
> helper does work as intended.

If you like:

Tested-by: Dave Martin <dave.martin@linaro.org>


Here's my silly test program.

It passed on a pandaboard (2-core A9) with
-O3 -DITERATIONS=1000000000ULL -DBITS64

(Really, -O should not make a significant difference, though.)

Since the test just loops around __kuser_cmpxchg64(), if the number
of involuntary preemptions of a thread is non-trivial, some of those
preemptions will occur inside the kuser helper.


# ./tst-kuser 
__kuser_helper_version = 5
iterations * 8696638275910399085 = 7609822085224859648
        Thread 0:            17992 preemptions
        Thread 1:            17636 preemptions
        Thread 2:            17885 preemptions
        Thread 3:            17517 preemptions
OK

--- /dev/null	2011-06-20 16:05:05.019195001 +0000
+++ tst-kuser.c	2011-06-20 17:45:12.000000000 +0000
@@ -0,0 +1,158 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+
+#include "kuser.h"
+
+#ifndef ITERATIONS
+#define ITERATIONS 1000000000ULL
+#endif
+
+#ifndef INCREMENT
+#ifdef BITS64
+/*
+ * So that target visits every value before repeating,
+ * INCREMENT should be an odd number.
+ * So that imperfect atomicity does not go unnoticed,
+ * INCREMENT should have plenty of non-zero bits, so that
+ * many bits of target change each time INCREMENT is added.
+ */
+#define INCREMENT 0x78B0AA6F67B4746DULL
+#else
+#define INCREMENT 0x67B4746DU
+#endif
+#endif
+
+#ifndef THREADS
+#define THREADS 4
+#endif
+
+#ifdef BITS64
+static volatile long long target = 0;
+#else
+static volatile unsigned target = 0;
+#endif
+
+struct thread_struct {
+	pthread_t thread;
+	volatile unsigned preemption_count;
+};
+
+#ifdef BITS64
+static void atomic_inc(long long volatile *p)
+#else
+static void atomic_inc(unsigned volatile *p)
+#endif
+{
+#ifdef BITS64
+	long long i, j;
+#else
+	int i, j;
+#endif
+
+	do {
+
+		i = *p;
+		j = i + INCREMENT;
+#ifdef BITS64
+	} while(__kuser_cmpxchg64(&i, &j, p));
+#else
+	} while(__kuser_cmpxchg(i, j, p));
+#endif
+}
+
+static unsigned thread_involuntary_switches(void)
+{
+	unsigned result = 0;
+	FILE *f = NULL;
+	char buf[80];
+#define FORMAT "/proc/%d/sched"
+	char namebuf[sizeof FORMAT + 10];
+	pid_t tid;
+
+	tid = syscall(__NR_gettid);
+	if(snprintf(namebuf, sizeof namebuf, FORMAT, tid) >= sizeof namebuf)
+		goto error;
+	f = fopen(namebuf, "r");
+	if(!f)
+		goto error;
+
+	while(fgets(buf, sizeof buf, f))
+		if(sscanf(buf, "nr_involuntary_switches : %d", &result))
+			goto done;
+
+error:
+	fprintf(stderr,
+		"Warning: %d: unable to read nr_involuntary_switches count\n",
+		tid);
+done:
+	if(f)
+		fclose(f);
+	return result;
+}
+
+static void *thread_func(void *arg)
+{
+	struct thread_struct *me = arg;
+
+	unsigned i;
+
+	for(i = 0; i < ITERATIONS; i++)
+		atomic_inc(&target);
+
+	me->preemption_count = thread_involuntary_switches();
+
+	return me;
+}
+
+int main(void)
+{
+	unsigned i;
+	struct thread_struct threads[THREADS];
+
+	fprintf(stderr, "__kuser_helper_version = %d\n",
+		__kuser_helper_version);
+#ifdef BTIS64
+	if(__kuser_helper_version < 5) {
+#else
+	if(__kuser_helper_version < 3) {
+#endif
+		fputs("Kernel too old\n", stderr);
+		exit(EXIT_FAILURE);
+	}
+
+	for(i = 0; i < THREADS; i++)
+		pthread_create(&threads[i].thread, NULL,
+			thread_func, &threads[i]);
+
+	for(i = 0; i < THREADS; i++)
+		pthread_join(threads[i].thread, NULL);
+
+	/*
+	 * For now, just leave the signaller threads running.
+	 * They should be harmless.
+	 */
+
+#ifdef BITS64
+	fprintf(stderr, "iterations * %llu = %llu\n", INCREMENT, target);
+#else
+	fprintf(stderr, "iterations * %u = %u\n", INCREMENT, target);
+#endif
+
+	for(i = 0; i < THREADS; i++)
+		fprintf(stderr, "\tThread %u:\t%10u preemptions\n",
+			i, threads[i].preemption_count);	
+
+	if(ITERATIONS * INCREMENT * THREADS != target) {
+		fputs("Error: Wrong final value of target.\n", stderr);
+		return EXIT_FAILURE;
+	} else {
+		fputs("OK\n", stderr);
+		return EXIT_SUCCESS;
+	}
+
+	return 0;
+}
--- /dev/null	2011-06-20 16:05:05.019195001 +0000
+++ kuser.h	2011-06-20 16:44:28.000000000 +0000
@@ -0,0 +1,18 @@
+#ifndef __ARM_KUSER_H
+#define __ARM_KUSER_H
+
+#define __kuser_helper_version (*(int *)0xffff0ffc)
+
+#define __kuser_decl __attribute__ (( __unused__ )) static
+
+__kuser_decl int __kuser_cmpxchg64(const long long *oldval, const long long *newval, volatile long long *ptr)
+{
+	return ((int (*)(const long long *, const long long *, volatile long long *))0xffff0f60)(oldval, newval, ptr);
+}
+
+__kuser_decl int __kuser_cmpxchg(int oldval, int newval, volatile int *ptr)
+{
+	return ((int (*)(int oldval, int newval, volatile int *))0xffff0fc0)(oldval, newval, ptr);
+}
+
+#endif /* __ARM_KUSER_H */

  reply	other threads:[~2011-06-21 16:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-21  1:54 Git pull request: 64-bit atomic user helper Nicolas Pitre
2011-06-21 16:17 ` Dave Martin [this message]
2011-06-28 19:59 ` Nicolas Pitre
2011-06-28 20:27   ` Russell King - ARM Linux
2011-06-28 20:41     ` Nicolas Pitre
2011-06-30 10:07 ` Russell King - ARM Linux
2011-06-30 12:02   ` Uwe Kleine-König
2011-06-30 14:29   ` Nicolas Pitre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110621161739.GA2519@arm.com \
    --to=dave.martin@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).