Код службы FSS [2] находится в модуле adi_fss.c, и в нем была ошибка с утечкой памяти.
Примечание: эти модули имеются даже 2 разных версий, и почему Analog Devices допустила дублирование кода, непонятно. Одна версия adi_fss.c, более старая (помечена в комментариях датой 2009-07-27 14:01:21), находится в каталоге VisualDSP 5.0 \ Blackfin \ Examples \ ADSP-BF527 EZ-KIT Lite \ Services \ File System \ VDK \ shell_browser, а другая версия, более новая (2010-12-10 09:07:11), находится в каталоге VisualDSP 5.0 \ Blackfin \ lib \ src \ services \ fss. Я взял более новую версию.
Ошибка с утечкой памяти находится в функции adi_fss_Terminate. Суть ошибки в том, что при завершении работы службы FSS она должна освобождать выделенную для работы память и закрывать все используемые драйверы, чтобы они в свою очередь также освободили выделенную для себя память. Идеология сервисов и драйверов библиотек ADI построена на обмене команд между отдельными компонентами библиотек, когда для завершения соответствующего драйвера ему посылается команда завершения (например, для драйвера устройства FSS это команда ADI_FSS_CMD_DEREGISTER_DEVICE), либо, как вариант, можно напрямую вызвать соответствующую функцию завершения драйвера adi_fss_DeRegisterDevice. Но почему-то Analog Devices отошла от собственной модели, и в функции adi_fss_Terminate освобождала ресурсы драйверов в цикле очистки списка устройств pDeviceList. Вот кусок кода adi_fss_Terminate, где освобождается память:
/*********************************************************************
Функция: adi_fss_Terminate
Описание: Завершает File System Service, размонтирует все
носители данных (media) и закрывает все открытые
драйверы устройств. При этом открытые файлы
не будут аккуратно закрыты.
*********************************************************************/
__ADI_FSS_SECTION_CODE
u32 adi_fss_Terminate (void) /* Завершение FSS */
{
...
/* Проход по списку устройств */
pDevice = pDeviceList;
while (pDevice)
{
pCurrDevice = pDevice;
pDevice = pDevice->pNext;
// < ---- в этом месте вкралась ошибка: не освобождается память,
// которая была ранее выделена для поля pDev
pCurrDevice->pDev->DeviceHandle = NULL;
_adi_fss_free(-1,pCurrDevice);
}
/* Сброс указателя на список устройств */
pDeviceList = NULL;
...
}
Почему был выбран такой принцип освобождения памяти, непонятно. На самом деле в цикле прохода по списку устройств ИМХО нужно было бы посылать драйверам команду ADI_FSS_CMD_DEREGISTER_DEVICE с помощью функции adi_fss_Control, например вот так:
...
pDevice = pDeviceList;
while (pDevice)
{
pCurrDevice = pDevice;
pDevice = pDevice->pNext;
adi_fss_Control(ADI_FSS_CMD_DEREGISTER_DEVICE,
(void*)&pCurrDevice->pDev->DeviceHandle);
pCurrDevice->pDev->DeviceHandle = NULL;
//_adi_fss_free(-1,pCurrDevice); // Освобождение памяти должна теперь
// делать функция adi_fss_DeRegisterDevice
}
...
Однако этой правкой дело не ограничивается, нужно еще доработать функцию adi_fss_DeRegisterDevice, чтобы она корректно освобождала память и демонтировала устройство в зависимости от его типа. Вот кусок старого кода adi_fss_DeRegisterDevice:
__ADI_FSS_SECTION_CODE
u32 adi_fss_DeRegisterDevice (ADI_DEV_DEVICE_HANDLE DeviceHandle)
{
...
if (DeviceFound)
{
UnMountDevice (DeviceHandle);
adi_dev_Control (DeviceHandle, ADI_PID_CMD_MEDIA_ACTIVATE, (void*)false);
/* Удаление записи драйвера из списка и освобождение его памяти */
if (pAhead)
{
pAhead->pNext = pDevice->pNext;
}
else
{
pDeviceList = pDevice->pNext;
}
_adi_fss_free(-1, pDevice->pDev);
_adi_fss_free(-1, pDevice);
Result = ADI_FSS_RESULT_SUCCESS;
}
return Result;
}
Вот исправленный код, который проверяет тип устройства pDevice->Type:
__ADI_FSS_SECTION_CODE
u32 adi_fss_DeRegisterDevice (ADI_DEV_DEVICE_HANDLE DeviceHandle)
{
...
if (DeviceFound)
{
if (ADI_FSS_DEVICE_TYPE_REGISTERED_PID == pDevice->Type)
{
UnMountDevice (DeviceHandle);
adi_dev_Control (DeviceHandle, ADI_PID_CMD_MEDIA_ACTIVATE, (void*)false);
_adi_fss_free(-1, pDevice->pDev);
}
/* Удаление записи драйвера из списка и освобождение его памяти */
if (pAhead) {
pAhead->pNext = pDevice->pNext;
}
else {
pDeviceList = pDevice->pNext;
}
_adi_fss_free(-1, pDevice);
Result = ADI_FSS_RESULT_SUCCESS;
}
return Result;
}
[Более простой вариант исправления ошибки]
Можно поступить проще (но не в соответствии с концепцией "все свое ношу с собой"), и ввести исправление только в функцию adi_fss_Terminate, например вот так:
...
/* Проход по списку устройств */
pDevice = pDeviceList;
while (pDevice)
{
pCurrDevice = pDevice;
pDevice = pDevice->pNext;
if (ADI_FSS_DEVICE_TYPE_REGISTERED_PID == pCurrDevice->Type)
{
adi_fss_DeRegisterDevice (pCurrDevice->pDev->DeviceHandle);
}
pCurrDevice->pDev->DeviceHandle = NULL;
_adi_fss_free(-1,pCurrDevice);
}
/* сброс списка указателей на устройства */
pDeviceList = NULL;
...