diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-04-16 00:04:28 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-04-16 00:04:28 +0000 |
commit | 1ea56deba6d80d9814e14d9824afaabbd44e2083 (patch) | |
tree | 2e4ed3d35b5e784b6240148e29a679482a5c5573 /sys | |
parent | 2b19543d6c25a0cb41471328b2231cf8b28a08a2 (diff) | |
download | FreeBSD-src-1ea56deba6d80d9814e14d9824afaabbd44e2083.zip FreeBSD-src-1ea56deba6d80d9814e14d9824afaabbd44e2083.tar.gz |
- Use memory barrier with atomic operations in ntoskrnl_lock_dpc() and
ntoskrnl_unlocl_dpc().
- hal_raise_irql(), hal_lower_irql() and hal_irql() didn't work right
on SMP (priority inheritance makes things... interesting). For now,
use only two states: DISPATCH_LEVEL (PI_REALTIME) and PASSIVE_LEVEL
(everything else). Tested on a dual PIII box.
- Use ndis_thsuspend() in ndis_sleep() instead of tsleep(). (I added
ndis_thsuspend() and ndis_thresume() to replace kthread_suspend()
and kthread_resume(); the former will preserve a thread's priority
when it wakes up, the latter will not.)
- Change use of tsleep() in ndis_stop_thread() to prevent priority
change on wakeup.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 2 | ||||
-rw-r--r-- | sys/compat/ndis/ntoskrnl_var.h | 4 | ||||
-rw-r--r-- | sys/compat/ndis/subr_hal.c | 56 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 3 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 12 |
5 files changed, 21 insertions, 56 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 733e0d3..6e5d35a 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -348,7 +348,7 @@ ndis_stop_thread(t) /* wait for thread exit */ - tsleep(r, PPAUSE|PCATCH, "ndisthrexit", hz * 60); + tsleep(r, curthread->td_priority|PCATCH, "ndisthexit", hz * 60); /* Now empty the job list. */ diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index 1e7b5a1..24260c6 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -204,10 +204,10 @@ typedef struct nt_dispatch_header nt_dispatch_header; ((td)->td_proc->p_flag & P_KTHREAD == FALSE) #define AT_DISPATCH_LEVEL(td) \ - ((td)->td_priority == PI_SOFT) + ((td)->td_priority == PI_REALTIME) #define AT_DIRQL_LEVEL(td) \ - ((td)->td_priority < PRI_MIN_KERN) + ((td)->td_priority <= PI_NET) #define AT_HIGH_LEVEL(td) \ ((td)->td_critnest != 0) diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c index beae7c1..9111cb2 100644 --- a/sys/compat/ndis/subr_hal.c +++ b/sys/compat/ndis/subr_hal.c @@ -266,6 +266,7 @@ hal_lock(/*lock*/void) oldirql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); FASTCALL1(ntoskrnl_lock_dpc, lock); + return(oldirql); } @@ -288,10 +289,6 @@ hal_irql(void) { if (AT_DISPATCH_LEVEL(curthread)) return(DISPATCH_LEVEL); - if (AT_DIRQL_LEVEL(curthread)) - return(DEVICE_LEVEL); - if (AT_HIGH_LEVEL(curthread)) - return(HIGH_LEVEL); return(PASSIVE_LEVEL); } @@ -313,27 +310,13 @@ hal_raise_irql(/*irql*/ void) __asm__ __volatile__ ("" : "=c" (irql)); - switch(irql) { - case HIGH_LEVEL: - oldirql = hal_irql(); - critical_enter(); - break; - case DEVICE_LEVEL: - mtx_lock_spin(&sched_lock); - oldirql = curthread->td_priority; - sched_prio(curthread, PI_REALTIME); - mtx_unlock_spin(&sched_lock); - break; - case DISPATCH_LEVEL: - mtx_lock_spin(&sched_lock); - oldirql = curthread->td_priority; - sched_prio(curthread, PI_SOFT); - mtx_unlock_spin(&sched_lock); - break; - default: - panic("can't raise IRQL to unknown level %d", irql); - break; - } + if (irql < hal_irql()) + panic("IRQL_NOT_LESS_THAN"); + + mtx_lock_spin(&sched_lock); + oldirql = curthread->td_priority; + sched_prio(curthread, PI_REALTIME); + mtx_unlock_spin(&sched_lock); return(oldirql); } @@ -342,26 +325,15 @@ __stdcall void hal_lower_irql(/*oldirql*/ void) { uint8_t oldirql; - uint8_t irql; __asm__ __volatile__ ("" : "=c" (oldirql)); - irql = hal_irql(); - - switch (irql) { - case HIGH_LEVEL: - critical_exit(); - break; - case DEVICE_LEVEL: - case DISPATCH_LEVEL: - mtx_lock_spin(&sched_lock); - sched_prio(curthread, oldirql); - mtx_unlock_spin(&sched_lock); - break; - default: - panic("can't lower IRQL to unknown level %d", irql); - break; - } + if (hal_irql() != DISPATCH_LEVEL) + panic("IRQL_NOT_GREATER_THAN"); + + mtx_lock_spin(&sched_lock); + sched_prio(curthread, oldirql); + mtx_unlock_spin(&sched_lock); return; } diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 24320b0..7b22f4c 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -2162,12 +2162,11 @@ ndis_sleep(usecs) uint32_t usecs; { struct timeval tv; - uint32_t dummy; tv.tv_sec = 0; tv.tv_usec = usecs; - tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); + ndis_thsuspend(curthread->td_proc, tvtohz(&tv)); return; } diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index 7162d59..a825cab 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -406,12 +406,6 @@ ntoskrnl_time(tval) * synchronization event wakes up just one. Also, a synchronization event * is auto-clearing, which means we automatically set the event back to * the non-signalled state once the wakeup is done. - * - * The problem with KeWaitForSingleObject() is that it can be called - * either from the main kernel 'process' or from a kthread. When sleeping - * inside a kernel thread, we need to use kthread_resume(), but that - * won't work in the kernel context proper. So if kthread_resume() returns - * EINVAL, we need to use tsleep() instead. */ __stdcall uint32_t @@ -1034,8 +1028,8 @@ ntoskrnl_lock_dpc(/*lock*/ void) __asm__ __volatile__ ("" : "=c" (lock)); - while (atomic_cmpset_int((volatile u_int *)lock, 0, 1) == 0) - /* do noting */; + while (atomic_cmpset_acq_int((volatile u_int *)lock, 0, 1) == 0) + /* do nothing */; return; } @@ -1047,7 +1041,7 @@ ntoskrnl_unlock_dpc(/*lock*/ void) __asm__ __volatile__ ("" : "=c" (lock)); - atomic_cmpset_int((volatile u_int *)lock, 1, 0); + atomic_cmpset_rel_int((volatile u_int *)lock, 1, 0); return; } |