From: Ingo Molnar <mingo@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: Andrew Morton <akpm@linux-foundation.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Mike Galbraith <efault@gmx.de>, Oleg Nesterov <oleg@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH 03/89] sched/rq_clock: Consolidate the ordering of the rq_clock methods
Date: Mon, 6 Feb 2017 14:28:06 +0100 [thread overview]
Message-ID: <1486387772-18837-4-git-send-email-mingo@kernel.org> (raw)
In-Reply-To: <1486387772-18837-1-git-send-email-mingo@kernel.org>
update_rq_clock_task() and update_rq_clock() we unnecessarily
spread across core.c, requiring an extra prototype line.
Move them next to each other and in the proper order.
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/sched/core.c | 153 +++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 78 insertions(+), 75 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 87cf7ba82bd5..a400190792b9 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -73,27 +73,6 @@
DEFINE_MUTEX(sched_domains_mutex);
DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
-static void update_rq_clock_task(struct rq *rq, s64 delta);
-
-void update_rq_clock(struct rq *rq)
-{
- s64 delta;
-
- lockdep_assert_held(&rq->lock);
-
- if (rq->clock_update_flags & RQCF_ACT_SKIP)
- return;
-
-#ifdef CONFIG_SCHED_DEBUG
- rq->clock_update_flags |= RQCF_UPDATED;
-#endif
- delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
- if (delta < 0)
- return;
- rq->clock += delta;
- update_rq_clock_task(rq, delta);
-}
-
/*
* Debugging: various feature bits
*/
@@ -218,6 +197,84 @@ struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
}
}
+/*
+ * RQ-clock updating methods:
+ */
+
+static void update_rq_clock_task(struct rq *rq, s64 delta)
+{
+/*
+ * In theory, the compile should just see 0 here, and optimize out the call
+ * to sched_rt_avg_update. But I don't trust it...
+ */
+#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
+ s64 steal = 0, irq_delta = 0;
+#endif
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
+
+ /*
+ * Since irq_time is only updated on {soft,}irq_exit, we might run into
+ * this case when a previous update_rq_clock() happened inside a
+ * {soft,}irq region.
+ *
+ * When this happens, we stop ->clock_task and only update the
+ * prev_irq_time stamp to account for the part that fit, so that a next
+ * update will consume the rest. This ensures ->clock_task is
+ * monotonic.
+ *
+ * It does however cause some slight miss-attribution of {soft,}irq
+ * time, a more accurate solution would be to update the irq_time using
+ * the current rq->clock timestamp, except that would require using
+ * atomic ops.
+ */
+ if (irq_delta > delta)
+ irq_delta = delta;
+
+ rq->prev_irq_time += irq_delta;
+ delta -= irq_delta;
+#endif
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+ if (static_key_false((¶virt_steal_rq_enabled))) {
+ steal = paravirt_steal_clock(cpu_of(rq));
+ steal -= rq->prev_steal_time_rq;
+
+ if (unlikely(steal > delta))
+ steal = delta;
+
+ rq->prev_steal_time_rq += steal;
+ delta -= steal;
+ }
+#endif
+
+ rq->clock_task += delta;
+
+#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
+ if ((irq_delta + steal) && sched_feat(NONTASK_CAPACITY))
+ sched_rt_avg_update(rq, irq_delta + steal);
+#endif
+}
+
+void update_rq_clock(struct rq *rq)
+{
+ s64 delta;
+
+ lockdep_assert_held(&rq->lock);
+
+ if (rq->clock_update_flags & RQCF_ACT_SKIP)
+ return;
+
+#ifdef CONFIG_SCHED_DEBUG
+ rq->clock_update_flags |= RQCF_UPDATED;
+#endif
+ delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
+ if (delta < 0)
+ return;
+ rq->clock += delta;
+ update_rq_clock_task(rq, delta);
+}
+
+
#ifdef CONFIG_SCHED_HRTICK
/*
* Use HR-timers to deliver accurate preemption points.
@@ -767,60 +824,6 @@ void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
dequeue_task(rq, p, flags);
}
-static void update_rq_clock_task(struct rq *rq, s64 delta)
-{
-/*
- * In theory, the compile should just see 0 here, and optimize out the call
- * to sched_rt_avg_update. But I don't trust it...
- */
-#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
- s64 steal = 0, irq_delta = 0;
-#endif
-#ifdef CONFIG_IRQ_TIME_ACCOUNTING
- irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
-
- /*
- * Since irq_time is only updated on {soft,}irq_exit, we might run into
- * this case when a previous update_rq_clock() happened inside a
- * {soft,}irq region.
- *
- * When this happens, we stop ->clock_task and only update the
- * prev_irq_time stamp to account for the part that fit, so that a next
- * update will consume the rest. This ensures ->clock_task is
- * monotonic.
- *
- * It does however cause some slight miss-attribution of {soft,}irq
- * time, a more accurate solution would be to update the irq_time using
- * the current rq->clock timestamp, except that would require using
- * atomic ops.
- */
- if (irq_delta > delta)
- irq_delta = delta;
-
- rq->prev_irq_time += irq_delta;
- delta -= irq_delta;
-#endif
-#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
- if (static_key_false((¶virt_steal_rq_enabled))) {
- steal = paravirt_steal_clock(cpu_of(rq));
- steal -= rq->prev_steal_time_rq;
-
- if (unlikely(steal > delta))
- steal = delta;
-
- rq->prev_steal_time_rq += steal;
- delta -= steal;
- }
-#endif
-
- rq->clock_task += delta;
-
-#if defined(CONFIG_IRQ_TIME_ACCOUNTING) || defined(CONFIG_PARAVIRT_TIME_ACCOUNTING)
- if ((irq_delta + steal) && sched_feat(NONTASK_CAPACITY))
- sched_rt_avg_update(rq, irq_delta + steal);
-#endif
-}
-
void sched_set_stop_task(int cpu, struct task_struct *stop)
{
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
--
2.7.4
next prev parent reply other threads:[~2017-02-06 13:58 UTC|newest]
Thread overview: 119+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-06 13:28 [PATCH 00/89] Major reorganization of <linux/sched.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 01/89] sched/core: Clean up comments Ingo Molnar
2017-02-06 13:28 ` [PATCH 02/89] delayacct: Include <uapi/linux/taskstats.h> Ingo Molnar
2017-02-06 13:28 ` Ingo Molnar [this message]
2017-02-06 13:28 ` [PATCH 04/89] sched/core: Remove unnecessary #include headers Ingo Molnar
2017-02-06 13:28 ` [PATCH 05/89] sched/topology: Split out scheduler topology code from core.c into topology.c Ingo Molnar
2017-02-06 13:28 ` [PATCH 06/89] sched/topology: Split out scheduler topology interfaces from <linux/sched.h> into <linux/sched/topology.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 07/89] sched/idle: Create <linux/sched/idle.h> for idle CPU related definitions Ingo Molnar
2017-02-06 13:28 ` [PATCH 08/89] sched/idle: Move wake_up_if_idle prototype to <linux/sched/idle.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 09/89] sched/wake_q: Move the wake-queue types and interfaces from sched.h into <linux/sched/wake_q.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 10/89] sched/clock: Introduce <linux/sched/clock.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 11/89] sched/headers, delayacct: Move the 'struct task_delay_info' definition from <linux/sched.h> to <linux/delayacct.h> Ingo Molnar
2017-02-06 18:16 ` Linus Torvalds
2017-02-06 21:16 ` [PATCH v2 " Ingo Molnar
2017-02-06 13:28 ` [PATCH 12/89] sched/abi: Introduce <uapi/linux/sched/types.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 13/89] sched/loadavg: Move loadavg related definitions from <linux/sched.h> to <linux/sched/loadavg.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 14/89] sched/autogroup: Collect extern APIs into <linux/sched/autogroup.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 15/89] sched/autogroup: Rename auto_group.[ch] to autogroup.[ch] Ingo Molnar
2017-02-06 13:28 ` [PATCH 16/89] sched/idle: Move polling methods to <linux/sched/idle.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 17/89] sched/idle: Remove tsk_is_polling() Ingo Molnar
2017-02-06 13:28 ` [PATCH 18/89] sched/core: Move task->mm handling methods to <linux/sched/mm.h> Ingo Molnar
2017-02-06 14:28 ` Christoph Hellwig
2017-02-06 22:43 ` Ingo Molnar
2017-02-07 7:30 ` Ingo Molnar
2017-02-06 13:28 ` [PATCH 19/89] sched/core: Move task->mm coredumping related defines and methods from <linux/sched.h> to <linux/sched/coredump.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 20/89] sched/headers, signals: Separate out task_struct::signal and task_struct::sighand types and accessors into <linux/sched/signal.h> Ingo Molnar
2017-02-06 21:11 ` Linus Torvalds
2017-02-06 21:35 ` Ingo Molnar
2017-02-06 21:57 ` Linus Torvalds
2017-02-06 22:38 ` Ingo Molnar
2017-02-06 13:28 ` [PATCH 21/89] sched/headers: Remove unused 'task_can_switch_user()' prototype Ingo Molnar
2017-02-06 13:28 ` [PATCH 22/89] sched/headers: Move 'struct user_struct' definition and APIs to the new <linux/sched/user.h> header Ingo Molnar
2017-02-06 13:28 ` [PATCH 23/89] sched/headers, softlockup: Move softlockup detector watchdog methods to <linux/nmi.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 24/89] sched/headers: Remove #include <linux/capability.h> from <linux/sched.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 25/89] sched/headers, cgroups: Remove the threadgroup_change_*() wrappery Ingo Molnar
2017-02-06 13:28 ` [PATCH 26/89] sched/headers: Remove unused <linux/cgroup-defs.h> include from <linux/sched.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 27/89] sched/headers: Move 'struct pacct_struct' and 'struct cpu_itimer' form <linux/sched.h> to <linux/sched/signal.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 28/89] sched/cpufreq: Move the cpufreq interface to <linux/sched/cpufreq.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 29/89] sched/headers: Move more mm_struct related functionality from <linux/sched.h> to <linux/sched/mm.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 30/89] sched/headers: Move the 'init_mm' declaration from <linux/sched.h> to <linux/mm_types.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 31/89] sched/headers: Move in_vfork() from <linux/sched.h> to <linux/sched/mm.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 32/89] sched/numa: Split <linux/sched/numa_balancing.h> out of <linux/sched.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 33/89] sched/headers: Move the JOBCTL_ defines and methods from <linux/sched.h> to <linux/sched/jobctl.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 34/89] sched/core: Move <asm/paravirt.h> include to kernel/sched/sched.h Ingo Molnar
2017-02-06 13:28 ` [PATCH 35/89] kasan, sched/headers: Remove <linux/sched.h> from <linux/kasan.h> and uninline kasan_enable/disable_current() Ingo Molnar
2017-02-06 13:28 ` [PATCH 36/89] sched/headers: Remove <linux/cred.h> inclusion from <linux/sched.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 37/89] sched/headers: Remove <asm/ptrace.h> " Ingo Molnar
2017-02-06 13:28 ` [PATCH 38/89] sched/headers: Remove <linux/rtmutex.h> " Ingo Molnar
2017-02-06 13:28 ` [PATCH 39/89] sched/headers: Remove various unrelated headers " Ingo Molnar
2017-02-06 13:28 ` [PATCH 40/89] sched/headers: Move CONFIG_TASK_XACCT bits out of <linux/sched.h> into <linux/sched/xacct.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 41/89] sched/headers: Move signal wakeup & sigpending methods from <linux/sched.h> into <linux/sched/signal.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 42/89] sched/headers: Move the memalloc_noio_*() APIs to <linux/sched/mm.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 43/89] sched/headers: Remove <linux/gfp.h> include from <linux/sched.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 44/89] sched/headers: Move task statistics from <linux/sched.h> to <linux/sched/stat.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 45/89] mm/vmacache, sched/headers: Introduce 'struct vmacache' and move it from <linux/sched.h> to <linux/mm_types> Ingo Molnar
2017-02-06 13:28 ` [PATCH 46/89] sched/headers: Move the NOHZ APIs from <linux/sched.h> to <linux/sched/nohz.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 47/89] sched/headers: Move debugging functions from <linux/sched.h> to <linux/sched/debug.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 48/89] sched/headers, time/timekeeping: Move the xtime_update() prototype from <linux/sched.h> to <linux/time.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 49/89] sched/headers: Move <asm/current.h> include from the middle of <linux/sched.h> to the header portion Ingo Molnar
2017-02-06 13:28 ` [PATCH 50/89] sched/core: Convert ___assert_task_state() link time assert to BUILD_BUG_ON() Ingo Molnar
2017-02-06 13:28 ` [PATCH 51/89] sched/headers: Split hotplug CPU interfaces out of <linux/sched.h> into <linux/sched/hotplug.h> Ingo Molnar
2017-02-06 13:28 ` [PATCH 52/89] sched/headers: Split <linux/sched/task.h> out of <linux/sched.h> Ingo Molnar
2017-02-06 21:16 ` Linus Torvalds
2017-02-06 21:41 ` Ingo Molnar
2017-02-06 21:45 ` Ingo Molnar
2017-02-06 13:28 ` [PATCH 53/89] sched/headers: Simplify <linux/sched/task.h> dependencies Ingo Molnar
2017-02-06 13:28 ` [PATCH 54/89] sched/headers: Make the include/linux/sched/*.h headers build standalone Ingo Molnar
2017-02-06 13:28 ` [PATCH 55/89] sched/core: Clean up <linux/sched.h> structure predeclarations and remove stale entries Ingo Molnar
2017-02-06 13:28 ` [PATCH 56/89] sched/headers: Move the PREEMPT_COUNT defines from <linux/sched.h> to <linux/preempt.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 57/89] sched/headers: Split <linux/sched/task_stack> out of <linux/sched.h> Ingo Molnar
2017-02-06 21:21 ` Linus Torvalds
2017-02-06 21:54 ` Ingo Molnar
2017-02-07 8:07 ` Geert Uytterhoeven
2017-02-07 8:13 ` Ingo Molnar
2017-02-07 8:27 ` Geert Uytterhoeven
2017-02-07 9:45 ` Ingo Molnar
2017-02-07 9:54 ` Geert Uytterhoeven
2017-02-06 13:29 ` [PATCH 58/89] sched/headers: Move the 'root_task_group' declaration to <linux/sched/autogroup.h> Ingo Molnar
2017-02-06 14:52 ` Peter Zijlstra
2017-02-06 13:29 ` [PATCH 59/89] sched/core: Move the get_preempt_disable_ip() inline to sched/core.c Ingo Molnar
2017-02-06 13:29 ` [PATCH 60/89] signals: Split out <linux/signal_types.h> from <linux/signal.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 61/89] sched/headers: Reduce <linux/sched.h> signal API dependency Ingo Molnar
2017-02-06 13:29 ` [PATCH 62/89] mm/headers, sched/headers: Split <linux/mm_types_task.h> out of <linux/mm_types.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 63/89] sched/headers: Remove the <linux/mm_types.h> dependency from <linux/sched.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 64/89] sched/headers: Remove 'init_pid_ns' prototype " Ingo Molnar
2017-02-06 13:29 ` [PATCH 65/89] sched/headers: Move 'init_task' and 'init_thread_union' from <linux/sched.h> to <linux/sched/task.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 66/89] sched/headers: Use <linux/rcuupdate.h> instead of <linux/rculist.h> in <linux/sched.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 67/89] sched/headers: Move the task_lock()/unlock() APIs to <linux/sched/task.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 68/89] sched/headers: Split cputime functionality out of <linux/sched.h>, into <linux/sched/cputime.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 69/89] sched/headers: Move sched_info_on() and force_schedstat_enabled() from <linux/sched.h> to <linux/sched/stat.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 70/89] sched/core: Remove unused prefetch_stack() Ingo Molnar
2017-02-06 13:29 ` [PATCH 71/89] sched/headers, vfs/execve: Move the do_execve*() prototypes from <linux/sched.h> to <linux/binfmts.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 72/89] sched/headers: Move kstack_end() from <linux/sched.h> to <linux/sched/task_stack.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 73/89] sched/headers: Move exit_files() and exit_itimers() from <linux/sched.h> to <linux/sched/task.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 74/89] sched/headers: Move _init() prototypes from <linux/sched.h> to <linux/sched/init.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 75/89] sched/headers, timekeeping: Consolidate the timer tick function prototypes Ingo Molnar
2017-02-06 13:29 ` [PATCH 76/89] sched/headers, mm: Move 'struct tlbflush_unmap_batch' from <linux/sched.h> to <linux/mm_types_task.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 77/89] sched/headers: Move the get_task_struct()/put_task_struct() and related APIs from <linux/sched.h> to <linux/sched/task.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 78/89] sched/core: Remove the tsk_cpus_allowed() wrapper Ingo Molnar
2017-02-06 14:53 ` Peter Zijlstra
2017-02-06 14:59 ` Peter Zijlstra
2017-02-06 22:03 ` Ingo Molnar
2017-02-07 8:06 ` Peter Zijlstra
2017-02-06 13:29 ` [PATCH 79/89] sched/core: Remove the tsk_nr_cpus_allowed() wrapper Ingo Molnar
2017-02-06 13:29 ` [PATCH 80/89] sched/headers: Move the <linux/magic.h> include to <linux/sched/task_stack.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 81/89] sched/headers: Remove spurious <linux/sched.h> inclusion dependencies Ingo Molnar
2017-02-06 13:29 ` [PATCH 82/89] rcu: Separate the rcu synchronization types and APIs into <linux/rcupdate_wait.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 83/89] timers: Remove the <linux/sysctl.h> include from <linux/timer.h> Ingo Molnar
2017-02-06 13:29 ` [PATCH 84/89] x86/apic: Remove the <linux/pm.h> header inclusion from <asm/apic.h> Ingo Molnar
2017-02-06 13:33 ` [PATCH 85/89] hrtimer: Remove the <linux/wait.h> include from <linux/hrtimer.h> Ingo Molnar
2017-02-06 13:34 ` [PATCH 86/89] sched/headers: Remove the <linux/topology.h> include from <linux/sched.h> Ingo Molnar
2017-02-06 13:34 ` [PATCH 87/89] sched/headers: Move the sched_exec() prototype to <linux/sched/task.h> Ingo Molnar
2017-02-06 13:35 ` [PATCH 88/89] sched/headers: Remove #ifdefs from <linux/sched.h> Ingo Molnar
2017-02-06 21:26 ` Linus Torvalds
2017-02-06 13:36 ` [PATCH 89/89] sched/headers: Clean up <linux/sched.h> Ingo Molnar
2017-02-06 13:39 ` [PATCH 00/89] Major reorganization of <linux/sched.h> Ingo Molnar
2017-02-06 21:31 ` Linus Torvalds
2017-02-06 22:13 ` Ingo Molnar
2017-02-07 8:08 ` Peter Zijlstra
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=1486387772-18837-4-git-send-email-mingo@kernel.org \
--to=mingo@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=efault@gmx.de \
--cc=linux-kernel@vger.kernel.org \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.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