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 <thread.h>
extern "C" {
# include "device.h"
# include <sys/callout.h>
# include <sys/mutex.h>
}
@@ -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);
}
+6 -36
View File
@@ -1,44 +1,14 @@
/*
* Copyright 2009, Colin Günther, [email protected]
* 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 <OS.h>
#include <compat/sys/kernel.h>
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());
}
@@ -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);
@@ -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 <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).
* 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 *);
@@ -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,
@@ -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)
@@ -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);
}
}