Thread (60 messages) 60 messages, 8 authors, 2018-04-03

Re: [RFC PATCH for 4.17 02/21] rseq: Introduce restartable sequences system call (v12)

From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date: 2018-03-28 14:06:14
Also in: lkml

----- On Mar 28, 2018, at 2:47 AM, Boqun Feng boqun.feng@gmail.com wrote:
On Tue, Mar 27, 2018 at 12:05:23PM -0400, Mathieu Desnoyers wrote:
[...]
quoted
Changes since v11:

- Replace task struct rseq_preempt, rseq_signal, and rseq_migrate
  bool by u32 rseq_event_mask.
[...]
quoted
@@ -979,6 +980,17 @@ struct task_struct {
 	unsigned long			numa_pages_migrated;
 #endif /* CONFIG_NUMA_BALANCING */
 
+#ifdef CONFIG_RSEQ
+	struct rseq __user *rseq;
+	u32 rseq_len;
+	u32 rseq_sig;
+	/*
+	 * RmW on rseq_event_mask must be performed atomically
+	 * with respect to preemption.
+	 */
+	unsigned long rseq_event_mask;
s/unsigned long/u32
good point, fixed.
quoted
+#endif
+
 	struct tlbflush_unmap_batch	tlb_ubc;
 
 	struct rcu_head			rcu;
@@ -1688,4 +1700,110 @@ extern long sched_getaffinity(pid_t pid, struct cpumask
*mask);
 #define TASK_SIZE_OF(tsk)	TASK_SIZE
 #endif
 
[...]
quoted
+
+static int rseq_ip_fixup(struct pt_regs *regs)
+{
+	unsigned long ip = instruction_pointer(regs), start_ip = 0,
+		post_commit_offset = 0, abort_ip = 0;
+	struct task_struct *t = current;
+	uint32_t cs_flags = 0;
+	bool in_rseq_cs = false;
This seems unnecessary? Because..
quoted
+	int ret;
+
+	ret = rseq_get_rseq_cs(t, &start_ip, &post_commit_offset, &abort_ip,
+			&cs_flags);
+	if (ret)
+		return ret;
+
+	/*
+	 * Handle potentially not being within a critical section.
+	 * Unsigned comparison will be true when
+	 * ip >= start_ip, and when ip < start_ip + post_commit_offset.
+	 */
+	if (ip - start_ip < post_commit_offset)
+		in_rseq_cs = true;
+
+	/*
+	 * If not nested over a rseq critical section, restart is
+	 * useless. Clear the rseq_cs pointer and return.
+	 */
+	if (!in_rseq_cs)
+		return clear_rseq_cs(t);
we can write

if (ip - start_ip >= post_commit_offset)
	return clear_rseq_cs(t);
Good point. In a previous version, rseq_get_rseq_cs() had to conditionally
update in_rseq_cs, but it's not the case anymore, so your approach
indeed cleans up the code.

Thanks!

Mathieu
Regards,
Boqun
quoted
+	ret = rseq_need_restart(t, cs_flags);
+	if (ret <= 0)
+		return ret;
+	ret = clear_rseq_cs(t);
+	if (ret)
+		return ret;
+	trace_rseq_ip_fixup(ip, start_ip, post_commit_offset, abort_ip);
+	instruction_pointer_set(regs, (unsigned long)abort_ip);
+	return 0;
+}
+
[...]
-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help