28 #include <sys/cdefs.h>
31 #include "opt_device_polling.h"
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/kthread.h>
38 #include <sys/eventhandler.h>
39 #include <sys/resourcevar.h>
40 #include <sys/socket.h>
41 #include <sys/sockio.h>
42 #include <sys/sysctl.h>
43 #include <sys/syslog.h>
46 #include <net/netisr.h>
94 #define MIN_POLL_BURST_MAX 10
95 #define MAX_POLL_BURST_MAX 1000
101 static SYSCTL_NODE(_kern, OID_AUTO, polling, CTLFLAG_RW, 0,
102 "Device polling parameters");
104 SYSCTL_UINT(_kern_polling, OID_AUTO, burst, CTLFLAG_RD,
105 &
poll_burst, 0,
"Current polling burst size");
117 if (error || !req->newptr )
132 SYSCTL_PROC(_kern_polling, OID_AUTO, burst_max, CTLTYPE_UINT | CTLFLAG_RW,
141 if (error || !req->newptr )
156 SYSCTL_PROC(_kern_polling, OID_AUTO, each_burst, CTLTYPE_UINT | CTLFLAG_RW,
158 "Max size of each burst");
161 SYSCTL_UINT(_kern_polling, OID_AUTO, idle_poll, CTLFLAG_RW,
162 &poll_in_idle_loop, 0,
"Enable device polling in idle loop");
171 if (error || !req->newptr )
173 if (val < 0 || val > 99)
182 SYSCTL_PROC(_kern_polling, OID_AUTO, user_frac, CTLTYPE_UINT | CTLFLAG_RW,
184 "Desired user fraction of cpu time");
194 if (error || !req->newptr )
196 if (val < 1 || val >
hz)
201 if (reg_frac_count >= reg_frac)
207 SYSCTL_PROC(_kern_polling, OID_AUTO, reg_frac, CTLTYPE_UINT | CTLFLAG_RW,
209 "Every this many cycles check registers");
212 SYSCTL_UINT(_kern_polling, OID_AUTO, short_ticks, CTLFLAG_RD,
213 &short_ticks, 0,
"Hardclock ticks shorter than they should be");
216 SYSCTL_UINT(_kern_polling, OID_AUTO, lost_polls, CTLFLAG_RD,
217 &lost_polls, 0,
"How many times we would have lost a poll tick");
220 SYSCTL_UINT(_kern_polling, OID_AUTO, pending_polls, CTLFLAG_RD,
221 &pending_polls, 0,
"Do we need to poll again");
224 SYSCTL_INT(_kern_polling, OID_AUTO, residual_burst, CTLFLAG_RD,
225 &residual_burst, 0,
"# of residual cycles in burst");
228 SYSCTL_UINT(_kern_polling, OID_AUTO, handlers, CTLFLAG_RD,
229 &poll_handlers, 0,
"Number of registered poll handlers");
232 SYSCTL_UINT(_kern_polling, OID_AUTO, phase, CTLFLAG_RD,
233 &phase, 0,
"Polling phase");
236 SYSCTL_UINT(_kern_polling, OID_AUTO, suspect, CTLFLAG_RD,
237 &suspect, 0,
"suspect event");
240 SYSCTL_UINT(_kern_polling, OID_AUTO, stalled, CTLFLAG_RD,
241 &stalled, 0,
"potential stalls");
244 SYSCTL_UINT(_kern_polling, OID_AUTO, idlepoll_sleeping, CTLFLAG_RD,
245 &idlepoll_sleeping, 0,
"idlepoll is sleeping");
248 #define POLL_LIST_LEN 128
268 EVENTHANDLER_REGISTER(shutdown_post_sync,
poll_shutdown, NULL,
290 static struct timeval prev_t, t;
297 delta = (t.tv_usec - prev_t.tv_usec) +
298 (t.tv_sec - prev_t.tv_sec)*1000000;
299 if (delta *
hz < 500000)
304 if (pending_polls > 100) {
323 if (pending_polls++ > 0)
341 pr[i].handler(
pr[i].ifp, POLL_ONLY, count);
377 if (residual_burst > 0) {
389 kern_load = (kern_load *
hz) / 10000;
390 if (kern_load > (100 - user_frac)) {
399 if (pending_polls == 0)
425 enum poll_cmd arg = POLL_ONLY;
434 if (residual_burst == 0) {
436 if (++reg_frac_count == reg_frac) {
437 arg = POLL_AND_CHECK_STATUS;
445 residual_burst -= cycles;
448 pr[i].handler(
pr[i].ifp, arg, cycles);
466 KASSERT(h != NULL, (
"%s: handler is NULL", __func__));
467 KASSERT(ifp != NULL, (
"%s: ifp is NULL", __func__));
478 static int verbose = 10 ;
480 log(LOG_ERR,
"poll handlers list full, "
481 "maybe a broken driver ?\n");
489 if (
pr[i].ifp == ifp &&
pr[i].handler != NULL) {
491 log(LOG_DEBUG,
"ether_poll_register: %s: handler"
492 " already registered\n", ifp->if_xname);
500 if (idlepoll_sleeping)
501 wakeup(&idlepoll_sleeping);
513 KASSERT(ifp != NULL, (
"%s: ifp is NULL", __func__));
518 if (
pr[i].ifp == ifp)
520 if (i == poll_handlers) {
521 log(LOG_DEBUG,
"ether_poll_deregister: %s: not found!\n",
527 if (i < poll_handlers) {
538 struct thread *td = curthread;
541 rtp.prio = RTP_PRIO_MAX;
542 rtp.type = RTP_PRIO_IDLE;
543 PROC_SLOCK(td->td_proc);
545 PROC_SUNLOCK(td->td_proc);
548 if (poll_in_idle_loop && poll_handlers > 0) {
549 idlepoll_sleeping = 0;
555 idlepoll_sleeping = 1;
556 tsleep(&idlepoll_sleeping, 0,
"pollid",
hz * 3);
static void poll_idle(void)
#define MAX_POLL_BURST_MAX
static uint32_t lost_polls
static uint32_t short_ticks
static struct timeval poll_start_t
SYSCTL_INT(_kern_polling, OID_AUTO, residual_burst, CTLFLAG_RD,&residual_burst, 0,"# of residual cycles in burst")
static uint32_t user_frac
static uint32_t poll_handlers
static void ether_poll(int count)
static uint32_t pending_polls
static int reg_frac_sysctl(SYSCTL_HANDLER_ARGS)
static uint32_t idlepoll_sleeping
void hardclock_device_poll(void)
void mi_switch(int flags, struct thread *newtd)
static void init_device_poll(void)
#define MIN_POLL_BURST_MAX
static int residual_burst
static int netisr_pollmore_scheduled
static uint32_t reg_frac_count
int rtp_to_pri(struct rtprio *rtp, struct thread *td)
static SYSCTL_NODE(_kern, OID_AUTO, polling, CTLFLAG_RW, 0,"Device polling parameters")
static struct proc * idlepoll
static uint32_t poll_in_idle_loop
static uint32_t poll_burst_max
static int poll_shutting_down
int sysctl_handle_int(SYSCTL_HANDLER_ARGS)
static int netisr_poll_scheduled
void log(int level, const char *fmt,...)
SYSINIT(device_poll, SI_SUB_CLOCKS, SI_ORDER_MIDDLE, init_device_poll, NULL)
static struct kproc_desc idlepoll_kp
static void poll_shutdown(void *arg, int howto)
int ether_poll_deregister(struct ifnet *ifp)
static uint32_t poll_each_burst
SYSCTL_PROC(_kern_polling, OID_AUTO, burst_max, CTLTYPE_UINT|CTLFLAG_RW, 0, sizeof(uint32_t), poll_burst_max_sysctl,"I","Max Polling burst size")
static uint32_t poll_burst
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
void kproc_start(void *udata) const
static int user_frac_sysctl(SYSCTL_HANDLER_ARGS)
static struct mtx poll_mtx
void microuptime(struct timeval *tvp)
SYSCTL_UINT(_kern_polling, OID_AUTO, burst, CTLFLAG_RD,&poll_burst, 0,"Current polling burst size")
static int poll_burst_max_sysctl(SYSCTL_HANDLER_ARGS)
static struct pollrec pr[POLL_LIST_LEN]
int ether_poll_register(poll_handler_t *h, struct ifnet *ifp)
static int poll_each_burst_sysctl(SYSCTL_HANDLER_ARGS)