Драйвер, вызывающий сбой пробуждения сна

В качестве исследования безопасности я пишу собственный драйвер IOKit. Драйвер регистрируется через уровень питания для драйверов, от которых он зависит. (услуги USB). Функция setPowerState вызывается, и драйвер корректно завершает работу.

Проблема в том, что случайным образом это вызывает проблемы со сном и пробуждением, и машина перезагружается. На самом деле сброс происходит во время пробуждения машины после того, как она вошла в спящий режим (видимо, пытается перейти в спящий режим)

Вопрос в том, как я могу отладить или решить эту проблему? Я использую отладку ядра FireWire, чтобы посмотреть, что происходит, но отладчик и точки останова вызывают задержки в механизме синхронизации сна, и все в беспорядке.

Данные в Интернете довольно слабые по этой проблеме, но полны жалоб на машины OSX, вызывающие сбои пробуждения во сне на чистых машинах.

Я тестирую его на разных машинах и версиях ядра, и он сохраняется.

Любая подсказка поможет.

РЕДАКТИРОВАТЬ: Дополнительный код

enum
{
    kOffPowerState, kStandbyPowerState, kIdlePowertState, kOnPowerState, kNumPowerStates
};

static IOPMPowerState gPowerStates[kNumPowerStates]   =
{
    //kOffPowerState
    {kIOPMPowerStateVersion1, 0,0,0,0,0,0,0,0,0,0,0},

    //kStandbyPowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0},

    //kIdlePowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0},

    //kOnPowerState
    {kIOPMPowerStateVersion1, kIOPMPowerOn | kIOPMDeviceUsable, kIOPMPowerOn, kIOPMPowerOn, 0,0,0,0,0,0,0,0}
};

bool driver::start(IOService* provider)
{
    IOLog("driver::start\n");

    if (IOService::start(provider) == false)
        return false; 

   PMinit();

   provider->joinPMtree(this);    
   makeUsable();
   changePowerStateTo(0);
   registerPowerDriver(this, gPowerStates, kNumPowerStates);
   registerService();
   return true;
}

IOReturn driver::setPowerState (unsigned long whichState, IOService * whatDevice)
{
    IOLog("driver::setPowerState (%lu)\n", whichState);

    if (whichState == 0)
        IOLog("driver: shutdown (%lu)\n", whichState);

    return kIOPMAckImplied;
}

person mrdvlpr    schedule 12.02.2015    source источник
comment
Вы уверены, что ядро ​​машины не паникует? также, возможно, SMC запрограммирован таким образом, что длительная задержка пробуждения заставляет его думать, что машина зависла (и, возможно, она зависла из-за бесконечного цикла в вашем драйвере или чего-то еще).   -  person Brad Allred    schedule 13.02.2015
comment
Можете ли вы свести проблему к суперминимальному тексту? Это не похоже на то, что мы можем помочь вам отладить без кода.   -  person pmdj    schedule 13.02.2015


Ответы (1)


Невыпущенная ссылка на IOService вызвала тупиковую блокировку в последовательности сна.

Мы использовали следующий код для получения указателей IOService.

mach_timespec time;
time.tv_sec = 0;
time.tv_nsec = 1000;
IOService* service = IOService::waitForService(IOService::serviceMatching(class_name, NULL), &time);
return service; 

оба IOService::serviceMatching и IOService::waitForService увеличивают счетчики ссылок.

Изменено на следующий пример кода:

OSDictionary *dict = IOService::serviceMatching(class_name, NULL);

if (dict == NULL)
    return NULL;

IOService* service = IOService::waitForMatchingService(dict, 1000);

dict->release();

return service;

IOService::waitForMatchingService не увеличивает счетчик ссылок, и мы отпускаем указатель OSDictionary.

person mrdvlpr    schedule 18.02.2015