Make the multiple DPC threads an option, and create only one by default.

This avoids the need for sched_bind() in the default case so that you
can start up the NDIS subsystem at boot time when only CPU 0 is running.

There are potentially ways to fix it so that the DPC threads aren't
started until after the other CPUs are launched, but doing it correctly
is tricky. You need to defer the startup of the ntoskrnl subsystem
(ntoskrnl_libinit()), not just defer ndis_attach().

For now, I don't think it will make much difference having just the
single DPC thread (I started out with just one anyway). Note that this
turns the KeSetTargetProcessorDpc() routine into a no-op, since the
CPU number in struct kdpc is now ignored.
This commit is contained in:
Bill Paul 2005-10-22 05:15:20 +00:00
parent 201aec8321
commit a50286e21d

View File

@ -269,7 +269,11 @@ ntoskrnl_libinit()
mtx_init(&ntoskrnl_calllock, MTX_NTOSKRNL_SPIN_LOCK, NULL, MTX_SPIN);
kq_queues = ExAllocatePoolWithTag(NonPagedPool,
#ifdef NTOSKRNL_MULTIPLE_DPCS
sizeof(kdpc_queue) * mp_ncpus, 0);
#else
sizeof(kdpc_queue), 0);
#endif
if (kq_queues == NULL)
return(ENOMEM);
@ -287,7 +291,11 @@ ntoskrnl_libinit()
* Launch the DPC threads.
*/
#ifdef NTOSKRNL_MULTIPLE_DPCS
for (i = 0; i < mp_ncpus; i++) {
#else
for (i = 0; i < 1; i++) {
#endif
kq = kq_queues + i;
kq->kq_cpu = i;
sprintf(name, "Windows DPC %d", i);
@ -3558,8 +3566,10 @@ ntoskrnl_dpc_thread(arg)
*/
mtx_lock_spin(&sched_lock);
#ifdef NTOSKRNL_MULTIPLE_DPCS
#if __FreeBSD_version >= 502102
sched_bind(curthread, kq->kq_cpu);
#endif
#endif
sched_prio(curthread, PRI_MIN_KERN);
#if __FreeBSD_version < 600000
@ -3611,7 +3621,11 @@ ntoskrnl_destroy_dpc_threads(void)
int i;
kq = kq_queues;
#ifdef NTOSKRNL_MULTIPLE_DPCS
for (i = 0; i < mp_ncpus; i++) {
#else
for (i = 0; i < 1; i++) {
#endif
kq += i;
kq->kq_exit = 1;
@ -3680,6 +3694,9 @@ KeInsertQueueDpc(dpc, sysarg1, sysarg2)
if (dpc == NULL)
return(FALSE);
kq = kq_queues;
#ifdef NTOSKRNL_MULTIPLE_DPCS
KeRaiseIrql(DISPATCH_LEVEL, &irql);
/*
@ -3687,13 +3704,15 @@ KeInsertQueueDpc(dpc, sysarg1, sysarg2)
* that scheduled it.
*/
kq = kq_queues;
if (dpc->k_num == KDPC_CPU_DEFAULT)
kq += curthread->td_oncpu;
else
kq += dpc->k_num;
KeAcquireSpinLockAtDpcLevel(&kq->kq_lock);
#else
KeAcquireSpinLock(&kq->kq_lock, &irql);
#endif
r = ntoskrnl_insert_dpc(&kq->kq_disp, dpc);
if (r == TRUE) {
dpc->k_sysarg1 = sysarg1;
@ -3719,11 +3738,17 @@ KeRemoveQueueDpc(dpc)
if (dpc == NULL)
return(FALSE);
#ifdef NTOSKRNL_MULTIPLE_DPCS
KeRaiseIrql(DISPATCH_LEVEL, &irql);
kq = kq_queues + dpc->k_num;
KeAcquireSpinLockAtDpcLevel(&kq->kq_lock);
#else
kq = kq_queues;
KeAcquireSpinLock(&kq->kq_lock, &irql);
#endif
if (dpc->k_dpclistentry.nle_flink == &dpc->k_dpclistentry) {
KeReleaseSpinLockFromDpcLevel(&kq->kq_lock);
KeLowerIrql(irql);
@ -3775,7 +3800,11 @@ KeFlushQueuedDpcs(void)
* for them to drain.
*/
#ifdef NTOSKRNL_MULTIPLE_DPCS
for (i = 0; i < mp_ncpus; i++) {
#else
for (i = 0; i < 1; i++) {
#endif
kq = kq_queues + i;
KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE);
KeWaitForSingleObject(&kq->kq_done, 0, 0, TRUE, NULL);