summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2004-03-10 07:43:11 +0000
committerwpaul <wpaul@FreeBSD.org>2004-03-10 07:43:11 +0000
commitdab75fac6b16faec6e60df4a6fcd6a2e2cdd4515 (patch)
tree6b864ba874e12e8ab8127bbc74071c49356f74c3
parentcd800560cfd64f550b1a4e6b03b9441aba0b4d24 (diff)
downloadFreeBSD-src-dab75fac6b16faec6e60df4a6fcd6a2e2cdd4515.zip
FreeBSD-src-dab75fac6b16faec6e60df4a6fcd6a2e2cdd4515.tar.gz
Fix several issues related to the KeInitializeTimer() etc... API stuff
that I added recently: - When a periodic timer fires, it's automatically re-armed. We must make sure to re-arm the timer _before_ invoking any caller-supplied defered procedure call: the DPC may choose to call KeCancelTimer(), and re-arming the timer after the DPC un-does the effect of the cancel. - Fix similar issue with periodic timers in subr_ndis.c. - When calling KeSetTimer() or KeSetTimerEx(), if the timer is already pending, untimeout() it first before timeout()ing it again. - The old Atheros driver for the 5211 seems to use KeSetTimerEx() incorrectly, or at the very least in a very strange way that doesn't quite follow the Microsoft documentation. In one case, it calls KeSetTimerEx() with a duetime of 0 and a period of 5000. The Microsoft documentation says that negative duetime values are relative to the current time and positive values are absolute. But it doesn't say what's supposed to happen with positive values that less than the current time, i.e. absolute values that are in the past. Lacking any further information, I have decided that timers with positive duetimes that are in the past should fire right away (or in our case, after only 1 tick). This also takes care of the other strange usage in the Atheros driver, where the duetime is specified as 500000 and the period is 50. I think someone may have meant to use -500000 and misinterpreted the documentation. - Also modified KeWaitForSingleObject() and KeWaitForMultipleObjects() to make the same duetime adjustment, since they have the same rules regarding timeout values. - Cosmetic: change name of 'timeout' variable in KeWaitForSingleObject() and KeWaitForMultipleObjects() to 'duetime' to avoid senseless (though harmless) overlap with timeout() function name. With these fixes, I can get the 5211 card to associate properly with my adhoc net using driver AR5211.SYS version 2.4.1.6.
-rw-r--r--sys/compat/ndis/subr_ndis.c8
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c87
2 files changed, 56 insertions, 39 deletions
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index df6a39a..80f5180 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -1045,10 +1045,6 @@ ndis_tick(arg)
timer = arg;
- timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
- timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
- ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header);
-
/* Automatically reload timer. */
tv.tv_sec = 0;
@@ -1058,6 +1054,10 @@ ndis_tick(arg)
timer->nmt_dpc.nk_sysarg2 = ndis_tick;
callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
+ timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
+ timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
+ ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header);
+
return;
}
diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
index 556de35..cb7de09 100644
--- a/sys/compat/ndis/subr_ntoskrnl.c
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -431,12 +431,12 @@ ntoskrnl_time(tval)
*/
__stdcall static uint32_t
-ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout)
+ntoskrnl_waitforobj(obj, reason, mode, alertable, duetime)
nt_dispatch_header *obj;
uint32_t reason;
uint32_t mode;
uint8_t alertable;
- int64_t *timeout;
+ int64_t *duetime;
{
struct thread *td = curthread;
kmutant *km;
@@ -485,22 +485,26 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout)
/*
* The timeout value is specified in 100 nanosecond units
* and can be a positive or negative number. If it's positive,
- * then the timeout is absolute, and we need to convert it
+ * then the duetime is absolute, and we need to convert it
* to an absolute offset relative to now in order to use it.
- * If it's negative, then the timeout is relative and we
+ * If it's negative, then the duetime is relative and we
* just have to convert the units.
*/
- if (timeout != NULL) {
- if (*timeout < 0) {
- tv.tv_sec = - (*timeout) / 10000000 ;
- tv.tv_usec = (- (*timeout) / 10) -
+ if (duetime != NULL) {
+ if (*duetime < 0) {
+ tv.tv_sec = - (*duetime) / 10000000;
+ tv.tv_usec = (- (*duetime) / 10) -
(tv.tv_sec * 1000000);
} else {
ntoskrnl_time(&curtime);
- tv.tv_sec = ((*timeout) - curtime) / 10000000 ;
- tv.tv_usec = ((*timeout) - curtime) / 10 -
- (tv.tv_sec * 1000000);
+ if (*duetime < curtime)
+ tv.tv_sec = tv.tv_usec = 0;
+ else {
+ tv.tv_sec = ((*duetime) - curtime) / 10000000;
+ tv.tv_usec = ((*duetime) - curtime) / 10 -
+ (tv.tv_sec * 1000000);
+ }
}
}
@@ -508,10 +512,10 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout)
if (td->td_proc->p_flag & P_KTHREAD)
error = kthread_suspend(td->td_proc,
- timeout == NULL ? 0 : tvtohz(&tv));
+ duetime == NULL ? 0 : tvtohz(&tv));
else
error = tsleep(td, PPAUSE|PDROP, "ndisws",
- timeout == NULL ? 0 : tvtohz(&tv));
+ duetime == NULL ? 0 : tvtohz(&tv));
mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock);
@@ -549,14 +553,14 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout)
__stdcall static uint32_t
ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode,
- alertable, timeout, wb_array)
+ alertable, duetime, wb_array)
uint32_t cnt;
nt_dispatch_header *obj[];
uint32_t wtype;
uint32_t reason;
uint32_t mode;
uint8_t alertable;
- int64_t *timeout;
+ int64_t *duetime;
wait_block *wb_array;
{
struct thread *td = curthread;
@@ -622,16 +626,20 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode,
wcnt++;
}
- if (timeout != NULL) {
- if (*timeout < 0) {
- tv.tv_sec = - (*timeout) / 10000000 ;
- tv.tv_usec = (- (*timeout) / 10) -
+ if (duetime != NULL) {
+ if (*duetime < 0) {
+ tv.tv_sec = - (*duetime) / 10000000;
+ tv.tv_usec = (- (*duetime) / 10) -
(tv.tv_sec * 1000000);
} else {
ntoskrnl_time(&curtime);
- tv.tv_sec = ((*timeout) - curtime) / 10000000 ;
- tv.tv_usec = ((*timeout) - curtime) / 10 -
- (tv.tv_sec * 1000000);
+ if (*duetime < curtime)
+ tv.tv_sec = tv.tv_usec = 0;
+ else {
+ tv.tv_sec = ((*duetime) - curtime) / 10000000;
+ tv.tv_usec = ((*duetime) - curtime) / 10 -
+ (tv.tv_sec * 1000000);
+ }
}
}
@@ -641,10 +649,10 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode,
if (td->td_proc->p_flag & P_KTHREAD)
error = kthread_suspend(td->td_proc,
- timeout == NULL ? 0 : tvtohz(&tv));
+ duetime == NULL ? 0 : tvtohz(&tv));
else
error = tsleep(td, PPAUSE|PDROP, "ndisws",
- timeout == NULL ? 0 : tvtohz(&tv));
+ duetime == NULL ? 0 : tvtohz(&tv));
mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock);
nanotime(&t2);
@@ -670,7 +678,7 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode,
if (error || wtype == WAITTYPE_ANY)
break;
- if (timeout != NULL) {
+ if (duetime != NULL) {
tv.tv_sec -= (t2.tv_sec - t1.tv_sec);
tv.tv_usec -= (t2.tv_nsec - t1.tv_nsec) / 1000;
}
@@ -1658,10 +1666,6 @@ ntoskrnl_timercall(arg)
timer = arg;
dpc = timer->k_dpc;
- timerfunc = (kdpc_func)dpc->k_deferedfunc;
- timerfunc(dpc, dpc->k_deferredctx, dpc->k_sysarg1, dpc->k_sysarg2);
-
- ntoskrnl_wakeup(&timer->k_header);
/*
* If this is a periodic timer, re-arm it
@@ -1675,6 +1679,14 @@ ntoskrnl_timercall(arg)
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);
+ }
+
+ ntoskrnl_wakeup(&timer->k_header);
+
return;
}
@@ -1741,9 +1753,10 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc)
return(FALSE);
if (timer->k_handle.callout != NULL &&
- callout_pending(timer->k_handle.callout))
+ callout_pending(timer->k_handle.callout)) {
+ untimeout(ntoskrnl_timercall, timer, timer->k_handle);
pending = TRUE;
- else
+ } else
pending = FALSE;
timer->k_duetime = duetime;
@@ -1752,14 +1765,18 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc)
timer->k_dpc = dpc;
if (duetime < 0) {
- tv.tv_sec = - (duetime) / 10000000 ;
+ tv.tv_sec = - (duetime) / 10000000;
tv.tv_usec = (- (duetime) / 10) -
(tv.tv_sec * 1000000);
} else {
ntoskrnl_time(&curtime);
- tv.tv_sec = ((duetime) - curtime) / 10000000 ;
- tv.tv_usec = ((duetime) - curtime) / 10 -
- (tv.tv_sec * 1000000);
+ if (duetime < curtime)
+ tv.tv_sec = tv.tv_usec = 0;
+ else {
+ tv.tv_sec = ((duetime) - curtime) / 10000000;
+ tv.tv_usec = ((duetime) - curtime) / 10 -
+ (tv.tv_sec * 1000000);
+ }
}
timer->k_handle = timeout(ntoskrnl_timercall, timer, tvtohz(&tv));
OpenPOWER on IntegriCloud