summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-09-29 17:48:39 +0000
committerjlemon <jlemon@FreeBSD.org>2001-09-29 17:48:39 +0000
commitb0e345dfe553238af5a174f92e6f954e9afb3439 (patch)
treee9908e8ec863e6a20c8858bc3d14add44afb07ab /sys/kern/kern_event.c
parentd8102a69adad4133d98e5b1c44107069b8d31373 (diff)
downloadFreeBSD-src-b0e345dfe553238af5a174f92e6f954e9afb3439.zip
FreeBSD-src-b0e345dfe553238af5a174f92e6f954e9afb3439.tar.gz
Have EVFILT_TIMERS allocate their callouts via malloc() instead of using
the static callout list allocated by the system. Change malloc type from M_TEMP to M_KQUEUE to better track memory. Add a kern.kq_calloutmax to globally limit the amount of kernel memory that can be allocated by callouts. Submitted by: iedowse (items 1, 2)
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 44a1401..191010d 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -45,11 +45,14 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/sysproto.h>
#include <sys/uio.h>
#include <vm/vm_zone.h>
+MALLOC_DEFINE(M_KQUEUE, "kqueue", "memory for kqueue system");
+
static int kqueue_scan(struct file *fp, int maxevents,
struct kevent *ulistp, const struct timespec *timeout,
struct thread *td);
@@ -105,6 +108,10 @@ static struct filterops timer_filtops =
{ 0, filt_timerattach, filt_timerdetach, filt_timer };
static vm_zone_t knote_zone;
+static int kq_ncallouts = 0;
+static int kq_calloutmax = (4 * 1024);
+SYSCTL_INT(_kern, OID_AUTO, kq_calloutmax, CTLFLAG_RW,
+ &kq_calloutmax, 0, "Maximum number of callouts allocated for kqueue");
#define KNOTE_ACTIVATE(kn) do { \
kn->kn_status |= KN_ACTIVE; \
@@ -278,7 +285,7 @@ static void
filt_timerexpire(void *knx)
{
struct knote *kn = knx;
- struct callout_handle ch;
+ struct callout *calloutp;
struct timeval tv;
int tticks;
@@ -289,8 +296,8 @@ filt_timerexpire(void *knx)
tv.tv_sec = kn->kn_sdata / 1000;
tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
tticks = tvtohz(&tv);
- ch = timeout(filt_timerexpire, kn, tticks);
- kn->kn_hook = (caddr_t)ch.callout;
+ calloutp = (struct callout *)kn->kn_hook;
+ callout_reset(calloutp, tticks, filt_timerexpire, kn);
}
}
@@ -300,17 +307,24 @@ filt_timerexpire(void *knx)
static int
filt_timerattach(struct knote *kn)
{
- struct callout_handle ch;
+ struct callout *calloutp;
struct timeval tv;
int tticks;
+ if (kq_ncallouts >= kq_calloutmax)
+ return (ENOMEM);
+ kq_ncallouts++;
+
tv.tv_sec = kn->kn_sdata / 1000;
tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
tticks = tvtohz(&tv);
kn->kn_flags |= EV_CLEAR; /* automatically set */
- ch = timeout(filt_timerexpire, kn, tticks);
- kn->kn_hook = (caddr_t)ch.callout;
+ MALLOC(calloutp, struct callout *, sizeof(*calloutp),
+ M_KQUEUE, M_WAITOK);
+ callout_init(calloutp, 0);
+ callout_reset(calloutp, tticks, filt_timerexpire, kn);
+ kn->kn_hook = (caddr_t)calloutp;
return (0);
}
@@ -318,10 +332,12 @@ filt_timerattach(struct knote *kn)
static void
filt_timerdetach(struct knote *kn)
{
- struct callout_handle ch;
+ struct callout *calloutp;
- ch.callout = (struct callout *)kn->kn_hook;
- untimeout(filt_timerexpire, kn, ch);
+ calloutp = (struct callout *)kn->kn_hook;
+ callout_stop(calloutp);
+ FREE(calloutp, M_KQUEUE);
+ kq_ncallouts--;
}
static int
@@ -350,7 +366,7 @@ kqueue(struct thread *td, struct kqueue_args *uap)
fp->f_flag = FREAD | FWRITE;
fp->f_type = DTYPE_KQUEUE;
fp->f_ops = &kqueueops;
- kq = malloc(sizeof(struct kqueue), M_TEMP, M_WAITOK | M_ZERO);
+ kq = malloc(sizeof(struct kqueue), M_KQUEUE, M_WAITOK | M_ZERO);
TAILQ_INIT(&kq->kq_head);
fp->f_data = (caddr_t)kq;
td->td_retval[0] = fd;
@@ -809,7 +825,7 @@ kqueue_close(struct file *fp, struct thread *td)
}
}
}
- free(kq, M_TEMP);
+ free(kq, M_KQUEUE);
fp->f_data = NULL;
return (0);
@@ -877,7 +893,7 @@ knote_attach(struct knote *kn, struct filedesc *fdp)
if (! kn->kn_fop->f_isfd) {
if (fdp->fd_knhashmask == 0)
- fdp->fd_knhash = hashinit(KN_HASHSIZE, M_TEMP,
+ fdp->fd_knhash = hashinit(KN_HASHSIZE, M_KQUEUE,
&fdp->fd_knhashmask);
list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
goto done;
@@ -888,14 +904,14 @@ knote_attach(struct knote *kn, struct filedesc *fdp)
while (size <= kn->kn_id)
size += KQEXTENT;
MALLOC(list, struct klist *,
- size * sizeof(struct klist *), M_TEMP, M_WAITOK);
+ size * sizeof(struct klist *), M_KQUEUE, M_WAITOK);
bcopy((caddr_t)fdp->fd_knlist, (caddr_t)list,
fdp->fd_knlistsize * sizeof(struct klist *));
bzero((caddr_t)list +
fdp->fd_knlistsize * sizeof(struct klist *),
(size - fdp->fd_knlistsize) * sizeof(struct klist *));
if (fdp->fd_knlist != NULL)
- FREE(fdp->fd_knlist, M_TEMP);
+ FREE(fdp->fd_knlist, M_KQUEUE);
fdp->fd_knlistsize = size;
fdp->fd_knlist = list;
}
OpenPOWER on IntegriCloud