diff options
author | jlemon <jlemon@FreeBSD.org> | 2001-09-29 17:48:39 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2001-09-29 17:48:39 +0000 |
commit | b0e345dfe553238af5a174f92e6f954e9afb3439 (patch) | |
tree | e9908e8ec863e6a20c8858bc3d14add44afb07ab /sys/kern/kern_event.c | |
parent | d8102a69adad4133d98e5b1c44107069b8d31373 (diff) | |
download | FreeBSD-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.c | 44 |
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; } |