On Tue, Jul 07, 2009 at 07:10:15PM +0100, Mindaugas Rasiukevicius wrote: > > > Module Name: src > > > Committed By: dyoung > > > Date: Fri Jun 26 19:30:46 UTC 2009 > > > > > > Modified Files: > > > src/sys/kern: kern_pmf.c subr_autoconf.c > > > src/sys/sys: device.h > > > > > > Log Message: > > > Switch to kmem(9). > > > > > > (void *)pew is one way to get a struct work *, but let's > > > write&pew->pew_work, instead. It is more defensive and persuasive. > > > > > > > It seems that pmf_event_inject() is called from interrupt context, from > > which kmem(9) cannot be used. You probably want to use pool_cache(9), or > > perhaps avoid allocations at all (since they are not intensive). > > > > Are you planning to fix it? It should probably be reverted, if takes a while.
How is this for a fix? I haven't run-tested this, yet. Dave -- David Young OJC Technologies dyo...@ojctech.com Urbana, IL * (217) 278-3933
Index: sys/kern/kern_pmf.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_pmf.c,v retrieving revision 1.27 diff -p -u -u -p -r1.27 kern_pmf.c --- sys/kern/kern_pmf.c 26 Jun 2009 19:30:45 -0000 1.27 +++ sys/kern/kern_pmf.c 7 Jul 2009 18:18:23 -0000 @@ -89,11 +100,19 @@ static TAILQ_HEAD(, pmf_event_handler) p TAILQ_HEAD_INITIALIZER(pmf_all_events); typedef struct pmf_event_workitem { - struct work pew_work; - pmf_generic_event_t pew_event; - device_t pew_device; + struct work pew_work; + pmf_generic_event_t pew_event; + device_t pew_device; + SIMPLEQ_ENTRY(pmf_event_workitem) pew_next_free; } pmf_event_workitem_t; +static kmutex_t pew_mtx; +static pmf_event_workitem_t pew_array[16]; +static SIMPLEQ_HEAD(, pmf_event_workitem) pew_list = + SIMPLEQ_HEAD_INITIALIZER(pew_list); + +static pmf_event_workitem_t *pmf_event_workitem_get(void); +static void pmf_event_workitem_put(pmf_event_workitem_t *); static bool pmf_device_resume_locked(device_t PMF_FN_PROTO); @@ -116,7 +203,7 @@ pmf_event_worker(struct work *wk, void * (*event->pmf_handler)(event->pmf_device); } - kmem_free(pew, sizeof(*pew)); + pmf_event_workitem_put(pew); } static bool @@ -555,7 +928,7 @@ pmf_event_inject(device_t dv, pmf_generi { pmf_event_workitem_t *pew; - pew = kmem_alloc(sizeof(pmf_event_workitem_t), KM_NOSLEEP); + pew = pmf_event_workitem_get(); if (pew == NULL) { PMF_EVENT_PRINTF(("%s: PMF event %d dropped (no memory)\n", dv ? device_xname(dv) : "<anonymous>", ev)); @@ -686,10 +1059,41 @@ pmf_class_display_register(device_t dv) return true; } +static void +pmf_event_workitem_put(pmf_event_workitem_t *pew) +{ + KASSERT(pew != NULL); + mutex_enter(&pew_mtx); + SIMPLEQ_INSERT_HEAD(&pew_list, pew, pew_next_free); + mutex_exit(&pew_mtx); +} + +static pmf_event_workitem_t * +pmf_event_workitem_get(void) +{ + pmf_event_workitem_t *pew; + + mutex_enter(&pew_mtx); + if ((pew = SIMPLEQ_FIRST(&pew_list)) != NULL) { + SIMPLEQ_REMOVE_HEAD(&pew_list, pew_next_free); + memset(pew, 0, sizeof(*pew)); + } + mutex_exit(&pew_mtx); + + return pew; +} + void pmf_init(void) { - int err; + int err, i; + + mutex_init(&pew_mtx, MUTEX_DEFAULT, IPL_HIGH); + + SIMPLEQ_INIT(&pew_list); + + for (i = __arraycount(pew_array); --i >= 0; ) + SIMPLEQ_INSERT_HEAD(&pew_list, &pew_array[i], pew_next_free); KASSERT(pmf_event_workqueue == NULL); err = workqueue_create(&pmf_event_workqueue, "pmfevent",