summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2004-03-25 08:23:08 +0000
committerwpaul <wpaul@FreeBSD.org>2004-03-25 08:23:08 +0000
commit57efe0d11e10072b9cc7f8b04f3de0bb7e2dd356 (patch)
tree6ce26621a7306c00c984a1277c433aee4d2bbff5 /sys/compat
parentb920a97333ac893452c623976ea6560c7caaa6a8 (diff)
downloadFreeBSD-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.)
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/ndis/kern_ndis.c33
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c81
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 },
OpenPOWER on IntegriCloud