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 */
next prev parent 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).