BSOD при KeWaitForSingleObject для KMUTEX
От: ScorpeeOn  
Дата: 22.12.07 20:23
Оценка:
Привет Всем!
Помогите разобраться с BSOD.
Я работаю со списком в драйвере и доступ к нему ограничиваю мьютексом.

PKMUTEX pProcInfoMutex; // Глобальная переменная
...
LARGE_INTEGER liWaitMutex = {0xFFFFFFFF, 0xFFFFFFFF};
...
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, &liWaitMutex);
// Здесь работаю со списком
KeReleaseMutex(pProcInfoMutex, FALSE);


Сам мьютекс инициализирован так в DriverEntry:

...
pProcInfoMutex = (PKMUTEX)ExAllocatePoolWithTag(NonPagedPool, sizeof(KMUTEX), PROCESS_POOL_TAG);
KeInitializeMutex(pProcInfoMutex, 0);
...


Без KeWaitForSingleObject и KeReleaseMutex все работает нормально.
В чем может быть причина?
С уважением,
Евгений
Re: BSOD при KeWaitForSingleObject для KMUTEX
От: TarasCo  
Дата: 22.12.07 21:42
Оценка: 3 (1)
SO>LARGE_INTEGER liWaitMutex = {0xFFFFFFFF, 0xFFFFFFFF};
SO>...
SO>ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
SO>KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, &liWaitMutex);

Ожидать мьютекса с ненулевым таймаутом можно только на PASSIVE_LEVEL. Если Вам нужно синхронизировать доступ к списку на DISPACTH_LEVEL — нужно использовать спинлок ( KSPIN_LOCK )
Да пребудет с тобою сила
Re[2]: BSOD при KeWaitForSingleObject для KMUTEX
От: ScorpeeOn  
Дата: 22.12.07 22:17
Оценка:
Здравствуйте, TarasCo, Вы писали:


SO>>LARGE_INTEGER liWaitMutex = {0xFFFFFFFF, 0xFFFFFFFF};

SO>>...
SO>>ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
SO>>KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, &liWaitMutex);

TC>Ожидать мьютекса с ненулевым таймаутом можно только на PASSIVE_LEVEL. Если Вам нужно синхронизировать доступ к списку на DISPACTH_LEVEL — нужно использовать спинлок ( KSPIN_LOCK )


Спасиб!
Вот попробовал так и все вроде работает:

KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, NULL);


Почему?

LARGE_INTEGER liWaitMutex = {0xFFFFFFFF, 0xFFFFFFFF}; // Это нулевой таймаут?!
Я по аналогии с UserMode (там INFINITE=0xFFFFFFFF)
С уважением,
Евгений
Re[2]: BSOD при KeWaitForSingleObject для KMUTEX
От: ScorpeeOn  
Дата: 23.12.07 08:51
Оценка:
Здравствуйте, TarasCo, Вы писали:


SO>>LARGE_INTEGER liWaitMutex = {0xFFFFFFFF, 0xFFFFFFFF};

SO>>...
SO>>ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
SO>>KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, &liWaitMutex);

TC>Ожидать мьютекса с ненулевым таймаутом можно только на PASSIVE_LEVEL. Если Вам нужно синхронизировать доступ к списку на DISPACTH_LEVEL — нужно использовать спинлок ( KSPIN_LOCK )


Разобрался вроде.
Я новичок, поэтому +3
С уважением,
Евгений
Re[3]: BSOD при KeWaitForSingleObject для KMUTEX
От: TarasCo  
Дата: 23.12.07 09:08
Оценка:
SO>Разобрался вроде.

Вы уверены? . Ожидание мьютекса без таймаута не гарантирует его захват. Он будет захвачен лишь в том случае, если окажется свободным. Если же Вам придет в голову на DISPATH_LEVEL опрашивать мьютекс в цикле, то есть вероятность угодить в жесткий дедлок. По сему, еще раз повторяю — надежную синхронизацию на DISPATCH_LEVEL можно сделать только с помощью спин-лока.
Да пребудет с тобою сила
Re[4]: BSOD при KeWaitForSingleObject для KMUTEX
От: ScorpeeOn  
Дата: 23.12.07 09:58
Оценка:
Здравствуйте, TarasCo, Вы писали:

SO>>Разобрался вроде.


TC>Вы уверены? . Ожидание мьютекса без таймаута не гарантирует его захват. Он будет захвачен лишь в том случае, если окажется свободным. Если же Вам придет в голову на DISPATH_LEVEL опрашивать мьютекс в цикле, то есть вероятность угодить в жесткий дедлок. По сему, еще раз повторяю — надежную синхронизацию на DISPATCH_LEVEL можно сделать только с помощью спин-лока.


Так... Тогда код приведу, как у меня...
Это там где вставляю всписок:

...
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, NULL);
InsertTailList(&DoubleHeadProcInfoList, &pProcInfo->linkfield);
KeReleaseMutex(pProcInfoMutex, FALSE);
...


NULL в KeWaitForSingleObject — это насколько я понял — захватить, пока не освобожу. Это прально?

Это там, где читаю и в юзермод передаю:

...
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
KeWaitForSingleObject(pProcInfoMutex, Executive, KernelMode, FALSE, NULL);
if( !IsListEmpty(&DoubleHeadProcInfoList) ) {
        pListEntry = RemoveHeadList(&DoubleHeadProcInfoList);
    pProcInfo = CONTAINING_RECORD(pListEntry, PROC_INFO, linkfield);
    RtlCopyMemory(pOutputBuffer, pProcInfo->chBuffer, pProcInfo->ulBuffLen);
    ulBytesSend = pProcInfo->ulBuffLen;
    ntStatus = STATUS_SUCCESS;
    ExFreePool(pProcInfo);
    InterlockedDecrement(&g_lListSize);
} // if( !IsListEmpty(&DoubleHeadProcInfoList) )
KeReleaseMutex(pProcInfoMutex, FALSE);
...


Чую, что криво...
В цикле вроде мьютекс не опрашиваю нигде.
Плиз хелп.
С уважением,
Евгений
Re[5]: BSOD при KeWaitForSingleObject для KMUTEX
От: TarasCo  
Дата: 24.12.07 09:04
Оценка:
SO>NULL в KeWaitForSingleObject — это насколько я понял — захватить, пока не освобожу. Это прально?

NULL — это значит ждать освобождения мьютекса ( с последующим захватом ) с бесконечным таймаутом. Код формально правильный, но может выполняться только на PASSIVE_LEVEL.
Да пребудет с тобою сила
Re[6]: BSOD при KeWaitForSingleObject для KMUTEX
От: ScorpeeOn  
Дата: 24.12.07 09:45
Оценка:
Здравствуйте, TarasCo, Вы писали:


SO>>NULL в KeWaitForSingleObject — это насколько я понял — захватить, пока не освобожу. Это прально?


TC>NULL — это значит ждать освобождения мьютекса ( с последующим захватом ) с бесконечным таймаутом. Код формально правильный, но может выполняться только на PASSIVE_LEVEL.


Я переделал, как Вы советовали со спинлоком. Опыту у Вас больше, поэтому прислушаюсь. Все работает.
Спасибо еще раз за разъяснения!
С уважением,
Евгений
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.