From fb00a65fc609a505dbc0763426228f09615c604e Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 31 Oct 2018 17:36:19 -0400 Subject: [PATCH] freebsd11_network: Avoid triggering timer interrupts 1000 times/sec. FreeBSD's "ticks" has a granularity of whatever "hz" is, presently 1000. It's declared as "extern int32" in FreeBSD's codebase, as it's the defining unit of time for most operations. We just use system_time() for essentially the same purpose, which requires no hard-clock timer interrupts at all, and so Colin seems to have decided to emulate "ticks" by just triggering a timer once per millisecond and then incrementing the "ticks" variable. 1000 timer interrupts per second is quite a lot (assuming the kernel actually combined these between drivers, otherwise it would be 1000 *per driver*), and probably a contributor to Haiku's not-so-great battery performance on most laptops. --- src/libs/compat/freebsd11_network/callout.cpp | 11 +++-- src/libs/compat/freebsd11_network/clock.c | 42 +++---------------- .../freebsd11_network/compat/sys/callout.h | 4 +- .../freebsd11_network/compat/sys/kernel.h | 16 +++---- .../freebsd11_network/compat/sys/taskqueue.h | 2 +- src/libs/compat/freebsd11_network/driver.c | 7 ---- src/libs/compat/freebsd11_network/taskqueue.c | 12 +++--- 7 files changed, 28 insertions(+), 66 deletions(-) diff --git a/src/libs/compat/freebsd11_network/callout.cpp b/src/libs/compat/freebsd11_network/callout.cpp index 681f50fcfb..3300989b07 100644 --- a/src/libs/compat/freebsd11_network/callout.cpp +++ b/src/libs/compat/freebsd11_network/callout.cpp @@ -5,12 +5,11 @@ */ -#include "device.h" - #include #include extern "C" { +# include "device.h" # include # include } @@ -176,7 +175,7 @@ callout_init_mtx(struct callout *c, struct mtx *mtx, int flags) int -callout_reset(struct callout *c, int ticks, void (*func)(void *), void *arg) +callout_reset(struct callout *c, int _ticks, void (*func)(void *), void *arg) { int canceled = callout_stop(c); @@ -192,7 +191,7 @@ callout_reset(struct callout *c, int ticks, void (*func)(void *), void *arg) if (c->due <= 0) list_add_item(&sTimers, c); - c->due = system_time() + ticks_to_usecs(ticks); + c->due = system_time() + ticks_to_usecs(_ticks); // notify timer about the change if necessary if (sTimeout > c->due) @@ -204,9 +203,9 @@ callout_reset(struct callout *c, int ticks, void (*func)(void *), void *arg) int -callout_schedule(struct callout *callout, int ticks) +callout_schedule(struct callout *callout, int _ticks) { - return callout_reset(callout, ticks, callout->c_func, callout->c_arg); + return callout_reset(callout, _ticks, callout->c_func, callout->c_arg); } diff --git a/src/libs/compat/freebsd11_network/clock.c b/src/libs/compat/freebsd11_network/clock.c index 258394a5cf..567a562110 100644 --- a/src/libs/compat/freebsd11_network/clock.c +++ b/src/libs/compat/freebsd11_network/clock.c @@ -1,44 +1,14 @@ /* - * Copyright 2009, Colin Günther, coling@gmx.de - * All rights reserved. Distributed under the terms of the MIT License. + * Copyright 2018, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. */ - -#include "device.h" - +#include #include -int32 ticks; -static timer sHardClockTimer; - - -/*! - * Implementation of FreeBSD's hardclock timer. - */ -static int32 -hardClock(timer* hardClockTimer) +int32_t +get_ticks() { - atomic_add(&ticks, 1); - return B_HANDLED_INTERRUPT; -} - - -/*! - * Initialization of the hardclock timer which ticks according to hz defined in - * compat/sys/kernel.h. - */ -status_t -init_hard_clock() -{ - ticks = 0; - return add_timer(&sHardClockTimer, hardClock, ticks_to_usecs(1), - B_PERIODIC_TIMER); -} - - -void -uninit_hard_clock() -{ - cancel_timer(&sHardClockTimer); + return usecs_to_ticks(system_time()); } diff --git a/src/libs/compat/freebsd11_network/compat/sys/callout.h b/src/libs/compat/freebsd11_network/compat/sys/callout.h index 5734ece8f3..fefdf1d5f6 100644 --- a/src/libs/compat/freebsd11_network/compat/sys/callout.h +++ b/src/libs/compat/freebsd11_network/compat/sys/callout.h @@ -19,8 +19,8 @@ void callout_init(struct callout *c, int mpsafe); void callout_init_mtx(struct callout *c, struct mtx *mutex, int flags); /* Time values are in ticks, see compat/sys/kernel.h for its definition */ -int callout_schedule(struct callout *c, int ticks); -int callout_reset(struct callout *c, int ticks, void (*func)(void *), void *arg); +int callout_schedule(struct callout *c, int _ticks); +int callout_reset(struct callout *c, int _ticks, void (*func)(void *), void *arg); int callout_pending(struct callout *c); int callout_active(struct callout *c); diff --git a/src/libs/compat/freebsd11_network/compat/sys/kernel.h b/src/libs/compat/freebsd11_network/compat/sys/kernel.h index 8a5f26b702..2494b15828 100644 --- a/src/libs/compat/freebsd11_network/compat/sys/kernel.h +++ b/src/libs/compat/freebsd11_network/compat/sys/kernel.h @@ -1,5 +1,5 @@ /* - * Copyright 2007-2009 Haiku Inc. All rights reserved. + * Copyright 2007-2018, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _FBSD_COMPAT_SYS_KERNEL_H_ @@ -14,22 +14,22 @@ #include -/* - * - * The rate at which FreeBSD can generate callouts (kind of timeout mechanism). +/* The rate at which FreeBSD can generate callouts (kind of timeout mechanism). * For FreeBSD 8 this is typically 1000 times per second (100 for ARM). * This value is defined in a file called subr_param.c * - * WHile Haiku can have a much higher granularity, it is not a good idea to have + * While Haiku can have a much higher granularity, it is not a good idea to have * this since FreeBSD tries to do certain tasks based on ticks, for instance * autonegotiation and wlan scanning. * Suffixing LL prevents integer overflows during calculations. - * as it defines a long long constant.*/ + * as it defines a long long constant. */ #define hz 1000LL -#define ticks_to_usecs(t) (1000000*((bigtime_t)t) / hz) +int32_t get_ticks(); +#define ticks (get_ticks()) -extern int32 ticks; +#define ticks_to_usecs(t) (1000000*((bigtime_t)t) / hz) +#define usecs_to_ticks(t) (((bigtime_t)t*hz) / 1000000) typedef void (*system_init_func_t)(void *); diff --git a/src/libs/compat/freebsd11_network/compat/sys/taskqueue.h b/src/libs/compat/freebsd11_network/compat/sys/taskqueue.h index de2592bf88..7f131d93d3 100644 --- a/src/libs/compat/freebsd11_network/compat/sys/taskqueue.h +++ b/src/libs/compat/freebsd11_network/compat/sys/taskqueue.h @@ -38,7 +38,7 @@ void taskqueue_block(struct taskqueue *queue); void taskqueue_unblock(struct taskqueue *queue); int taskqueue_enqueue(struct taskqueue *tq, struct task *task); int taskqueue_enqueue_timeout(struct taskqueue *queue, - struct timeout_task *ttask, int ticks); + struct timeout_task *ttask, int _ticks); int taskqueue_cancel(struct taskqueue *queue, struct task *task, u_int *pendp); int taskqueue_cancel_timeout(struct taskqueue *queue, diff --git a/src/libs/compat/freebsd11_network/driver.c b/src/libs/compat/freebsd11_network/driver.c index b7d472f54f..05a3f26e4b 100644 --- a/src/libs/compat/freebsd11_network/driver.c +++ b/src/libs/compat/freebsd11_network/driver.c @@ -113,10 +113,6 @@ _fbsd_init_drivers(driver_t *drivers[]) if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK) gPCIx86 = NULL; - status = init_hard_clock(); - if (status < B_OK) - goto err1; - status = init_mutexes(); if (status < B_OK) goto err2; @@ -207,8 +203,6 @@ err4: err3: uninit_mutexes(); err2: - uninit_hard_clock(); -err1: put_module(B_PCI_MODULE_NAME); if (gPCIx86 != NULL) put_module(B_PCI_X86_MODULE_NAME); @@ -236,7 +230,6 @@ _fbsd_uninit_drivers(driver_t *drivers[]) uninit_callout(); uninit_mbufs(); uninit_mutexes(); - uninit_hard_clock(); put_module(B_PCI_MODULE_NAME); if (gPCIx86 != NULL) diff --git a/src/libs/compat/freebsd11_network/taskqueue.c b/src/libs/compat/freebsd11_network/taskqueue.c index cb8fac155b..21bd1d08c8 100644 --- a/src/libs/compat/freebsd11_network/taskqueue.c +++ b/src/libs/compat/freebsd11_network/taskqueue.c @@ -345,7 +345,7 @@ taskqueue_timeout_func(void *arg) int taskqueue_enqueue_timeout(struct taskqueue *queue, - struct timeout_task *ttask, int ticks) + struct timeout_task *ttask, int _ticks) { int res; cpu_status status; @@ -359,7 +359,7 @@ taskqueue_enqueue_timeout(struct taskqueue *queue, /* Do nothing */ tq_unlock(queue, status); res = -1; - } else if (ticks == 0) { + } else if (_ticks == 0) { tq_unlock(queue, status); taskqueue_enqueue(queue, &ttask->t); } else { @@ -368,12 +368,12 @@ taskqueue_enqueue_timeout(struct taskqueue *queue, } else { queue->tq_callouts++; ttask->f |= DT_CALLOUT_ARMED; - if (ticks < 0) - ticks = -ticks; /* Ignore overflow. */ + if (_ticks < 0) + _ticks = -_ticks; /* Ignore overflow. */ } tq_unlock(queue, status); - if (ticks > 0) { - callout_reset(&ttask->c, ticks, + if (_ticks > 0) { + callout_reset(&ttask->c, _ticks, taskqueue_timeout_func, ttask); } }