Procházet zdrojové kódy

Implement mutex for local target, fix concurrency test (#104)

* Implement mutex support for target_lo

* Kill application if test hangs

* Use mutex in furi_take and furi_give

* Give furi application enough time to finish

* remove app obj after build

* enable counting semaphores

Co-authored-by: aanper <mail@s3f.ru>
Vadim Kaushan před 5 roky
rodič
revize
884fccc591

+ 1 - 1
applications/tests/furi_record_test.c

@@ -235,7 +235,7 @@ bool test_furi_concurrent_access(FuriRecordSubscriber* log) {
         furi_give(holding_record);
         furi_give(holding_record);
     }
     }
 
 
-    delay(20);
+    delay(50);
 
 
     if(second_app->handler != NULL) {
     if(second_app->handler != NULL) {
         fuprintf(log, "second app still alive\n");
         fuprintf(log, "second app still alive\n");

+ 6 - 3
core/furi.c

@@ -192,15 +192,18 @@ static void furi_notify(FuriRecordSubscriber* handler, const void* value, size_t
 
 
 void* furi_take(FuriRecordSubscriber* handler) {
 void* furi_take(FuriRecordSubscriber* handler) {
     if(handler == NULL || handler->record == NULL) return NULL;
     if(handler == NULL || handler->record == NULL) return NULL;
-    // take mutex
 
 
-    return handler->record->value;
+    if (xSemaphoreTake(handler->record->mutex, portMAX_DELAY) == pdTRUE) {
+        return handler->record->value;
+    } else {
+        return NULL;
+    }
 }
 }
 
 
 void furi_give(FuriRecordSubscriber* handler) {
 void furi_give(FuriRecordSubscriber* handler) {
     if(handler == NULL || handler->record == NULL) return;
     if(handler == NULL || handler->record == NULL) return;
 
 
-    // release mutex
+    xSemaphoreGive(handler->record->mutex);
 }
 }
 
 
 void furi_commit(FuriRecordSubscriber* handler) {
 void furi_commit(FuriRecordSubscriber* handler) {

+ 1 - 0
target_f1/Inc/FreeRTOSConfig.h

@@ -67,6 +67,7 @@
 #define configUSE_MUTEXES                        1
 #define configUSE_MUTEXES                        1
 #define configQUEUE_REGISTRY_SIZE                8
 #define configQUEUE_REGISTRY_SIZE                8
 #define configUSE_PORT_OPTIMISED_TASK_SELECTION  1
 #define configUSE_PORT_OPTIMISED_TASK_SELECTION  1
+#define configUSE_COUNTING_SEMAPHORES			 1
 
 
 /* Co-routine definitions. */
 /* Co-routine definitions. */
 #define configUSE_CO_ROUTINES                    0
 #define configUSE_CO_ROUTINES                    0

+ 1 - 3
target_f1/Makefile

@@ -261,18 +261,16 @@ rust_lib:
 	$(RUST_LIB_CMD)
 	$(RUST_LIB_CMD)
 
 
 example_blink:
 example_blink:
-	rm $(BUILD_DIR)/app.o
 	EXAMPLE_BLINK=1 make
 	EXAMPLE_BLINK=1 make
 	rm $(BUILD_DIR)/app.o
 	rm $(BUILD_DIR)/app.o
 
 
 example_uart_write:
 example_uart_write:
-	rm $(BUILD_DIR)/app.o
 	EXAMPLE_UART_WRITE=1 make
 	EXAMPLE_UART_WRITE=1 make
 	rm $(BUILD_DIR)/app.o
 	rm $(BUILD_DIR)/app.o
 
 
 example_ipc:
 example_ipc:
-	rm $(BUILD_DIR)/app.o
 	EXAMPLE_IPC=1 make
 	EXAMPLE_IPC=1 make
+	rm $(BUILD_DIR)/app.o
 
 
 test:
 test:
 	TEST=1 make
 	TEST=1 make

+ 1 - 0
target_f1/cubemx_restore.sh

@@ -1,5 +1,6 @@
 git checkout -- target_f1/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
 git checkout -- target_f1/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h
 git checkout -- target_f1/Makefile
 git checkout -- target_f1/Makefile
+git checkout -- target_f1/Inc/FreeRTOSConfig.h
 git checkout -- target_f1/Src/stm32l4xx_it.c
 git checkout -- target_f1/Src/stm32l4xx_it.c
 git checkout -- target_f1/Src/usbd_conf.c
 git checkout -- target_f1/Src/usbd_conf.c
 git checkout -- target_f1/Src/usbd_desc.c
 git checkout -- target_f1/Src/usbd_desc.c

+ 3 - 1
target_lo/Inc/cmsis_os.h

@@ -14,10 +14,12 @@ typedef pthread_t* TaskHandle_t;
 
 
 
 
 typedef enum {
 typedef enum {
-    SemaphoreTypeCounting
+    SemaphoreTypeMutex,
+    SemaphoreTypeCounting,
 } SemaphoreType;
 } SemaphoreType;
 typedef struct {
 typedef struct {
     SemaphoreType type;
     SemaphoreType type;
+    pthread_mutex_t mutex;
     uint8_t take_counter;
     uint8_t take_counter;
     uint8_t give_counter;
     uint8_t give_counter;
 } StaticSemaphore_t;
 } StaticSemaphore_t;

+ 1 - 1
target_lo/Makefile

@@ -162,7 +162,7 @@ example_ipc:
 test:
 test:
 	rm -f $(BUILD_DIR)/app.o
 	rm -f $(BUILD_DIR)/app.o
 	TEST=1 make
 	TEST=1 make
-	$(BUILD_DIR)/$(TARGET)
+	timeout --signal=9 5 $(BUILD_DIR)/$(TARGET)
 
 
 .PHONY: all rust_lib example_blink example_uart_write test
 .PHONY: all rust_lib example_blink example_uart_write test
 
 

+ 44 - 9
target_lo/Src/lo_os.c

@@ -82,11 +82,6 @@ bool task_equal(TaskHandle_t a, TaskHandle_t b) {
     return pthread_equal(*a, *b) != 0;
     return pthread_equal(*a, *b) != 0;
 }
 }
 
 
-SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t* pxMutexBuffer) {
-    // TODO add posix mutex init
-    return NULL;
-}
-
 BaseType_t xQueueSend(
 BaseType_t xQueueSend(
     QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait
     QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait
 ) {
 ) {
@@ -127,14 +122,46 @@ SemaphoreHandle_t xSemaphoreCreateCountingStatic(
     UBaseType_t uxInitialCount,
     UBaseType_t uxInitialCount,
     StaticSemaphore_t* pxSemaphoreBuffer
     StaticSemaphore_t* pxSemaphoreBuffer
 ) {
 ) {
+    pxSemaphoreBuffer->type = SemaphoreTypeCounting;
     pxSemaphoreBuffer->take_counter = 0;
     pxSemaphoreBuffer->take_counter = 0;
     pxSemaphoreBuffer->give_counter = 0;
     pxSemaphoreBuffer->give_counter = 0;
     return pxSemaphoreBuffer;
     return pxSemaphoreBuffer;
 }
 }
 
 
-BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) {
-    if(xSemaphore == NULL) return false;
-    
+SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t* pxMutexBuffer) {
+    pxMutexBuffer->type = SemaphoreTypeMutex;
+    pthread_mutex_init(&pxMutexBuffer->mutex, NULL);
+    pxMutexBuffer->take_counter = 0;
+    pxMutexBuffer->give_counter = 0;
+    return pxMutexBuffer;
+}
+
+
+BaseType_t xSemaphoreTake(volatile SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) {
+    if(xSemaphore == NULL) return pdFALSE;
+
+    if (xSemaphore->type == SemaphoreTypeMutex) {
+        if (xTicksToWait == portMAX_DELAY) {
+            if (pthread_mutex_lock(&xSemaphore->mutex) == 0) {
+                return pdTRUE;
+            } else {
+                return pdFALSE;
+            }
+        } else {
+            TickType_t ticks = xTicksToWait;
+            while (ticks >= 0) {
+                if (pthread_mutex_trylock(&xSemaphore->mutex) == 0) {
+                    return pdTRUE;
+                }
+                if (ticks > 0) {
+                    osDelay(1);
+                }
+                ticks--;
+            }
+            return pdFALSE;
+        }
+    }
+
     // TODO: need to add inter-process sync or use POSIX primitives
     // TODO: need to add inter-process sync or use POSIX primitives
     xSemaphore->take_counter++;
     xSemaphore->take_counter++;
 
 
@@ -154,7 +181,15 @@ BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait)
 }
 }
 
 
 BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
 BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
-    if(xSemaphore == NULL) return false;
+    if(xSemaphore == NULL) return pdFALSE;
+
+    if (xSemaphore->type == SemaphoreTypeMutex) {
+        if (pthread_mutex_unlock(&xSemaphore->mutex) == 0) {
+            return pdTRUE;
+        } else {
+            return pdFALSE;
+        }
+    }
 
 
     // TODO: need to add inter-process sync or use POSIX primitives
     // TODO: need to add inter-process sync or use POSIX primitives
     xSemaphore->give_counter++;
     xSemaphore->give_counter++;