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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user