diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-03-25 08:23:08 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-03-25 08:23:08 +0000 |
commit | 57efe0d11e10072b9cc7f8b04f3de0bb7e2dd356 (patch) | |
tree | 6ce26621a7306c00c984a1277c433aee4d2bbff5 | |
parent | b920a97333ac893452c623976ea6560c7caaa6a8 (diff) | |
download | FreeBSD-src-57efe0d11e10072b9cc7f8b04f3de0bb7e2dd356.zip FreeBSD-src-57efe0d11e10072b9cc7f8b04f3de0bb7e2dd356.tar.gz |
- In kern_ndis.c, implement ndis_unsched(), the complement to ndis_sched(),
which pulls a job off a thread work queue (assuming it hasn't run yet).
This is needed for KeRemoveQueueDpc().
- In subr_ntoskrnl.c, implement KeInsertQueueDpc() and KeRemoveQueueDpc(),
to go with KeInitializeDpc() to round out the API. Also change the
KeTimer implementation to use this API instead of the private
timer callout scheduler. Functionality of the timer API remains
unchanged, but we get a couple new Windows kernel API routines and
more closely imitate the way thing works in Windows. (As of yet
I haven't encountered any drivers that use KeInsertQueueDpc() or
KeRemoveQueueDpc(), but it doesn't hurt to have them.)
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 33 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 81 |
2 files changed, 86 insertions, 28 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 89cc5e6..f633a1c 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -403,6 +403,39 @@ ndis_shrink_thrqueue(cnt) } int +ndis_unsched(func, arg, t) + void (*func)(void *); + void *arg; + int t; +{ + struct ndis_req *r; + struct ndisqhead *q; + struct proc *p; + + if (t == NDIS_TASKQUEUE) { + q = &ndis_ttodo; + p = ndis_tproc.np_p; + } else { + q = &ndis_itodo; + p = ndis_iproc.np_p; + } + + mtx_pool_lock(ndis_mtxpool, ndis_thr_mtx); + STAILQ_FOREACH(r, q, link) { + if (r->nr_func == func && r->nr_arg == arg) { + STAILQ_REMOVE(q, r, ndis_req, link); + STAILQ_INSERT_HEAD(&ndis_free, r, link); + mtx_pool_unlock(ndis_mtxpool, ndis_thr_mtx); + return(0); + } + } + + mtx_pool_unlock(ndis_mtxpool, ndis_thr_mtx); + + return(ENOENT); +} + +int ndis_sched(func, arg, t) void (*func)(void *); void *arg; diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index cfc11ee..c58e8a3 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -85,7 +85,7 @@ __stdcall static uint32_t ntoskrnl_waitforobjs(uint32_t, int64_t *, wait_block *); static void ntoskrnl_wakeup(void *); static void ntoskrnl_timercall(void *); -static void ntoskrnl_timersched(void *); +static void ntoskrnl_run_dpc(void *); __stdcall static void ntoskrnl_writereg_ushort(uint16_t *, uint16_t); __stdcall static uint16_t ntoskrnl_readreg_ushort(uint16_t *); __stdcall static void ntoskrnl_writereg_ulong(uint32_t *, uint32_t); @@ -1641,31 +1641,14 @@ ntoskrnl_debugger(void) return; } -/* - * We run all timer callouts in the ndis swi thread to take - * advantage of its larger stack size. If we don't do this, - * the callout will run in the clock ithread context. - */ - -static void -ntoskrnl_timersched(arg) - void *arg; -{ - ndis_sched(ntoskrnl_timercall, arg, NDIS_SWI); - return; -} - static void ntoskrnl_timercall(arg) void *arg; { ktimer *timer; - __stdcall kdpc_func timerfunc; - kdpc *dpc; struct timeval tv; timer = arg; - dpc = timer->k_dpc; /* * If this is a periodic timer, re-arm it @@ -1680,14 +1663,11 @@ ntoskrnl_timercall(arg) tv.tv_sec = 0; tv.tv_usec = timer->k_period * 1000; timer->k_handle = - timeout(ntoskrnl_timersched, timer, tvtohz(&tv)); + timeout(ntoskrnl_timercall, timer, tvtohz(&tv)); } - if (dpc != NULL) { - timerfunc = (kdpc_func)dpc->k_deferedfunc; - timerfunc(dpc, dpc->k_deferredctx, - dpc->k_sysarg1, dpc->k_sysarg2); - } + if (timer->k_dpc != NULL) + ntoskrnl_queue_dpc(timer->k_dpc, NULL, NULL); ntoskrnl_wakeup(&timer->k_header); @@ -1727,6 +1707,25 @@ ntoskrnl_init_timer_ex(timer, type) return; } +/* + * This is a wrapper for Windows deferred procedure calls that + * have been placed on an NDIS thread work queue. We need it + * since the DPC could be a _stdcall function. + */ +static void +ntoskrnl_run_dpc(arg) + void *arg; +{ + __stdcall kdpc_func dpcfunc; + kdpc *dpc; + + dpc = arg; + dpcfunc = (kdpc_func)dpc->k_deferedfunc; + dpcfunc(dpc, dpc->k_deferredctx, dpc->k_sysarg1, dpc->k_sysarg2); + + return; +} + __stdcall void ntoskrnl_init_dpc(dpc, dpcfunc, dpcctx) kdpc *dpc; @@ -1743,6 +1742,30 @@ ntoskrnl_init_dpc(dpc, dpcfunc, dpcctx) } __stdcall uint8_t +ntoskrnl_queue_dpc(dpc, sysarg1, sysarg2) + kdpc *dpc; + void *sysarg1; + void *sysarg2; +{ + dpc->k_sysarg1 = sysarg1; + dpc->k_sysarg2 = sysarg2; + if (ndis_sched(ntoskrnl_run_dpc, dpc, NDIS_SWI)) + return(FALSE); + + return(TRUE); +} + +__stdcall uint8_t +ntoskrnl_dequeue_dpc(dpc) + kdpc *dpc; +{ + if (ndis_unsched(ntoskrnl_run_dpc, dpc, NDIS_SWI)) + return(FALSE); + + return(TRUE); +} + +__stdcall uint8_t ntoskrnl_set_timer_ex(timer, duetime, period, dpc) ktimer *timer; int64_t duetime; @@ -1758,7 +1781,7 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc) if (timer->k_handle.callout != NULL && callout_pending(timer->k_handle.callout)) { - untimeout(ntoskrnl_timersched, timer, timer->k_handle); + untimeout(ntoskrnl_timercall, timer, timer->k_handle); pending = TRUE; } else pending = FALSE; @@ -1783,7 +1806,7 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc) } } - timer->k_handle = timeout(ntoskrnl_timersched, timer, tvtohz(&tv)); + timer->k_handle = timeout(ntoskrnl_timercall, timer, tvtohz(&tv)); return(pending); } @@ -1812,7 +1835,7 @@ ntoskrnl_cancel_timer(timer) else pending = FALSE; - untimeout(ntoskrnl_timersched, timer, timer->k_handle); + untimeout(ntoskrnl_timercall, timer, timer->k_handle); return(pending); } @@ -1925,11 +1948,13 @@ image_patch_table ntoskrnl_functbl[] = { { "KeReadStateEvent", (FUNC)ntoskrnl_read_event }, { "KeInitializeTimer", (FUNC)ntoskrnl_init_timer }, { "KeInitializeTimerEx", (FUNC)ntoskrnl_init_timer_ex }, - { "KeInitializeDpc", (FUNC)ntoskrnl_init_dpc }, { "KeSetTimer", (FUNC)ntoskrnl_set_timer }, { "KeSetTimerEx", (FUNC)ntoskrnl_set_timer_ex }, { "KeCancelTimer", (FUNC)ntoskrnl_cancel_timer }, { "KeReadStateTimer", (FUNC)ntoskrnl_read_timer }, + { "KeInitializeDpc", (FUNC)ntoskrnl_init_dpc }, + { "KeInsertQueueDpc", (FUNC)ntoskrnl_queue_dpc }, + { "KeRemoveQueueDpc", (FUNC)ntoskrnl_dequeue_dpc }, { "ObReferenceObjectByHandle", (FUNC)ntoskrnl_objref }, { "ObfDereferenceObject", (FUNC)ntoskrnl_objderef }, { "ZwClose", (FUNC)ntoskrnl_zwclose }, |