Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/drm2/linux linux compat: Draft hrtimer shims.
details: https://anonhg.NetBSD.org/src/rev/c767682185e6
branches: trunk
changeset: 1028590:c767682185e6
user: riastradh <riastradh%NetBSD.org@localhost>
date: Sun Dec 19 11:23:51 2021 +0000
description:
linux compat: Draft hrtimer shims.
(not actually high-resolution, just a wrapper around callout(9))
diffstat:
sys/external/bsd/drm2/include/linux/hrtimer.h | 41 ++++-
sys/external/bsd/drm2/linux/files.drmkms_linux | 3 +-
sys/external/bsd/drm2/linux/linux_hrtimer.c | 212 +++++++++++++++++++++++++
3 files changed, 254 insertions(+), 2 deletions(-)
diffs (291 lines):
diff -r 44882e7aa42d -r c767682185e6 sys/external/bsd/drm2/include/linux/hrtimer.h
--- a/sys/external/bsd/drm2/include/linux/hrtimer.h Sun Dec 19 11:23:37 2021 +0000
+++ b/sys/external/bsd/drm2/include/linux/hrtimer.h Sun Dec 19 11:23:51 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hrtimer.h,v 1.3 2021/12/19 10:38:05 riastradh Exp $ */
+/* $NetBSD: hrtimer.h,v 1.4 2021/12/19 11:23:51 riastradh Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -32,9 +32,48 @@
#ifndef _LINUX_HRTIMER_H_
#define _LINUX_HRTIMER_H_
+#include <sys/types.h>
+
+#include <sys/callout.h>
+
+#include <linux/ktime.h>
#include <linux/timer.h>
struct hrtimer {
+ enum hrtimer_restart (*function)(struct hrtimer *);
+
+ struct hrtimer_private *hrt_private;
+};
+
+enum hrtimer_mode {
+ HRTIMER_MODE_ABS,
+ HRTIMER_MODE_REL,
+};
+
+enum hrtimer_restart {
+ HRTIMER_NORESTART,
+ HRTIMER_RESTART,
};
+#define hrtimer_active linux_hrtimer_active
+#define hrtimer_add_expires_ns linux_hrtimer_add_expires_ns
+#define hrtimer_cancel linux_hrtimer_cancel
+#define hrtimer_forward linux_hrtimer_forward
+#define hrtimer_forward_now linux_hrtimer_forward_now
+#define hrtimer_init linux_hrtimer_init
+#define hrtimer_set_expires linux_hrtimer_set_expiresp
+#define hrtimer_start linux_hrtimer_start
+#define hrtimer_start_range_ns linux_hrtimer_start_range_ns
+
+void hrtimer_init(struct hrtimer *, clockid_t, enum hrtimer_mode);
+void hrtimer_set_expires(struct hrtimer *, ktime_t);
+void hrtimer_add_expires_ns(struct hrtimer *, uint64_t);
+void hrtimer_start(struct hrtimer *, ktime_t, enum hrtimer_mode);
+void hrtimer_start_range_ns(struct hrtimer *, ktime_t, uint64_t,
+ enum hrtimer_mode);
+int hrtimer_cancel(struct hrtimer *);
+bool hrtimer_active(struct hrtimer *);
+uint64_t hrtimer_forward(struct hrtimer *, ktime_t, ktime_t);
+uint64_t hrtimer_forward_now(struct hrtimer *, ktime_t);
+
#endif /* _LINUX_HRTIMER_H_ */
diff -r 44882e7aa42d -r c767682185e6 sys/external/bsd/drm2/linux/files.drmkms_linux
--- a/sys/external/bsd/drm2/linux/files.drmkms_linux Sun Dec 19 11:23:37 2021 +0000
+++ b/sys/external/bsd/drm2/linux/files.drmkms_linux Sun Dec 19 11:23:51 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.drmkms_linux,v 1.30 2021/12/19 11:21:30 riastradh Exp $
+# $NetBSD: files.drmkms_linux,v 1.31 2021/12/19 11:23:52 riastradh Exp $
define drmkms_linux: i2cexec, i2c_bitbang
@@ -13,6 +13,7 @@
file external/bsd/drm2/linux/linux_dma_resv.c drmkms_linux
file external/bsd/drm2/linux/linux_dmi.c drmkms_linux
file external/bsd/drm2/linux/linux_firmware.c drmkms_linux
+file external/bsd/drm2/linux/linux_hrtimer.c drmkms_linux
file external/bsd/drm2/linux/linux_i2c.c drmkms_linux
file external/bsd/drm2/linux/linux_idr.c drmkms_linux
file external/bsd/drm2/linux/linux_kmap.c drmkms_linux
diff -r 44882e7aa42d -r c767682185e6 sys/external/bsd/drm2/linux/linux_hrtimer.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/external/bsd/drm2/linux/linux_hrtimer.c Sun Dec 19 11:23:51 2021 +0000
@@ -0,0 +1,212 @@
+/* $NetBSD: linux_hrtimer.c,v 1.1 2021/12/19 11:23:52 riastradh Exp $ */
+
+/*-
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: linux_hrtimer.c,v 1.1 2021/12/19 11:23:52 riastradh Exp $");
+
+#include <sys/types.h>
+#include <sys/callout.h>
+#include <sys/kmem.h>
+
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+
+struct hrtimer_private {
+ struct callout ch;
+ enum hrtimer_mode mode;
+ ktime_t expires;
+};
+
+static void hrtimer_fire(void *);
+
+void
+hrtimer_init(struct hrtimer *hrt, clockid_t clkid, enum hrtimer_mode mode)
+{
+ struct hrtimer_private *H;
+
+ KASSERTMSG(clkid == CLOCK_MONOTONIC, "clkid %d", clkid);
+
+ H = hrt->hrt_private = kmem_zalloc(sizeof(*H), KM_SLEEP);
+
+ callout_init(&H->ch, CALLOUT_MPSAFE);
+ callout_setfunc(&H->ch, hrtimer_fire, H);
+ H->mode = mode;
+}
+
+static void
+_hrtimer_schedule(struct hrtimer *hrt)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+ int delta;
+
+ switch (H->mode) {
+ case HRTIMER_MODE_ABS:
+ panic("absolute hrtimer NYI");
+ break;
+ case HRTIMER_MODE_REL:
+ delta = ktime_to_ms(H->expires);
+ break;
+ default:
+ panic("invalid hrtimer mode %d", H->mode);
+ }
+ callout_schedule(&H->ch, delta);
+}
+
+static void
+hrtimer_fire(void *cookie)
+{
+ struct hrtimer *hrt = cookie;
+ struct hrtimer_private *H = hrt->hrt_private;
+
+ switch ((*hrt->function)(hrt)) {
+ case HRTIMER_RESTART:
+ _hrtimer_schedule(hrt);
+ break;
+ case HRTIMER_NORESTART:
+ break;
+ }
+
+ callout_ack(&H->ch);
+}
+
+void
+hrtimer_set_expires(struct hrtimer *hrt, ktime_t expires)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+
+ H->expires = expires;
+}
+
+void
+hrtimer_add_expires_ns(struct hrtimer *hrt, uint64_t ns)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+
+ H->expires = ktime_add_ns(H->expires, ns);
+}
+
+void
+hrtimer_start(struct hrtimer *hrt, ktime_t expires, enum hrtimer_mode mode)
+{
+
+ hrtimer_start_range_ns(hrt, expires, 0, mode);
+}
+
+void
+hrtimer_start_range_ns(struct hrtimer *hrt, ktime_t expires, uint64_t range_ns,
+ enum hrtimer_mode mode)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+
+ H->expires = expires;
+ (void)range_ns;
+ H->mode = mode;
+ _hrtimer_schedule(hrt);
+}
+
+int
+hrtimer_cancel(struct hrtimer *hrt)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+ bool active;
+
+ /*
+ * Halt the callout and ascertain whether the hrtimer was
+ * active when we invoked hrtimer_cancel.
+ */
+ if (callout_halt(&H->ch, NULL)) {
+ /* Callout expired, meaning it was active. */
+ active = true;
+ } else {
+ /*
+ * Callout had not yet expired. It will not expire
+ * now, so callout_pending is now stable and
+ * corresponds with whether the hrtimer was active or
+ * not.
+ */
+ active = callout_pending(&H->ch);
+ }
+
+ callout_destroy(&H->ch);
+ kmem_free(H, sizeof(*H));
+
+ explicit_memset(hrt, 0, sizeof(*hrt)); /* paranoia */
+
+ return active;
+}
+
+bool
+hrtimer_active(struct hrtimer *hrt)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+
+ /*
+ * If the callout has been scheduled, but has not yet fired,
+ * then it is pending.
+ *
+ * If the callout has fired, but has not yet reached
+ * callout_ack, then it is invoking.
+ */
+ return callout_pending(&H->ch) || callout_invoking(&H->ch);
+}
+
+uint64_t
+hrtimer_forward(struct hrtimer *hrt, ktime_t now, ktime_t period)
+{
+ struct hrtimer_private *H = hrt->hrt_private;
+ uint64_t now_ms, period_ms, expires_ms, nperiods;
+
+ KASSERT(!callout_pending(&H->ch));
+
+ /*
+ * Can't get better than 10ms precision (or ~1ms if you set
+ * HZ=1000) so not much point in doing this arithmetic at finer
+ * resolution than ms.
+ */
+ now_ms = ktime_to_ms(now);
+ period_ms = ktime_to_ms(period);
+ expires_ms = ktime_to_ms(H->expires);
+
+ /* If it hasn't yet expired, no overruns. */
+ if (now_ms < expires_ms)
+ return 0;
+
+ /* Advance it by as many periods as it should have fired. */
+ /* XXX fenceposts */
+ nperiods = howmany(now_ms - expires_ms, period_ms);
+ H->expires = ktime_add_ns(H->expires, 1000000*nperiods*period_ms);
+
+ return nperiods;
+}
+
+uint64_t
+hrtimer_forward_now(struct hrtimer *hrt, ktime_t period)
+{
+
+ return hrtimer_forward(hrt, ktime_get(), period);
+}
Home |
Main Index |
Thread Index |
Old Index