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.
This commit is contained in:
Augustin Cavalier
2018-10-31 19:03:40 -04:00
parent 04b07407ef
commit fb00a65fc6
7 changed files with 28 additions and 66 deletions
@@ -5,12 +5,11 @@
*/ */
#include "device.h"
#include <lock.h> #include <lock.h>
#include <thread.h> #include <thread.h>
extern "C" { extern "C" {
# include "device.h"
# include <sys/callout.h> # include <sys/callout.h>
# include <sys/mutex.h> # include <sys/mutex.h>
} }
@@ -176,7 +175,7 @@ callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
int 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); 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) if (c->due <= 0)
list_add_item(&sTimers, c); 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 // notify timer about the change if necessary
if (sTimeout > c->due) if (sTimeout > c->due)
@@ -204,9 +203,9 @@ callout_reset(struct callout *c, int ticks, void (*func)(void *), void *arg)
int 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);
} }
+6 -36
View File
@@ -1,44 +1,14 @@
/* /*
* Copyright 2009, Colin Günther, [email protected] * Copyright 2018, Haiku, Inc. All rights reserved.
* All rights reserved. Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <OS.h>
#include "device.h"
#include <compat/sys/kernel.h> #include <compat/sys/kernel.h>
int32 ticks; int32_t
static timer sHardClockTimer; get_ticks()
/*!
* Implementation of FreeBSD's hardclock timer.
*/
static int32
hardClock(timer* hardClockTimer)
{ {
atomic_add(&ticks, 1); return usecs_to_ticks(system_time());
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);
} }
@@ -19,8 +19,8 @@
void callout_init(struct callout *c, int mpsafe); void callout_init(struct callout *c, int mpsafe);
void callout_init_mtx(struct callout *c, struct mtx *mutex, int flags); 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 */ /* Time values are in ticks, see compat/sys/kernel.h for its definition */
int callout_schedule(struct callout *c, int ticks); int callout_schedule(struct callout *c, int _ticks);
int callout_reset(struct callout *c, int ticks, void (*func)(void *), void *arg); int callout_reset(struct callout *c, int _ticks, void (*func)(void *), void *arg);
int callout_pending(struct callout *c); int callout_pending(struct callout *c);
int callout_active(struct callout *c); int callout_active(struct callout *c);
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _FBSD_COMPAT_SYS_KERNEL_H_ #ifndef _FBSD_COMPAT_SYS_KERNEL_H_
@@ -14,22 +14,22 @@
#include <sys/queue.h> #include <sys/queue.h>
/* /* 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). * For FreeBSD 8 this is typically 1000 times per second (100 for ARM).
* This value is defined in a file called subr_param.c * 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 * this since FreeBSD tries to do certain tasks based on ticks, for instance
* autonegotiation and wlan scanning. * autonegotiation and wlan scanning.
* Suffixing LL prevents integer overflows during calculations. * 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 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 *); typedef void (*system_init_func_t)(void *);
@@ -38,7 +38,7 @@ void taskqueue_block(struct taskqueue *queue);
void taskqueue_unblock(struct taskqueue *queue); void taskqueue_unblock(struct taskqueue *queue);
int taskqueue_enqueue(struct taskqueue *tq, struct task *task); int taskqueue_enqueue(struct taskqueue *tq, struct task *task);
int taskqueue_enqueue_timeout(struct taskqueue *queue, 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, int taskqueue_cancel(struct taskqueue *queue, struct task *task,
u_int *pendp); u_int *pendp);
int taskqueue_cancel_timeout(struct taskqueue *queue, int taskqueue_cancel_timeout(struct taskqueue *queue,
@@ -113,10 +113,6 @@ _fbsd_init_drivers(driver_t *drivers[])
if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK) if (get_module(B_PCI_X86_MODULE_NAME, (module_info **)&gPCIx86) != B_OK)
gPCIx86 = NULL; gPCIx86 = NULL;
status = init_hard_clock();
if (status < B_OK)
goto err1;
status = init_mutexes(); status = init_mutexes();
if (status < B_OK) if (status < B_OK)
goto err2; goto err2;
@@ -207,8 +203,6 @@ err4:
err3: err3:
uninit_mutexes(); uninit_mutexes();
err2: err2:
uninit_hard_clock();
err1:
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
if (gPCIx86 != NULL) if (gPCIx86 != NULL)
put_module(B_PCI_X86_MODULE_NAME); put_module(B_PCI_X86_MODULE_NAME);
@@ -236,7 +230,6 @@ _fbsd_uninit_drivers(driver_t *drivers[])
uninit_callout(); uninit_callout();
uninit_mbufs(); uninit_mbufs();
uninit_mutexes(); uninit_mutexes();
uninit_hard_clock();
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
if (gPCIx86 != NULL) if (gPCIx86 != NULL)
@@ -345,7 +345,7 @@ taskqueue_timeout_func(void *arg)
int int
taskqueue_enqueue_timeout(struct taskqueue *queue, taskqueue_enqueue_timeout(struct taskqueue *queue,
struct timeout_task *ttask, int ticks) struct timeout_task *ttask, int _ticks)
{ {
int res; int res;
cpu_status status; cpu_status status;
@@ -359,7 +359,7 @@ taskqueue_enqueue_timeout(struct taskqueue *queue,
/* Do nothing */ /* Do nothing */
tq_unlock(queue, status); tq_unlock(queue, status);
res = -1; res = -1;
} else if (ticks == 0) { } else if (_ticks == 0) {
tq_unlock(queue, status); tq_unlock(queue, status);
taskqueue_enqueue(queue, &ttask->t); taskqueue_enqueue(queue, &ttask->t);
} else { } else {
@@ -368,12 +368,12 @@ taskqueue_enqueue_timeout(struct taskqueue *queue,
} else { } else {
queue->tq_callouts++; queue->tq_callouts++;
ttask->f |= DT_CALLOUT_ARMED; ttask->f |= DT_CALLOUT_ARMED;
if (ticks < 0) if (_ticks < 0)
ticks = -ticks; /* Ignore overflow. */ _ticks = -_ticks; /* Ignore overflow. */
} }
tq_unlock(queue, status); tq_unlock(queue, status);
if (ticks > 0) { if (_ticks > 0) {
callout_reset(&ttask->c, ticks, callout_reset(&ttask->c, _ticks,
taskqueue_timeout_func, ttask); taskqueue_timeout_func, ttask);
} }
} }