Я работаю с микроконтроллером NXP LPC1788, и я разрабатываю многопоточное приложение в C. В части моего приложения я определяю структуру данных с настраиваемым списком. Раньше у меня были проблемы с моей программой из-за одновременного доступа к определенному списку, который, по-видимому, я решил решить, внедряя метод блокировки и метод блокировки для списков, которые потоки могут вызывать перед доступом к самому списку.Атомный тестовый набор для микроконтроллера LPC1788
Я сделал это, добавив «Сема» элемент данных в списке структуры:
typedef struct linked_list
{
list_node_t *head;
list_node_t *tail;
uint32_t len;
NODE_ITEM_TYPE_T itemType;
uint32_t itemSize;
uint8_t sema;
} linked_list_t;
Мой метод «замок захватит» дается ниже:
void LIST_AcquireLock(linked_list_t *list)
{
while(list->sema);
list->sema = 1;
}
Мой «разблокировки» метод приводится ниже:
void LIST_ReleaseLock(linked_list_t *list)
{
list->sema = 0;
}
Как правило, это работает нормально, поскольку мое приложение включает в себя добавление и удаление пунктов в список, как это тысячи раз в секунду, и я не заметил никаких ошибок, связанных с одновременным доступом с тех пор.
Однако, чтобы быть более уверенным в том, что это работает, мне было интересно, существует ли какой-либо способ внедрения тестового подхода. LPC1788 полагается на версию набора команд Thumb, специфичных для микроконтроллеров Cortex-M3, которые можно найти here или в user manual на стр. 918+.
Просматривая это, я не могу найти ничего похожего на инструкцию по тестированию. Я мог бы просто пропустить это.
В идеале я хотел бы иметь что-то вроде этого:
void LIST_AcquireLock(linked_list_t *list)
{
do{
while(list->sema);
} while(TestAndSet(list->sema));
}
EDIT
На основании ответа Немо, я попытался следующее:
void LIST_AcquireLock(linked_list_t *list)
{
// Wait until lock seems free.
while(list->sema);
// Make sure lock is actually free.
do {
// If the semaphore is locked, we continue.
// OTHERWISE we try to lock it ourselves.
if(__LDREXB(&(list->sema))) continue;
// If __STREXB returns 1, then another thread might have accessed that
// memory location and we can't be sure the lock operation is atomic,
// so try the locking procedure again.
} while(__STREXB(1, &(list->sema)));
}
Если это полезно, это соответствующий код сборки:
LIST_AcquireLock:
??LIST_AcquireLock_0:
0x56de: 0x7d01 LDRB R1, [R0, #0x14]
0x56e0: 0x2900 CMP R1, #0
0x56e2: 0xd1fc BNE.N ??LIST_AcquireLock_0 ; 0x56de
??LIST_AcquireLock_1:
0x56e4: 0xf110 0x0114 ADDS.W R1, R0, #20 ; 0x14
0x56e8: 0xe8d1 0x1f4f LDREXB R1, [R1]
0x56ec: 0xb2c9 UXTB R1, R1
0x56ee: 0x2900 CMP R1, #0
??LIST_AcquireLock_2:
0x56f0: 0xf110 0x0114 ADDS.W R1, R0, #20 ; 0x14
0x56f4: 0x2201 MOVS R2, #1
0x56f6: 0xe8c1 0x2f43 STREXB R3, R2, [R1]
0x56fa: 0x2b00 CMP R3, #0
0x56fc: 0xd1f2 BNE.N ??LIST_AcquireLock_1 ; 0x56e4
0x56fe: 0x4770 BX LR
У меня возникли проблемы с воспроизведением параллельных проблем доступа (при условии, что это были проблемы параллелизма, которые у меня были), поэтому я не знаю точно, что это работает.
http://www.doulos.com/knowhow/arm/Hints_and_Tips/Implementing_Semaphores/ –
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHEJCHB ,html –
Спасибо за ссылки, я дам им прочитать. – Tagc