From: Sagi Maimon <maimon.sagi@gmail.com>
To: richardcochran@gmail.com, luto@kernel.org, datglx@linutronix.de,
mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com,
x86@kernel.org, hpa@zytor.com, arnd@arndb.de,
geert@linux-m68k.org, peterz@infradead.org, hannes@cmpxchg.org,
sohil.mehta@intel.com, rick.p.edgecombe@intel.com,
nphamcs@gmail.com, palmer@sifive.com, maimon.sagi@gmail.com,
keescook@chromium.org, legion@kernel.org, mark.rutland@arm.com
Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
linux-arch@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH v5] posix-timers: add multi_clock_gettime system call
Date: Tue, 2 Jan 2024 11:18:55 +0200 [thread overview]
Message-ID: <20240102091855.70418-1-maimon.sagi@gmail.com> (raw)
Some user space applications need to read some clocks.
Each read requires moving from user space to kernel space.
The syscall overhead causes unpredictable delay between N clocks reads
Removing this delay causes better synchronization between N clocks.
Introduce a new system call multi_clock_gettime, which can be used to measure
the offset between multiple clocks, from variety of types: PHC, virtual PHC
and various system clocks (CLOCK_REALTIME, CLOCK_MONOTONIC, etc).
The offset includes the total time that the driver needs to read the clock
timestamp.
New system call allows the reading of a list of clocks - up to PTP_MAX_CLOCKS.
Supported clocks IDs: PHC, virtual PHC and various system clocks.
Up to PTP_MAX_SAMPLES times (per clock) in a single system call read.
The system call returns n_clocks timestamps for each measurement:
- clock 0 timestamp
- ...
- clock n timestamp
Signed-off-by: Sagi Maimon <maimon.sagi@gmail.com>
---
Changes since version 4:
- fix error : 'struct __ptp_multi_clock_get' declared inside parameter list
will not be visible outside of this definition or declaration
arch/x86/entry/syscalls/syscall_64.tbl | 1 +
include/linux/syscalls.h | 3 +-
include/uapi/asm-generic/unistd.h | 4 +-
include/uapi/linux/multi_clock.h | 21 +++++++++
kernel/time/posix-timers.c | 59 ++++++++++++++++++++++++++
5 files changed, 86 insertions(+), 2 deletions(-)
create mode 100644 include/uapi/linux/multi_clock.h
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 8cb8bf68721c..9cdeb0bf49db 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -378,6 +378,7 @@
454 common futex_wake sys_futex_wake
455 common futex_wait sys_futex_wait
456 common futex_requeue sys_futex_requeue
+457 common multi_clock_gettime sys_multi_clock_gettime
#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index fd9d12de7e92..bde7dec493fd 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -74,6 +74,7 @@ struct landlock_ruleset_attr;
enum landlock_rule_type;
struct cachestat_range;
struct cachestat;
+struct __ptp_multi_clock_get;
#include <linux/types.h>
#include <linux/aio_abi.h>
@@ -1161,7 +1162,7 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
-
+asmlinkage long sys_multi_clock_gettime(struct __ptp_multi_clock_get __user * ptp_multi_clk_get);
/*
* Not a real system call, but a placeholder for syscalls which are
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 756b013fb832..beb3e0052d3c 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -828,9 +828,11 @@ __SYSCALL(__NR_futex_wake, sys_futex_wake)
__SYSCALL(__NR_futex_wait, sys_futex_wait)
#define __NR_futex_requeue 456
__SYSCALL(__NR_futex_requeue, sys_futex_requeue)
+#define __NR_multi_clock_gettime 457
+__SYSCALL(__NR_multi_clock_gettime, sys_multi_clock_gettime)
#undef __NR_syscalls
-#define __NR_syscalls 457
+#define __NR_syscalls 458
/*
* 32 bit systems traditionally used different
diff --git a/include/uapi/linux/multi_clock.h b/include/uapi/linux/multi_clock.h
new file mode 100644
index 000000000000..5e78dac3a533
--- /dev/null
+++ b/include/uapi/linux/multi_clock.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_MULTI_CLOCK_H
+#define _UAPI_MULTI_CLOCK_H
+
+#include <linux/types.h>
+#include <linux/time_types.h>
+
+#define MULTI_PTP_MAX_CLOCKS 32 /* Max number of clocks */
+#define MULTI_PTP_MAX_SAMPLES 32 /* Max allowed offset measurement samples. */
+
+struct __ptp_multi_clock_get {
+ unsigned int n_clocks; /* Desired number of clocks. */
+ unsigned int n_samples; /* Desired number of measurements per clock. */
+ clockid_t clkid_arr[MULTI_PTP_MAX_CLOCKS]; /* list of clock IDs */
+ /*
+ * Array of list of n_clocks clocks time samples n_samples times.
+ */
+ struct __kernel_timespec ts[MULTI_PTP_MAX_SAMPLES][MULTI_PTP_MAX_CLOCKS];
+};
+
+#endif /* _UAPI_MULTI_CLOCK_H */
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index b924f0f096fa..1d321dc56a25 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -31,6 +31,8 @@
#include <linux/compat.h>
#include <linux/nospec.h>
#include <linux/time_namespace.h>
+#include <linux/multi_clock.h>
+#include <linux/slab.h>
#include "timekeeping.h"
#include "posix-timers.h"
@@ -1426,6 +1428,63 @@ SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags,
#endif
+SYSCALL_DEFINE1(multi_clock_gettime, struct __ptp_multi_clock_get __user *, ptp_multi_clk_get)
+{
+ const struct k_clock *kc;
+ struct timespec64 *kernel_tp;
+ struct timespec64 *kernel_tp_base;
+ unsigned int n_clocks; /* Desired number of clocks. */
+ unsigned int n_samples; /* Desired number of measurements per clock. */
+ unsigned int i, j;
+ clockid_t clkid_arr[MULTI_PTP_MAX_CLOCKS]; /* list of clock IDs */
+ int error = 0;
+
+ if (copy_from_user(&n_clocks, &ptp_multi_clk_get->n_clocks, sizeof(n_clocks)))
+ return -EFAULT;
+ if (copy_from_user(&n_samples, &ptp_multi_clk_get->n_samples, sizeof(n_samples)))
+ return -EFAULT;
+ if (n_samples > MULTI_PTP_MAX_SAMPLES)
+ return -EINVAL;
+ if (n_clocks > MULTI_PTP_MAX_CLOCKS)
+ return -EINVAL;
+ if (copy_from_user(clkid_arr, &ptp_multi_clk_get->clkid_arr,
+ sizeof(clockid_t) * n_clocks))
+ return -EFAULT;
+
+ kernel_tp_base = kmalloc_array(n_clocks * n_samples,
+ sizeof(struct timespec64), GFP_KERNEL);
+ if (!kernel_tp_base)
+ return -ENOMEM;
+
+ kernel_tp = kernel_tp_base;
+ for (j = 0; j < n_samples; j++) {
+ for (i = 0; i < n_clocks; i++) {
+ kc = clockid_to_kclock(clkid_arr[i]);
+ if (!kc) {
+ error = -EINVAL;
+ goto out;
+ }
+ error = kc->clock_get_timespec(clkid_arr[i], kernel_tp++);
+ if (error)
+ goto out;
+ }
+ }
+
+ kernel_tp = kernel_tp_base;
+ for (j = 0; j < n_samples; j++) {
+ for (i = 0; i < n_clocks; i++) {
+ if (put_timespec64(kernel_tp++, (struct __kernel_timespec __user *)
+ &ptp_multi_clk_get->ts[j][i])) {
+ error = -EFAULT;
+ goto out;
+ }
+ }
+ }
+out:
+ kfree(kernel_tp_base);
+ return error;
+}
+
static const struct k_clock clock_realtime = {
.clock_getres = posix_get_hrtimer_res,
.clock_get_timespec = posix_get_realtime_timespec,
--
2.26.3
next reply other threads:[~2024-01-02 9:19 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-02 9:18 Sagi Maimon [this message]
2024-01-02 10:21 ` [PATCH v5] posix-timers: add multi_clock_gettime system call Arnd Bergmann
2024-01-03 12:59 ` Sagi Maimon
2024-01-04 3:06 ` kernel test robot
2024-01-08 11:09 ` Thomas Gleixner
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=20240102091855.70418-1-maimon.sagi@gmail.com \
--to=maimon.sagi@gmail.com \
--cc=arnd@arndb.de \
--cc=bp@alien8.de \
--cc=datglx@linutronix.de \
--cc=dave.hansen@linux.intel.com \
--cc=geert@linux-m68k.org \
--cc=hannes@cmpxchg.org \
--cc=hpa@zytor.com \
--cc=keescook@chromium.org \
--cc=legion@kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=nphamcs@gmail.com \
--cc=palmer@sifive.com \
--cc=peterz@infradead.org \
--cc=richardcochran@gmail.com \
--cc=rick.p.edgecombe@intel.com \
--cc=sohil.mehta@intel.com \
--cc=x86@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.