From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S965414AbbJVSGl (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 14:06:41 -0400
Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:13007 "EHLO
	mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK)
	by vger.kernel.org with ESMTP id S1751990AbbJVSGi (ORCPT
	<rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 14:06:38 -0400
Date: Thu, 22 Oct 2015 11:06:28 -0700
From: Dave Watson <davejwatson@fb.com>
To: <davejwatson@fb.com>, <kernel-team@fb.com>, <linux-kernel@vger.kernel.org>,
        <linux-api@vger.kernel.org>, <pjt@google.com>,
        <mathieu.desnoyers@efficios.com>
Subject: [RFC PATCH 0/3] restartable sequences benchmarks
Message-ID: <cover.1445464158.git.davejwatson@fb.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
User-Agent: Mutt/1.5.20 (2009-12-10)
X-Originating-IP: [192.168.52.123]
X-Proofpoint-Spam-Reason: safe
X-FB-Internal: Safe
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2015-10-22_12:,,
 signatures=0
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

We've been testing out restartable sequences + malloc changes for use
at Facebook.  Below are some test results, as well as some possible
changes based on Paul Turner's original patches

https://lkml.org/lkml/2015/6/24/665

I ran one service with several permutations of various mallocs.  The
service is CPU-bound, and hits the allocator quite hard.  Requests/s
are held constant at the source, so we use cpu idle time and latency
as an indicator of service quality. These are average numbers over
several hours.  Machines were dual E5-2660, total 16 cores +
hyperthreading.  This service has ~400 total threads, 70-90 of which
are doing work at any particular time.

                                   RSS CPUIDLE LATENCYMS
jemalloc 4.0.0                     31G   33%     390
jemalloc + this patch              25G   33%     390
jemalloc + this patch using lsl    25G   30%     420
jemalloc + PT's rseq patch         25G   32%     405
glibc malloc 2.20                  27G   30%     420
tcmalloc gperftools trunk (2.2)    21G   30%     480

jemalloc rseq patch used for testing:
https://github.com/djwatson/jemalloc

lsl test - using lsl segment limit to get cpu (i.e. inlined vdso
getcpu on x86) instead of using the thread caching as in this patch.
There has been some suggestions to add the thread-cached getcpu()
feature separately.  It does seem to move the needle in a real service
by about ~3% to have a thread-cached getcpu vs. not.  I don't think we
can use restartable sequences in production without a faster getcpu.

GS-segment / migration only tests

There's been some interest in seeing if we can do this with only gs
segment, here's some numbers for those.  This doesn't have to be gs,
it could just be a migration signal sent to userspace as well, the
same approaches would apply.

GS patch: https://lkml.org/lkml/2014/9/13/59

                                   RSS CPUIDLE LATENCYMS
jemalloc 4.0.0                     31G   33%     390
jemalloc + percpu locking          25G   25%     420
jemalloc + preempt lock / signal   25G   32%     415

* Percpu locking - just lock everything percpu all the time.  If
  scheduled off during the critical section, other threads have to
  wait.

* 'Preempt lock' idea is that we grab a lock, but if we miss the lock,
  send a signal to the offending thread (tid is stored in the lock
  variable) to restart its critical section.  Libunwind was used to
  fixup ips in the signal handler, walking all the frames.  This is
  slower than the kernel preempt check, but happens less often - only
  if there was a preempt during the critical section.  Critical
  sections were inlined using the same scheme as in this patch.  There
  is more overhead than restartable sequences in the hot path (an
  extra unlocked cmpxchg, some accounting). Microbenchmarks showed it
  was 2x slower than rseq, but still faster than atomics.

  Roughly like this: https://gist.github.com/djwatson/9c268681a0dfa797990c

* I also tried a percpu version of stm (software transactional
  memory), but could never write anything better than ~3x slower than
  atomics in a microbenchmark.  I didn't test this in a real service.

Attached are two changes to the original patch:

1) Support more than one critical memory range in the kernel using
   binary search.  This has several advantages:

  * We don't need an extra register ABI to support multiplexing them
    in userspace.  This also avoids some complexity knowing which
    registers/flags might be smashed by a restart.

  * There are no collisions between shared libraries

  * They can be inlined with gcc inline asm.  With optimization on,
    gcc correctly inlines and registers many more regions.  In a real
    service this does seem to improve latency a hair.  A
    microbenchmark shows ~20% faster.

Downsides:  Less control over how we search/jump to the regions, but I
didn't notice any difference in testing a reasonable number of regions
(less than 100).  We could set a max limit?

2) Additional checks in ptrace to single step over critical sections.
   We also prevent setting breakpoints, as these also seem to confuse
   gdb sometimes.

Dave Watson (3):
  restartable sequences: user-space per-cpu critical sections
  restartable sequences: x86 ABI
  restartable sequences: basic user-space self-tests

 arch/Kconfig                                       |   7 +
 arch/x86/Kconfig                                   |   1 +
 arch/x86/entry/common.c                            |   3 +
 arch/x86/entry/syscalls/syscall_64.tbl             |   1 +
 arch/x86/include/asm/restartable_sequences.h       |  44 +++
 arch/x86/kernel/Makefile                           |   2 +
 arch/x86/kernel/ptrace.c                           |   6 +-
 arch/x86/kernel/restartable_sequences.c            |  47 +++
 arch/x86/kernel/signal.c                           |  12 +-
 fs/exec.c                                          |   3 +-
 include/linux/sched.h                              |  39 +++
 include/uapi/asm-generic/unistd.h                  |   4 +-
 init/Kconfig                                       |   9 +
 kernel/Makefile                                    |   2 +-
 kernel/fork.c                                      |   1 +
 kernel/ptrace.c                                    |  15 +-
 kernel/restartable_sequences.c                     | 255 ++++++++++++++++
 kernel/sched/core.c                                |   5 +
 kernel/sched/sched.h                               |   3 +
 kernel/sys_ni.c                                    |   3 +
 tools/testing/selftests/rseq/Makefile              |  14 +
 .../testing/selftests/rseq/basic_percpu_ops_test.c | 331 +++++++++++++++++++++
 tools/testing/selftests/rseq/rseq.c                |  48 +++
 tools/testing/selftests/rseq/rseq.h                |  17 ++
 24 files changed, 862 insertions(+), 10 deletions(-)
 create mode 100644 arch/x86/include/asm/restartable_sequences.h
 create mode 100644 arch/x86/kernel/restartable_sequences.c
 create mode 100644 kernel/restartable_sequences.c
 create mode 100644 tools/testing/selftests/rseq/Makefile
 create mode 100644 tools/testing/selftests/rseq/basic_percpu_ops_test.c
 create mode 100644 tools/testing/selftests/rseq/rseq.c
 create mode 100644 tools/testing/selftests/rseq/rseq.h

-- 
2.4.6


From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S965455AbbJVSGx (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 14:06:53 -0400
Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:43499 "EHLO
	mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK)
	by vger.kernel.org with ESMTP id S965425AbbJVSGv (ORCPT
	<rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 14:06:51 -0400
Date: Thu, 22 Oct 2015 11:06:40 -0700
From: Dave Watson <davejwatson@fb.com>
To: <davejwatson@fb.com>, <kernel-team@fb.com>, <linux-kernel@vger.kernel.org>,
        <linux-api@vger.kernel.org>, <pjt@google.com>,
        <mathieu.desnoyers@efficios.com>
Subject: [RFC PATCH 1/3] restartable sequences: user-space per-cpu critical
 sections
Message-ID: <581c0b6403285219724961a3d250c6d95dfacea7.1445464158.git.davejwatson@fb.com>
References: <cover.1445464158.git.davejwatson@fb.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <cover.1445464158.git.davejwatson@fb.com>
User-Agent: Mutt/1.5.20 (2009-12-10)
X-Originating-IP: [192.168.52.123]
X-Proofpoint-Spam-Reason: safe
X-FB-Internal: Safe
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2015-10-22_12:,,
 signatures=0
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

Introduce the notion of 'restartable sequence'.  This is a user-defined range
within which we guarantee user-execution will occur serially with respect
to scheduling events such as migration or competition with other threads.

Preemption, or other interruption within this region, results in control being
transferred to a user-defined restart handler when rescheduled.  This handler
may arrange for the original operation to be retried, including potentially
resynchronizing with dependent state that may have been updated in the interim.

This may be used in combination with an in-memory cpu-id to allow user programs
to implement cpu-local data-structures and primitives, without the use/overhead
of any atomics.

The kernel ABI generally consists of:
- A critical region, with start, end and restart addresses
- A (per-thread) memory location which will be kept current with its cpu

The definition of the above is performed via a new syscall,
  SYSCALL_DEFINE5(restartable_sequences,
                  int, op, int, flags, long, val1, long, val2, long, val3)

There are currently 2 possible operations,
  1) Configure the critical region(s)
  2) Configure the per-thread cpu pointer

[ See kernel/restartable_sequences.c for full documentation ]

A thread that has not configured (2) will not be restarted when executing in
(1).

This patch introduces the general framework for configuration, as well as
exposing the syscall.  We minimally expose x86 as having support (even though
the actual ABI is added by a subsequent patch) so that this can be compile
tested in isolation.

Ptrace is modified to avoid setting a breakpoint in the critical region,
since doing so would always restart the critical section, and may
not work correctly if the breakpoint is also the restart address.
---
 arch/Kconfig                      |   7 ++
 arch/x86/Kconfig                  |   1 +
 fs/exec.c                         |   3 +-
 include/linux/sched.h             |  39 ++++++
 include/uapi/asm-generic/unistd.h |   4 +-
 init/Kconfig                      |   9 ++
 kernel/Makefile                   |   2 +-
 kernel/fork.c                     |   1 +
 kernel/ptrace.c                   |  15 ++-
 kernel/restartable_sequences.c    | 250 ++++++++++++++++++++++++++++++++++++++
 kernel/sched/core.c               |   5 +
 kernel/sched/sched.h              |   3 +
 kernel/sys_ni.c                   |   3 +
 13 files changed, 335 insertions(+), 7 deletions(-)
 create mode 100644 kernel/restartable_sequences.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 4e949e5..93c18fa 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -241,6 +241,13 @@ config HAVE_REGS_AND_STACK_ACCESS_API
 	  declared in asm/ptrace.h
 	  For example the kprobes-based event tracer needs this API.
 
+config HAVE_RESTARTABLE_SEQUENCE_SUPPORT
+	bool
+	depends on HAVE_REGS_AND_STACK_ACCESS_API
+	help
+	  This symbol should be selected by an architecture if it supports an
+	  implementation of restartable sequences.
+
 config HAVE_CLK
 	bool
 	help
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 96d058a..865e795 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -112,6 +112,7 @@ config X86
 	select HAVE_IOREMAP_PROT
 	select HAVE_IRQ_EXIT_ON_IRQ_STACK	if X86_64
 	select HAVE_IRQ_TIME_ACCOUNTING
+	select HAVE_RESTARTABLE_SEQUENCE_SUPPORT
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZ4
diff --git a/fs/exec.c b/fs/exec.c
index b06623a..aa94834 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -19,7 +19,7 @@
  * current->executable is only used by the procfs.  This allows a dispatch
  * table to check for several different types  of binary formats.  We keep
  * trying until we recognize the file or we run out of supported binary
- * formats. 
+ * formats.
  */
 
 #include <linux/slab.h>
@@ -1596,6 +1596,7 @@ static int do_execveat_common(int fd, struct filename *filename,
 	current->in_execve = 0;
 	acct_update_integrals(current);
 	task_numa_free(current);
+	rseq_clear_state_exec(current);
 	free_bprm(bprm);
 	kfree(pathbuf);
 	putname(filename);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b7b9501..a7b6e24 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1182,6 +1182,31 @@ struct mempolicy;
 struct pipe_inode_info;
 struct uts_namespace;
 
+#ifdef CONFIG_RESTARTABLE_SEQUENCES
+struct restartable_sequence_section {
+	/* Start and end of an address space's critical section. */
+	struct rb_node node;
+	void __user *crit_start, __user *crit_end, __user *crit_restart;
+};
+struct restartable_sequence_state {
+	struct rb_root sections;
+	/* Thread's current CPU, typically in TLS. */
+	int __user *cpu_pointer;
+	struct preempt_notifier notifier;
+};
+
+void rseq_clear_state_exec(struct task_struct *p);
+unsigned long rseq_lookup(struct task_struct *p, unsigned long ip);
+#else
+static inline void rseq_clear_state_exec(struct task_struct *p) {}
+static inline void rseq_fork(struct task_struct *p) {}
+static inline unsigned long
+rseq_lookup(struct task_struct *p, unsigned long ip)
+{
+	return 0;
+}
+#endif
+
 struct load_weight {
 	unsigned long weight;
 	u32 inv_weight;
@@ -1811,6 +1836,11 @@ struct task_struct {
 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
 	unsigned long	task_state_change;
 #endif
+
+#ifdef CONFIG_RESTARTABLE_SEQUENCES
+	struct restartable_sequence_state rseq_state;
+#endif
+
 	int pagefault_disabled;
 /* CPU-specific state of this task */
 	struct thread_struct thread;
@@ -3180,4 +3210,13 @@ static inline unsigned long rlimit_max(unsigned int limit)
 	return task_rlimit_max(current, limit);
 }
 
+#ifdef CONFIG_RESTARTABLE_SEQUENCES
+static inline int rseq_active(struct task_struct *p)
+{
+	return p->rseq_state.cpu_pointer != NULL;
+}
+#else
+static inline int rseq_active(struct task_struct *p) { return 0; }
+#endif
+
 #endif
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index ee12400..9659f31 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -713,9 +713,11 @@ __SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat)
 __SYSCALL(__NR_userfaultfd, sys_userfaultfd)
 #define __NR_membarrier 283
 __SYSCALL(__NR_membarrier, sys_membarrier)
+#define __NR_restartable_sequences 284
+__SYSCALL(__NR_restartable_sequences, sys_restartable_sequences)
 
 #undef __NR_syscalls
-#define __NR_syscalls 284
+#define __NR_syscalls 285
 
 /*
  * All syscalls below here should go away really,
diff --git a/init/Kconfig b/init/Kconfig
index c24b6f7..9b4a180 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2042,6 +2042,15 @@ source "block/Kconfig"
 config PREEMPT_NOTIFIERS
 	bool
 
+config RESTARTABLE_SEQUENCES
+	bool "Userspace Restartable Sequences (RSEQ)"
+	default n
+	depends on HAVE_RESTARTABLE_SEQUENCE_SUPPORT && PREEMPT_NOTIFIERS
+	help
+	  Allows binaries to define a region of user-text within which
+	  execution will be restarted in the event of signal delivery or
+	  preemption.
+
 config PADATA
 	depends on SMP
 	bool
diff --git a/kernel/Makefile b/kernel/Makefile
index 53abf00..dbe6963 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -101,8 +101,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
 obj-$(CONFIG_TORTURE_TEST) += torture.o
 obj-$(CONFIG_MEMBARRIER) += membarrier.o
-
 obj-$(CONFIG_HAS_IOMEM) += memremap.o
+obj-$(CONFIG_RESTARTABLE_SEQUENCES) += restartable_sequences.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 2845623..aa3ba1e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -252,6 +252,7 @@ void __put_task_struct(struct task_struct *tsk)
 	WARN_ON(tsk == current);
 
 	task_numa_free(tsk);
+	rseq_clear_state_exec(tsk);
 	security_task_free(tsk);
 	exit_creds(tsk);
 	delayacct_tsk_free(tsk);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 787320d..63935bc 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -825,7 +825,10 @@ int ptrace_request(struct task_struct *child, long request,
 		return generic_ptrace_peekdata(child, addr, data);
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
-		return generic_ptrace_pokedata(child, addr, data);
+		/* Don't breakpoint restartable sequences */
+		if (!rseq_lookup(child, addr))
+			return generic_ptrace_pokedata(child, addr, data);
+		break;
 
 #ifdef PTRACE_OLDSETOPTIONS
 	case PTRACE_OLDSETOPTIONS:
@@ -1116,7 +1119,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 	compat_ulong_t __user *datap = compat_ptr(data);
 	compat_ulong_t word;
 	siginfo_t siginfo;
-	int ret;
+	int ret = -EIO;
 
 	switch (request) {
 	case PTRACE_PEEKTEXT:
@@ -1130,8 +1133,12 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 
 	case PTRACE_POKETEXT:
 	case PTRACE_POKEDATA:
-		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
-		ret = (ret != sizeof(data) ? -EIO : 0);
+		/* Don't breakpoint restartable sequences */
+		if (!rseq_lookup(child, addr)) {
+			ret = access_process_vm(
+				child, addr, &data, sizeof(data), 1);
+			ret = (ret != sizeof(data) ? -EIO : 0);
+		}
 		break;
 
 	case PTRACE_GETEVENTMSG:
diff --git a/kernel/restartable_sequences.c b/kernel/restartable_sequences.c
new file mode 100644
index 0000000..72cfa9b
--- /dev/null
+++ b/kernel/restartable_sequences.c
@@ -0,0 +1,250 @@
+/*
+ * Restartable Sequences are a lightweight interface that allows user-level
+ * code to be executed atomically relative to scheduler preemption.  Typically
+ * used for implementing per-cpu operations.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2015, Google, Inc.,
+ * Paul Turner <pjt@google.com> and Andrew Hunter <ahh@google.com>
+ *
+ */
+
+#ifdef CONFIG_RESTARTABLE_SEQUENCES
+
+#include <linux/uaccess.h>
+#include <linux/preempt.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+
+static void rseq_sched_in_nop(struct preempt_notifier *pn, int cpu) {}
+static void rseq_sched_out_nop(struct preempt_notifier *pn,
+			       struct task_struct *next) {}
+
+static __read_mostly struct preempt_ops rseq_preempt_ops = {
+	.sched_in = rseq_sched_in_nop,
+	.sched_out = rseq_sched_out_nop,
+};
+
+unsigned long rseq_lookup(struct task_struct *p, unsigned long ip)
+{
+	struct task_struct *leader = p->group_leader;
+	struct restartable_sequence_state *rseq_state = &leader->rseq_state;
+	struct restartable_sequence_section *item;
+
+	struct rb_node *node = rseq_state->sections.rb_node;
+
+	while (node) {
+		item = container_of(
+			node, struct restartable_sequence_section, node);
+		if (ip < (unsigned long)item->crit_start)
+			node = node->rb_left;
+		else if (ip >= (unsigned long)item->crit_end)
+			node = node->rb_right;
+		else
+			return (unsigned long)item->crit_restart;
+	}
+
+	return 0;
+}
+
+int rseq_register_cpu_pointer(struct task_struct *p, int __user *cpu_pointer)
+{
+	struct restartable_sequence_state *rseq_state =
+		&p->rseq_state;
+	int registered = 0, rc = 0;
+
+	if (cpu_pointer == rseq_state->cpu_pointer)
+		return 0;
+
+	if (cpu_pointer && !access_ok(VERIFY_WRITE, cpu_pointer, sizeof(int)))
+		return -EINVAL;
+
+	rcu_read_lock();
+	/* Group leader always holds critical section definition. */
+	if (cpu_pointer && !current->group_leader->rseq_state.cpu_pointer &&
+		current->group_leader != p) {
+		rc = -EINVAL;
+		goto out_unlock;
+	}
+	smp_rmb();  /* Pairs with setting group_leaders cpu_pointer */
+
+	if (rseq_state->cpu_pointer)
+		registered = 1;
+	rseq_state->cpu_pointer = cpu_pointer;
+
+	if (cpu_pointer && !registered) {
+		preempt_notifier_inc();
+
+		preempt_notifier_init(&rseq_state->notifier,
+				      &rseq_preempt_ops);
+		preempt_notifier_register(&rseq_state->notifier);
+	} else if (!cpu_pointer && registered) {
+		preempt_notifier_unregister(&rseq_state->notifier);
+
+		preempt_notifier_dec();
+	}
+
+	/* Will update *cpu_pointer on return. */
+	if (cpu_pointer)
+		set_thread_flag(TIF_NOTIFY_RESUME);
+
+out_unlock:
+	rcu_read_unlock();
+
+	return 0;
+}
+
+void rseq_clear_state_exec(struct task_struct *task)
+{
+	struct restartable_sequence_section *section;
+	struct rb_node *node;
+
+	/* Ensure notifier is disabled. */
+	rseq_register_cpu_pointer(task, NULL);
+
+	/* Free and reinit */
+	while ((node = rb_first(&task->rseq_state.sections))) {
+		section = rb_entry(node,
+				struct restartable_sequence_section, node);
+		rb_erase(&section->node, &task->rseq_state.sections);
+		kfree(section);
+	}
+
+	memset(&task->rseq_state, 0, sizeof(task->rseq_state));
+	task->rseq_state.sections = RB_ROOT;
+}
+
+static DEFINE_MUTEX(rseq_state_mutex);
+
+int rseq_register_critical_current(__user void *start, __user void *end,
+				__user void *restart)
+{
+	struct restartable_sequence_state *rseq_state;
+	struct restartable_sequence_section *section;
+	struct rb_node **new, *parent = NULL;
+	int rc = 0;
+
+	rcu_read_lock();
+	/* The critical section is shared by all threads in a process. */
+	rseq_state = &current->group_leader->rseq_state;
+
+	/* Verify section */
+	if (start >= end) {
+		rc = -EINVAL;
+		goto out_rcu;
+	}
+
+	if (!access_ok(VERIFY_READ, start, end - start) ||
+		!access_ok(VERIFY_READ, restart, 1)) {
+		rc = -EINVAL;
+		goto out_rcu;
+	}
+
+	if (rseq_state->cpu_pointer) {
+		rc = -EBUSY;
+		goto out_rcu;
+	}
+
+	new = &(rseq_state->sections.rb_node);
+
+	section = kmalloc(
+		sizeof(struct restartable_sequence_section), GFP_KERNEL);
+	if (!section) {
+		rc = -ENOMEM;
+		goto out_rcu;
+	}
+	section->crit_end = end;
+	section->crit_start = start;
+	section->crit_restart = restart;
+
+	mutex_lock(&rseq_state_mutex);
+
+	while (*new) {
+		struct restartable_sequence_section *this = container_of(
+			*new, struct restartable_sequence_section, node);
+
+		parent = *new;
+		if (section->crit_end <= this->crit_start)
+			new = &((*new)->rb_left);
+		else if (section->crit_start >= this->crit_end)
+			new = &((*new)->rb_right);
+		else {
+			/* Prevent overlapping regions */
+			kfree(section);
+			rc = -EBUSY;
+			goto out_lock;
+		}
+	}
+
+	rb_link_node(&section->node, parent, new);
+	rb_insert_color(&section->node, &rseq_state->sections);
+
+out_lock:
+	mutex_unlock(&rseq_state_mutex);
+out_rcu:
+
+	smp_wmb();  /* synchronize visibility of new section */
+
+	rcu_read_unlock();
+	return rc;
+}
+
+#define SYS_RSEQ_SET_CRITICAL		0
+#define SYS_RSEQ_SET_CPU_POINTER	1
+
+/*
+ * RSEQ syscall interface.
+ *
+ * Usage:
+ *   SYS_RSEQ_SET_CRITICAL, flags, crit_start, crit_end, crit_restart)
+ *    A thread with user rip in (crit_start, crit_end] that has called
+ *    RSEQ_SET_CPU_POINTER will have its execution resumed at crit_restart
+ *    when interrupted by preemption or signal.
+ *
+ *   SYS_RSEQ_SET_CPU_POINTER, flags, cpu_pointer_address
+ *    Configures a (typically per-thread) value, containing the cpu which that
+ *    thread is currently executing on.
+ *    REQUIRES: SYS_RSEQ_SET_CRITICAL must have previously been called.
+ *
+ *  flags is currently unused.
+ */
+SYSCALL_DEFINE5(restartable_sequences,
+		int, op, int, flags, long, val1, long, val2, long, val3)
+{
+	int rc = -EINVAL;
+
+	if (op == SYS_RSEQ_SET_CRITICAL) {
+		/* Defines (process-wide) critical section. */
+		__user void *crit_start = (__user void *)val1;
+		__user void *crit_end = (__user void *)val2;
+		__user void *crit_restart = (__user void *)val3;
+
+		rc = rseq_register_critical_current(
+			crit_start, crit_end, crit_restart);
+	} else if (op == SYS_RSEQ_SET_CPU_POINTER) {
+		/*
+		 * Enables RSEQ for this thread; sets location for CPU update
+		 * to val1.
+		 */
+		int __user *cpu = (int __user *)val1;
+
+		rc = rseq_register_cpu_pointer(current, cpu);
+	}
+
+	return rc;
+}
+#else
+SYSCALL_DEFINE0(restartable_sequences)
+{
+	return -ENOSYS;
+}
+#endif
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 10a8faa..1e192f5 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2112,6 +2112,11 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
 
 	p->numa_group = NULL;
 #endif /* CONFIG_NUMA_BALANCING */
+
+#ifdef CONFIG_RESTARTABLE_SEQUENCES
+	memset(&p->rseq_state, 0, sizeof(p->rseq_state));
+	p->rseq_state.sections = RB_ROOT;
+#endif
 }
 
 #ifdef CONFIG_NUMA_BALANCING
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 6d2a119..c7fb1a6 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -953,6 +953,9 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
 {
 	set_task_rq(p, cpu);
 #ifdef CONFIG_SMP
+	if (rseq_active(p))
+		set_tsk_thread_flag(p, TIF_NOTIFY_RESUME);
+
 	/*
 	 * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be
 	 * successfuly executed on another CPU. We must ensure that updates of
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index a02decf..d396884 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -248,3 +248,6 @@ cond_syscall(sys_execveat);
 
 /* membarrier */
 cond_syscall(sys_membarrier);
+
+/* restartable sequences */
+cond_syscall(sys_restartable_sequences);
-- 
2.4.6


From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S965472AbbJVSHG (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 14:07:06 -0400
Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:15302 "EHLO
	mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK)
	by vger.kernel.org with ESMTP id S965425AbbJVSHD (ORCPT
	<rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 14:07:03 -0400
Date: Thu, 22 Oct 2015 11:06:54 -0700
From: Dave Watson <davejwatson@fb.com>
To: <davejwatson@fb.com>, <kernel-team@fb.com>, <linux-kernel@vger.kernel.org>,
        <linux-api@vger.kernel.org>, <pjt@google.com>,
        <mathieu.desnoyers@efficios.com>
Subject: [RFC PATCH 2/3] restartable sequences: x86 ABI
Message-ID: <b61f16b6a758f10c0e69677e77c5db328fc9c9ab.1445464158.git.davejwatson@fb.com>
References: <cover.1445464158.git.davejwatson@fb.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <cover.1445464158.git.davejwatson@fb.com>
User-Agent: Mutt/1.5.20 (2009-12-10)
X-Originating-IP: [192.168.52.123]
X-Proofpoint-Spam-Reason: safe
X-FB-Internal: Safe
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2015-10-22_12:,,
 signatures=0
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

Implements the x86 (i386 & x86-64) ABIs for interrupting and restarting
execution within restartable sequence sections.

Ptrace is modified to single step over the entire critical region.
---
 arch/x86/entry/common.c                      |  3 ++
 arch/x86/entry/syscalls/syscall_64.tbl       |  1 +
 arch/x86/include/asm/restartable_sequences.h | 44 ++++++++++++++++++++++++++
 arch/x86/kernel/Makefile                     |  2 ++
 arch/x86/kernel/ptrace.c                     |  6 ++--
 arch/x86/kernel/restartable_sequences.c      | 47 ++++++++++++++++++++++++++++
 arch/x86/kernel/signal.c                     | 12 ++++++-
 kernel/restartable_sequences.c               | 11 +++++--
 8 files changed, 120 insertions(+), 6 deletions(-)
 create mode 100644 arch/x86/include/asm/restartable_sequences.h
 create mode 100644 arch/x86/kernel/restartable_sequences.c

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 80dcc92..e817f04 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -24,6 +24,7 @@
 
 #include <asm/desc.h>
 #include <asm/traps.h>
+#include <asm/restartable_sequences.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
@@ -253,6 +254,8 @@ __visible void prepare_exit_to_usermode(struct pt_regs *regs)
 		if (cached_flags & _TIF_NOTIFY_RESUME) {
 			clear_thread_flag(TIF_NOTIFY_RESUME);
 			tracehook_notify_resume(regs);
+			if (rseq_active(current))
+				arch_rseq_handle_notify_resume(regs);
 		}
 
 		if (cached_flags & _TIF_USER_RETURN_NOTIFY)
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 278842f..0fd4243 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -331,6 +331,7 @@
 322	64	execveat		stub_execveat
 323	common	userfaultfd		sys_userfaultfd
 324	common	membarrier		sys_membarrier
+325	common	restartable_sequences	sys_restartable_sequences
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/arch/x86/include/asm/restartable_sequences.h b/arch/x86/include/asm/restartable_sequences.h
new file mode 100644
index 0000000..c0bcab2
--- /dev/null
+++ b/arch/x86/include/asm/restartable_sequences.h
@@ -0,0 +1,44 @@
+#ifndef _ASM_X86_RESTARTABLE_SEQUENCES_H
+#define _ASM_X86_RESTARTABLE_SEQUENCES_H
+
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_RESTARTABLE_SEQUENCES
+
+static inline unsigned long arch_rseq_in_crit_section(struct task_struct *p,
+						struct pt_regs *regs)
+{
+	unsigned long ip = (unsigned long)regs->ip;
+
+	return rseq_lookup(p, ip);
+}
+
+static inline bool arch_rseq_needs_notify_resume(struct task_struct *p)
+{
+#ifdef CONFIG_PREEMPT
+	/*
+	 * Under CONFIG_PREEMPT it's possible for regs to be incoherent in the
+	 * case that we took an interrupt during syscall entry.  Avoid this by
+	 * always deferring to our notify-resume handler.
+	 */
+	return true;
+#else
+	return arch_rseq_in_crit_section(p, task_pt_regs(p));
+#endif
+}
+
+void arch_rseq_handle_notify_resume(struct pt_regs *regs);
+void arch_rseq_check_critical_section(struct task_struct *p,
+				      struct pt_regs *regs);
+
+#else /* !CONFIG_RESTARTABLE_SEQUENCES */
+
+static inline void arch_rseq_handle_notify_resume(struct pt_regs *regs) {}
+static inline void arch_rseq_check_critical_section(struct task_struct *p,
+						    struct pt_regs *regs) {}
+
+#endif
+
+#endif /* _ASM_X86_RESTARTABLE_SEQUENCES_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index b1b78ff..ee98fb6 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -110,6 +110,8 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 
+obj-$(CONFIG_RESTARTABLE_SEQUENCES)	+= restartable_sequences.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 558f50e..934aeaf 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1439,6 +1439,8 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
 	struct siginfo info;
 
 	fill_sigtrap_info(tsk, regs, error_code, si_code, &info);
-	/* Send us the fake SIGTRAP */
-	force_sig_info(SIGTRAP, &info, tsk);
+	/* Don't single step in to a restartable sequence */
+	if (!rseq_lookup(tsk, (unsigned long)regs->ip))
+		/* Send us the fake SIGTRAP */
+		force_sig_info(SIGTRAP, &info, tsk);
 }
diff --git a/arch/x86/kernel/restartable_sequences.c b/arch/x86/kernel/restartable_sequences.c
new file mode 100644
index 0000000..330568a
--- /dev/null
+++ b/arch/x86/kernel/restartable_sequences.c
@@ -0,0 +1,47 @@
+/*
+ * Restartable Sequences: x86 ABI.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2015, Google, Inc.,
+ * Paul Turner <pjt@google.com> and Andrew Hunter <ahh@google.com>
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/restartable_sequences.h>
+#include <asm/restartable_sequences.h>
+
+void arch_rseq_check_critical_section(struct task_struct *p,
+				      struct pt_regs *regs)
+{
+	unsigned long ip = arch_rseq_in_crit_section(p, regs);
+
+	if (!ip)
+		return;
+
+	/* RSEQ only applies to user-mode execution */
+	BUG_ON(!user_mode(regs));
+
+	regs->ip = ip;
+}
+
+void arch_rseq_handle_notify_resume(struct pt_regs *regs)
+{
+	struct restartable_sequence_state *rseq_state = &current->rseq_state;
+
+	/* If this update fails our user-state is incoherent. */
+	if (put_user(task_cpu(current), rseq_state->cpu_pointer))
+		force_sig(SIGSEGV, current);
+
+	arch_rseq_check_critical_section(current, regs);
+}
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index da52e6b..1516e5d 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -30,6 +30,7 @@
 #include <asm/fpu/signal.h>
 #include <asm/vdso.h>
 #include <asm/mce.h>
+#include <asm/restartable_sequences.h>
 #include <asm/sighandling.h>
 #include <asm/vm86.h>
 
@@ -377,7 +378,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
 		 */
 		put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
 	} put_user_catch(err);
-	
+
 	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
 				regs, set->sig[0]);
@@ -613,6 +614,15 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
 	sigset_t *set = sigmask_to_save();
 	compat_sigset_t *cset = (compat_sigset_t *) set;
 
+	/*
+	 * If we are executing in the critical section of a restartable
+	 * sequence we need to fix up the user's stack saved ip at this point
+	 * so that signal handler return does not allow us to jump back into
+	 * the block across a context switch boundary.
+	 */
+	if (rseq_active(current))
+		arch_rseq_check_critical_section(current, regs);
+
 	/* Set up the stack frame */
 	if (is_ia32_frame()) {
 		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
diff --git a/kernel/restartable_sequences.c b/kernel/restartable_sequences.c
index 72cfa9b..87e63e2 100644
--- a/kernel/restartable_sequences.c
+++ b/kernel/restartable_sequences.c
@@ -20,18 +20,23 @@
 
 #ifdef CONFIG_RESTARTABLE_SEQUENCES
 
+#include <asm/restartable_sequences.h>
 #include <linux/uaccess.h>
 #include <linux/preempt.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 
 static void rseq_sched_in_nop(struct preempt_notifier *pn, int cpu) {}
-static void rseq_sched_out_nop(struct preempt_notifier *pn,
-			       struct task_struct *next) {}
+static void rseq_sched_out(struct preempt_notifier *pn,
+			   struct task_struct *next)
+{
+	if (arch_rseq_needs_notify_resume(current))
+		set_thread_flag(TIF_NOTIFY_RESUME);
+}
 
 static __read_mostly struct preempt_ops rseq_preempt_ops = {
 	.sched_in = rseq_sched_in_nop,
-	.sched_out = rseq_sched_out_nop,
+	.sched_out = rseq_sched_out,
 };
 
 unsigned long rseq_lookup(struct task_struct *p, unsigned long ip)
-- 
2.4.6


From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S965489AbbJVSHU (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 14:07:20 -0400
Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:13223 "EHLO
	mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK)
	by vger.kernel.org with ESMTP id S965425AbbJVSHO (ORCPT
	<rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 14:07:14 -0400
Date: Thu, 22 Oct 2015 11:07:06 -0700
From: Dave Watson <davejwatson@fb.com>
To: <davejwatson@fb.com>, <kernel-team@fb.com>, <linux-kernel@vger.kernel.org>,
        <linux-api@vger.kernel.org>, <pjt@google.com>,
        <mathieu.desnoyers@efficios.com>
Subject: [RFC PATCH 3/3] restartable sequences: basic user-space self-tests
Message-ID: <8599a58de3220519f4311c7f6267ff0d87087a8a.1445464158.git.davejwatson@fb.com>
References: <cover.1445464158.git.davejwatson@fb.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <cover.1445464158.git.davejwatson@fb.com>
User-Agent: Mutt/1.5.20 (2009-12-10)
X-Originating-IP: [192.168.52.123]
X-Proofpoint-Spam-Reason: safe
X-FB-Internal: Safe
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2015-10-22_12:,,
 signatures=0
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

    Implements basic tests of RSEQ functionality.

    "basic_percpu_ops_test" implements a few simple per-cpu operations and
    testing their correctness.
---
 tools/testing/selftests/rseq/Makefile              |  14 +
 .../testing/selftests/rseq/basic_percpu_ops_test.c | 331 +++++++++++++++++++++
 tools/testing/selftests/rseq/rseq.c                |  48 +++
 tools/testing/selftests/rseq/rseq.h                |  17 ++
 4 files changed, 410 insertions(+)
 create mode 100644 tools/testing/selftests/rseq/Makefile
 create mode 100644 tools/testing/selftests/rseq/basic_percpu_ops_test.c
 create mode 100644 tools/testing/selftests/rseq/rseq.c
 create mode 100644 tools/testing/selftests/rseq/rseq.h

diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile
new file mode 100644
index 0000000..3a9cb5c
--- /dev/null
+++ b/tools/testing/selftests/rseq/Makefile
@@ -0,0 +1,14 @@
+CFLAGS += -Wall
+LDFLAGS += -lpthread
+
+TESTS = basic_test basic_percpu_ops_test
+
+basic_percpu_ops_test: basic_percpu_ops_test.c
+
+
+all: $(TESTS)
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $^ rseq.c $(LDFLAGS)
+
+clean:
+	$(RM) $(TESTS)
diff --git a/tools/testing/selftests/rseq/basic_percpu_ops_test.c b/tools/testing/selftests/rseq/basic_percpu_ops_test.c
new file mode 100644
index 0000000..63a668d
--- /dev/null
+++ b/tools/testing/selftests/rseq/basic_percpu_ops_test.c
@@ -0,0 +1,331 @@
+#define _GNU_SOURCE
+#include <assert.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rseq.h"
+
+#if defined(__x86_64__)
+
+#define barrier() {__asm__ __volatile__("" : : : "memory"); }
+
+struct rseq_section {
+	void *begin;
+	void *end;
+	void *restart;
+};
+
+extern struct rseq_section const __start___rseq_sections[]
+__attribute((weak));
+extern struct rseq_section const __stop___rseq_sections[]
+__attribute((weak));
+
+/* Implemented by percpu_ops.S */
+struct percpu_lock {
+	int word[CPU_SETSIZE][16];  /* cache aligned; lock-word is [cpu][0] */
+};
+
+/* A simple percpu spinlock.  Returns the cpu lock was acquired on. */
+int rseq_percpu_lock(struct percpu_lock *lock)
+{
+	int out = -1;
+
+	asm volatile (
+		"1:\n\t"
+		"movl %1, %0\n\t"
+		"leaq (,%0,8), %%r10\n\t"
+		"leaq (%2, %%r10, 8), %%r10\n\t"
+		"2:\n\t"
+		"cmpl $0, (%%r10)\n\t"
+		"jne 2b\n\t"
+		"movl $1, (%%r10)\n\t"
+		"3:\n\t"
+		".pushsection __rseq_sections, \"a\"\n\t"
+		".quad 1b, 3b, 1b\n\t"
+		".popsection\n\t"
+		: "+r" (out)
+		: "m" (__rseq_current_cpu), "r" ((unsigned long)lock)
+		: "memory", "r10");
+	return out;
+}
+
+/*
+ * cmpxchg [with an additional check value].
+ *
+ * Returns:
+ *  -1 if *p != old or cpu != current cpu [ || check_ptr != check_val, ]
+ * otherwise 0.
+ *
+ * Note: When specified, check_ptr is dereferenced iff *p == old
+ */
+int rseq_percpu_cmpxchg(int cpu, intptr_t *p, intptr_t old, intptr_t new)
+{
+	asm volatile goto (
+		"1:\n\t"
+		"cmpl %1, %0\n\t"
+		"jne %l[fail]\n\t"
+		"cmpq %2, %3\n\t"
+		"jne %l[fail]\n\t"
+		"movq %4, %3\n\t"
+		"2:\n\t"
+		".pushsection __rseq_sections, \"a\"\n\t"
+		".quad 1b, 2b, 1b\n\t"
+		".popsection\n\t"
+		:
+		: "r" (cpu), "m" (__rseq_current_cpu),
+		  "r" (old), "m" (*p), "r" (new)
+		: "memory"
+		: fail);
+	return 0;
+fail:
+	return -1;
+}
+int rseq_percpu_cmpxchgcheck(int cpu, intptr_t *p, intptr_t old, intptr_t new,
+			intptr_t *check_ptr, intptr_t check_val)
+{
+	asm volatile goto (
+		"1:\n\t"
+		"cmpl %1, %0\n\t"
+		"jne %l[fail]\n\t"
+		"cmpq %2, %3\n\t"
+		"jne %l[fail]\n\t"
+		"cmpq %5, %6\n\t"
+		"jne %l[fail]\n\t"
+		"movq %4, %3\n\t"
+		"2:\n\t"
+		".pushsection __rseq_sections, \"a\"\n\t"
+		".quad 1b, 2b, 1b\n\t"
+		".popsection\n\t"
+		:
+		: "r" (cpu), "m" (__rseq_current_cpu),
+		  "r" (old), "m" (*p), "r" (new),
+		  "r" (check_val), "m" (*check_ptr)
+		: "memory"
+		: fail);
+	return 0;
+fail:
+	return -1;
+}
+
+
+void rseq_percpu_unlock(struct percpu_lock *lock, int cpu)
+{
+	barrier();  /* need a release-store here, this suffices on x86. */
+	assert(lock->word[cpu][0] == 1);
+	lock->word[cpu][0] = 0;
+}
+
+void rseq_unknown_restart_addr(void *addr)
+{
+	fprintf(stderr, "rseq: unrecognized restart address %p\n", addr);
+	exit(1);
+}
+
+struct spinlock_test_data {
+	struct percpu_lock lock;
+	int counts[CPU_SETSIZE];
+	int reps;
+};
+
+void *test_percpu_spinlock_thread(void *arg)
+{
+	struct spinlock_test_data *data = arg;
+	int i, cpu;
+
+	rseq_configure_cpu_pointer();
+	for (i = 0; i < data->reps; i++) {
+		cpu = rseq_percpu_lock(&data->lock);
+		data->counts[cpu]++;
+		rseq_percpu_unlock(&data->lock, cpu);
+	}
+
+	return 0;
+}
+
+/*
+ * A simple test which implements a sharded counter using a per-cpu lock.
+ * Obviously real applications might prefer to simply use a per-cpu increment;
+ * however, this is reasonable for a test and the lock can be extended to
+ * synchronize more complicated operations.
+ */
+void test_percpu_spinlock(void)
+{
+	int i, sum;
+	pthread_t test_threads[200];
+	struct spinlock_test_data data;
+
+	memset(&data, 0, sizeof(data));
+	data.reps = 5000;
+
+	for (i = 0; i < 200; i++)
+		pthread_create(&test_threads[i], NULL,
+			       test_percpu_spinlock_thread, &data);
+
+	for (i = 0; i < 200; i++)
+		pthread_join(test_threads[i], NULL);
+
+	sum = 0;
+	for (i = 0; i < CPU_SETSIZE; i++)
+		sum += data.counts[i];
+
+	assert(sum == data.reps * 200);
+}
+
+struct percpu_list_node {
+	intptr_t data;
+	struct percpu_list_node *next;
+};
+
+struct percpu_list {
+	struct percpu_list_node *heads[CPU_SETSIZE];
+};
+
+int percpu_list_push(struct percpu_list *list, struct percpu_list_node *node)
+{
+	int cpu;
+
+	do {
+		cpu = rseq_current_cpu();
+		node->next = list->heads[cpu];
+	} while (0 != rseq_percpu_cmpxchg(
+			cpu,
+			(intptr_t *)&list->heads[cpu], (intptr_t)node->next,
+			(intptr_t)node));
+
+	return cpu;
+}
+
+struct percpu_list_node *percpu_list_pop(struct percpu_list *list)
+{
+	int cpu;
+	struct percpu_list_node *head, *next;
+
+	do {
+		cpu = rseq_current_cpu();
+		head = list->heads[cpu];
+		/*
+		 * Unlike a traditional lock-less linked list; the availability
+		 * of a cmpxchg-check primitive allows us to implement pop
+		 * without concerns over ABA-type races.
+		 */
+		if (!head)
+			return 0;
+		next = head->next;
+	} while (0 != rseq_percpu_cmpxchgcheck(cpu,
+		(intptr_t *)&list->heads[cpu], (intptr_t)head, (intptr_t)next,
+		(intptr_t *)&head->next, (intptr_t)next));
+
+	return head;
+}
+
+
+void *test_percpu_list_thread(void *arg)
+{
+	int i;
+	struct percpu_list *list = (struct percpu_list *)arg;
+
+	rseq_configure_cpu_pointer();
+	for (i = 0; i < 100000; i++) {
+		struct percpu_list_node *node = percpu_list_pop(list);
+
+		sched_yield();  /* encourage shuffling */
+		if (node)
+			percpu_list_push(list, node);
+	}
+
+	return 0;
+}
+
+/*
+ * Implements a per-cpu linked list then shuffles it via popping and pushing
+ * from many threads.
+ */
+void test_percpu_list(void)
+{
+	int i, j;
+	long sum = 0, expected_sum = 0;
+	struct percpu_list list;
+	pthread_t test_threads[200];
+	cpu_set_t allowed_cpus;
+
+	memset(&list, 0, sizeof(list));
+
+	/* Generate list entries for every usable cpu. */
+	sched_getaffinity(0, sizeof(allowed_cpus), &allowed_cpus);
+	for (i = 0; i < CPU_SETSIZE; i++) {
+		if (!CPU_ISSET(i, &allowed_cpus))
+			continue;
+		for (j = 1; j <= 100; j++) {
+			struct percpu_list_node *node;
+
+			expected_sum += j;
+
+			node = malloc(sizeof(*node));
+			assert(node);
+			node->data = j;
+			node->next = list.heads[i];
+			list.heads[i] = node;
+		}
+	}
+
+	for (i = 0; i < 200; i++)
+		assert(pthread_create(&test_threads[i], NULL,
+			       test_percpu_list_thread, &list) == 0);
+
+	for (i = 0; i < 200; i++)
+		pthread_join(test_threads[i], NULL);
+
+	for (i = 0; i < CPU_SETSIZE; i++) {
+		cpu_set_t pin_mask;
+		struct percpu_list_node *node;
+
+		if (!CPU_ISSET(i, &allowed_cpus))
+			continue;
+
+		CPU_ZERO(&pin_mask);
+		CPU_SET(i, &pin_mask);
+		sched_setaffinity(0, sizeof(pin_mask), &pin_mask);
+
+		while ((node = percpu_list_pop(&list))) {
+			sum += node->data;
+			free(node);
+		}
+	}
+
+	/*
+	 * All entries should now be accounted for (unless some external actor
+	 * is interfering with our allowed affinity while this test is
+	 * running).
+	 */
+	assert(sum == expected_sum);
+}
+
+int main(int argc, char **argv)
+{
+	const struct rseq_section *iter;
+
+	for (iter = __start___rseq_sections;
+	     iter < __stop___rseq_sections;
+	     iter++) {
+		rseq_configure_region(iter->begin, iter->end, iter->restart);
+		printf("Installing region %p, %p\n", iter->begin, iter->end);
+	}
+	rseq_configure_cpu_pointer();
+
+	test_percpu_spinlock();
+	test_percpu_list();
+
+	return 0;
+}
+
+#else
+int main(int argc, char **argv)
+{
+	fprintf(stderr, "architecture not supported\n");
+	return 0;
+}
+#endif
diff --git a/tools/testing/selftests/rseq/rseq.c b/tools/testing/selftests/rseq/rseq.c
new file mode 100644
index 0000000..4dc5059
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq.c
@@ -0,0 +1,48 @@
+#define _GNU_SOURCE
+#include <assert.h>
+#include <errno.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "rseq.h"
+
+__thread volatile const int __rseq_current_cpu = -1;
+
+#define __NR_rseq	323
+#define SYS_RSEQ_SET_CRITICAL		0
+#define SYS_RSEQ_SET_CPU_POINTER	1
+
+int sys_rseq(int op, int flags, void *val1, void *val2, void *val3)
+{
+	return syscall(__NR_rseq, op, flags,
+		(intptr_t)val1, (intptr_t)val2, (intptr_t)val3);
+}
+
+static void sys_rseq_checked(int op, int flags,
+			void *val1, void *val2, void *val3)
+{
+	int rc = sys_rseq(op, flags, val1, val2, val3);
+
+	if (rc) {
+		fprintf(stderr, "sys_rseq(%d, %d, %p, %p, %p) failed(%d): %s\n",
+			op, flags, val1, val2, val3, errno, strerror(errno));
+		exit(1);
+	}
+}
+
+void rseq_configure_region(void *rseq_text_start, void *rseq_text_end,
+			void *rseq_text_restart)
+{
+	sys_rseq_checked(SYS_RSEQ_SET_CRITICAL, 0,
+			rseq_text_start, rseq_text_end, rseq_text_restart);
+}
+
+void rseq_configure_cpu_pointer(void)
+{
+	sys_rseq_checked(SYS_RSEQ_SET_CPU_POINTER, 0,
+			(void *)&__rseq_current_cpu, 0, 0);
+	assert(rseq_current_cpu() != -1); /* always updated prior to return. */
+}
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
new file mode 100644
index 0000000..e12db18
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -0,0 +1,17 @@
+#ifndef RSEQ_TEST_H
+#define RSEQ_TEST_H
+
+int sys_rseq(int op, int flags, void *val1, void *val2, void *val3);
+/* RSEQ provided thread-local current_cpu */
+
+void rseq_configure_cpu_pointer(void);
+
+void rseq_configure_region(void *rseq_text_start, void *rseq_text_end,
+	void *rseq_text_restart);
+
+extern __thread volatile const int __rseq_current_cpu;
+static inline int rseq_current_cpu(void) { return __rseq_current_cpu; }
+
+void run_tests(void);
+
+#endif
-- 
2.4.6


From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S965836AbbJVSyh (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 14:54:37 -0400
Received: from mga14.intel.com ([192.55.52.115]:32264 "EHLO mga14.intel.com"
	rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP
	id S965790AbbJVSyJ (ORCPT <rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 14:54:09 -0400
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.20,183,1444719600"; 
   d="scan'208";a="800450571"
Date: Fri, 23 Oct 2015 02:53:41 +0800
From: kbuild test robot <lkp@intel.com>
To: Dave Watson <davejwatson@fb.com>
Cc: kbuild-all@01.org, davejwatson@fb.com, kernel-team@fb.com,
        linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
        pjt@google.com, mathieu.desnoyers@efficios.com
Subject: Re: [RFC PATCH 1/3] restartable sequences: user-space per-cpu
 critical sections
Message-ID: <201510230203.337YMkHy%fengguang.wu@intel.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <581c0b6403285219724961a3d250c6d95dfacea7.1445464158.git.davejwatson@fb.com>
User-Agent: Mutt/1.5.23 (2014-03-12)
X-SA-Exim-Connect-IP: <locally generated>
X-SA-Exim-Mail-From: fengguang.wu@intel.com
X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

Hi Dave,

[auto build test WARNING on v4.3-rc6 -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Dave-Watson/restartable-sequences-benchmarks/20151023-020939
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
   include/linux/radix-tree.h:212:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
--
   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
--
   mm/page_alloc.c:6010:1: sparse: directive in argument list
   mm/page_alloc.c:6012:1: sparse: directive in argument list
   mm/page_alloc.c:6019:1: sparse: directive in argument list
   mm/page_alloc.c:6021:1: sparse: directive in argument list
   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
--
   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
   include/linux/radix-tree.h:212:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:196:16: sparse: incompatible types in comparison expression (different address spaces)
--
   mm/debug.c:176:1: sparse: directive in argument list
   mm/debug.c:178:1: sparse: directive in argument list
   mm/debug.c:187:1: sparse: directive in argument list
   mm/debug.c:189:1: sparse: directive in argument list
   mm/debug.c:190:1: sparse: directive in argument list
   mm/debug.c:192:1: sparse: directive in argument list
   mm/debug.c:194:1: sparse: directive in argument list
   mm/debug.c:196:1: sparse: directive in argument list
   mm/debug.c:197:1: sparse: directive in argument list
   mm/debug.c:199:1: sparse: directive in argument list
   mm/debug.c:200:1: sparse: directive in argument list
   mm/debug.c:202:1: sparse: directive in argument list
   mm/debug.c:206:1: sparse: directive in argument list
   mm/debug.c:208:1: sparse: directive in argument list
   mm/debug.c:221:1: sparse: directive in argument list
   mm/debug.c:223:1: sparse: directive in argument list
   mm/debug.c:224:1: sparse: directive in argument list
   mm/debug.c:226:1: sparse: directive in argument list
   mm/debug.c:228:1: sparse: directive in argument list
   mm/debug.c:230:1: sparse: directive in argument list
   mm/debug.c:231:1: sparse: directive in argument list
   mm/debug.c:233:1: sparse: directive in argument list
   mm/debug.c:234:1: sparse: directive in argument list
   mm/debug.c:236:1: sparse: directive in argument list
   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
--
   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
   include/linux/radix-tree.h:212:16: sparse: incompatible types in comparison expression (different address spaces)
   include/linux/radix-tree.h:212:16: sparse: incompatible types in comparison expression (different address spaces)
--
   include/linux/sched.h:1189:34: sparse: Expected ) in function declarator
   include/linux/sched.h:1189:34: sparse: got (
>> builtin:0:0: sparse: expected ; at end of declaration
   include/linux/sched.h:1190:1: sparse: Expected ; at the end of type declaration
   include/linux/sched.h:1190:1: sparse: got }
   mm/memcontrol.c:3289:21: sparse: incompatible types in comparison expression (different address spaces)
   mm/memcontrol.c:3291:21: sparse: incompatible types in comparison expression (different address spaces)
   mm/memcontrol.c:4861:23: sparse: incompatible types in comparison expression (different address spaces)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S965624AbbJVTMK (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 15:12:10 -0400
Received: from mail-oi0-f50.google.com ([209.85.218.50]:36727 "EHLO
	mail-oi0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
	with ESMTP id S965180AbbJVTME (ORCPT
	<rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 15:12:04 -0400
MIME-Version: 1.0
In-Reply-To: <cover.1445464158.git.davejwatson@fb.com>
References: <cover.1445464158.git.davejwatson@fb.com>
From: Andy Lutomirski <luto@amacapital.net>
Date: Thu, 22 Oct 2015 12:11:42 -0700
Message-ID: <CALCETrWXR0BMeEygiLoT5gbyYpGxren_Fch=S4RSryfqwdxH8g@mail.gmail.com>
Subject: Re: [RFC PATCH 0/3] restartable sequences benchmarks
To: Dave Watson <davejwatson@fb.com>
Cc: kernel-team@fb.com,
        "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
        Linux API <linux-api@vger.kernel.org>, Paul Turner <pjt@google.com>,
        Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Content-Type: text/plain; charset=UTF-8
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

On Thu, Oct 22, 2015 at 11:06 AM, Dave Watson <davejwatson@fb.com> wrote:
> We've been testing out restartable sequences + malloc changes for use
> at Facebook.  Below are some test results, as well as some possible
> changes based on Paul Turner's original patches

Thanks!  I'll stare at this some time between now and Kernel Summit.

>
> https://lkml.org/lkml/2015/6/24/665
>
> I ran one service with several permutations of various mallocs.  The
> service is CPU-bound, and hits the allocator quite hard.  Requests/s
> are held constant at the source, so we use cpu idle time and latency
> as an indicator of service quality. These are average numbers over
> several hours.  Machines were dual E5-2660, total 16 cores +
> hyperthreading.  This service has ~400 total threads, 70-90 of which
> are doing work at any particular time.
>
>                                    RSS CPUIDLE LATENCYMS
> jemalloc 4.0.0                     31G   33%     390
> jemalloc + this patch              25G   33%     390
> jemalloc + this patch using lsl    25G   30%     420
> jemalloc + PT's rseq patch         25G   32%     405
> glibc malloc 2.20                  27G   30%     420
> tcmalloc gperftools trunk (2.2)    21G   30%     480

Slightly confused.  This is showing a space efficiency improvement but
not a performance improvement?  Is the idea that percpu free lists are
more space efficient than per-thread free lists?

>
> jemalloc rseq patch used for testing:
> https://github.com/djwatson/jemalloc
>
> lsl test - using lsl segment limit to get cpu (i.e. inlined vdso
> getcpu on x86) instead of using the thread caching as in this patch.
> There has been some suggestions to add the thread-cached getcpu()
> feature separately.  It does seem to move the needle in a real service
> by about ~3% to have a thread-cached getcpu vs. not.  I don't think we
> can use restartable sequences in production without a faster getcpu.

If nothing else, I'd like to replace the thread-cached getcpu thing
with percpu gsbase, at least on x86.  That doesn't necessarily have to
be exclusive with restartable sequences.

>
> GS-segment / migration only tests
>
> There's been some interest in seeing if we can do this with only gs
> segment, here's some numbers for those.  This doesn't have to be gs,
> it could just be a migration signal sent to userspace as well, the
> same approaches would apply.
>
> GS patch: https://lkml.org/lkml/2014/9/13/59
>
>                                    RSS CPUIDLE LATENCYMS
> jemalloc 4.0.0                     31G   33%     390
> jemalloc + percpu locking          25G   25%     420
> jemalloc + preempt lock / signal   25G   32%     415

Neat!

--Andy

From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S1757794AbbJVTgE (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 15:36:04 -0400
Received: from mga09.intel.com ([134.134.136.24]:28822 "EHLO mga09.intel.com"
	rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP
	id S1757204AbbJVTgC (ORCPT <rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 15:36:02 -0400
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.20,184,1444719600"; 
   d="gz'50?scan'50,208,50";a="817261500"
Date: Fri, 23 Oct 2015 03:35:27 +0800
From: kbuild test robot <lkp@intel.com>
To: Dave Watson <davejwatson@fb.com>
Cc: kbuild-all@01.org, davejwatson@fb.com, kernel-team@fb.com,
        linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
        pjt@google.com, mathieu.desnoyers@efficios.com
Subject: Re: [RFC PATCH 1/3] restartable sequences: user-space per-cpu
 critical sections
Message-ID: <201510230345.MJYgQ3C1%fengguang.wu@intel.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="3MwIy2ne0vdjdPXF"
Content-Disposition: inline
In-Reply-To: <581c0b6403285219724961a3d250c6d95dfacea7.1445464158.git.davejwatson@fb.com>
User-Agent: Mutt/1.5.23 (2014-03-12)
X-SA-Exim-Connect-IP: <locally generated>
X-SA-Exim-Mail-From: fengguang.wu@intel.com
X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org


--3MwIy2ne0vdjdPXF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi Dave,

[auto build test ERROR on v4.3-rc6 -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Dave-Watson/restartable-sequences-benchmarks/20151023-020939
config: openrisc-allmodconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=openrisc 

All errors (new ones prefixed by >>):

   In file included from include/asm-generic/unistd.h:1:0,
                    from arch/openrisc/include/uapi/asm/unistd.h:26,
                    from arch/openrisc/kernel/sys_call_table.c:27:
>> include/uapi/asm-generic/unistd.h:717:1: error: 'sys_restartable_sequences' undeclared here (not in a function)

vim +/sys_restartable_sequences +717 include/uapi/asm-generic/unistd.h

   711	__SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat)
   712	#define __NR_userfaultfd 282
   713	__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
   714	#define __NR_membarrier 283
   715	__SYSCALL(__NR_membarrier, sys_membarrier)
   716	#define __NR_restartable_sequences 284
 > 717	__SYSCALL(__NR_restartable_sequences, sys_restartable_sequences)
   718	
   719	#undef __NR_syscalls
   720	#define __NR_syscalls 285

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

--3MwIy2ne0vdjdPXF
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=".config.gz"
Content-Transfer-Encoding: base64

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

--3MwIy2ne0vdjdPXF--

From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <linux-kernel-owner@vger.kernel.org>
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S1758152AbbJVWLG (ORCPT <rfc822;w@1wt.eu>);
	Thu, 22 Oct 2015 18:11:06 -0400
Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:25167 "EHLO
	mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK)
	by vger.kernel.org with ESMTP id S1752153AbbJVWLE (ORCPT
	<rfc822;linux-kernel@vger.kernel.org>);
	Thu, 22 Oct 2015 18:11:04 -0400
Date: Thu, 22 Oct 2015 15:10:54 -0700
From: Dave Watson <davejwatson@fb.com>
To: Andy Lutomirski <luto@amacapital.net>
CC: <kernel-team@fb.com>,
        "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
        Linux API <linux-api@vger.kernel.org>, Paul Turner <pjt@google.com>,
        Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Subject: Re: [RFC PATCH 0/3] restartable sequences benchmarks
Message-ID: <20151022221054.GA2949757@devbig217.prn1.facebook.com>
References: <cover.1445464158.git.davejwatson@fb.com>
 <CALCETrWXR0BMeEygiLoT5gbyYpGxren_Fch=S4RSryfqwdxH8g@mail.gmail.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <CALCETrWXR0BMeEygiLoT5gbyYpGxren_Fch=S4RSryfqwdxH8g@mail.gmail.com>
User-Agent: Mutt/1.5.20 (2009-12-10)
X-Originating-IP: [192.168.52.123]
X-Proofpoint-Spam-Reason: safe
X-FB-Internal: Safe
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2015-10-23_01:,,
 signatures=0
Sender: linux-kernel-owner@vger.kernel.org
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org

On Thu, Oct 22, 2015 at 12:11:42PM -0700, Andy Lutomirski wrote:
> On Thu, Oct 22, 2015 at 11:06 AM, Dave Watson <davejwatson@fb.com> wrote:
> >
> >                                    RSS CPUIDLE LATENCYMS
> > jemalloc 4.0.0                     31G   33%     390
> > jemalloc + this patch              25G   33%     390
> > jemalloc + this patch using lsl    25G   30%     420
> > jemalloc + PT's rseq patch         25G   32%     405
> > glibc malloc 2.20                  27G   30%     420
> > tcmalloc gperftools trunk (2.2)    21G   30%     480
> 
> Slightly confused.  This is showing a space efficiency improvement but
> not a performance improvement?  Is the idea that percpu free lists are
> more space efficient than per-thread free lists?
> 
> --Andy

Correct - the service was already tuned such that most requests hit
the (very large) thread free lists to avoided taking expensive locks
talking to the central arena.  There were more threads than cpus, so
the memory win is just needing fewer free lists. 

