]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/commitdiff
Fixed the deadlock, now I have to implement this scheme everywhere.
authorCarlos Jenkins <carlos@jenkins.co.cr>
Mon, 10 Jun 2013 03:35:13 +0000 (05:35 +0200)
committerCarlos Jenkins <carlos@jenkins.co.cr>
Mon, 10 Jun 2013 03:35:13 +0000 (05:35 +0200)
apps/rpp-test-suite/src/ain.c

index 905601440a6fe46f6c8065629ca6f8716d187c9e..5b0b7f0d3fc4d14faecec873beb9be579ea1726a 100644 (file)
@@ -31,6 +31,9 @@
 #define FREQ_MILLIS     1000
 
 
+static boolean_t stop_tasks = FALSE;
+static uint8_t tasks_running = 0;
+
 /**
  * FreeRTOS Task that read analog inputs and prints them on the SCI.
  */
@@ -43,7 +46,7 @@ void ain_test_task(void* par)
     static const portTickType freq_ticks = FREQ_MILLIS / portTICK_RATE_MS;
     portTickType last_wake_time = xTaskGetTickCount();
 
-    while(TRUE) {
+    while(!stop_tasks) {
 
         // Update inputs
         rpp_ain_update();
@@ -73,6 +76,10 @@ void ain_test_task(void* par)
         // Wait until next step
         vTaskDelayUntil(&last_wake_time, freq_ticks);
     }
+
+    // Delete myself
+    tasks_running--;
+    vTaskDelete(NULL);
 }
 
 
@@ -83,13 +90,11 @@ void test_ain(void)
 {
     xTaskHandle test_task_handle;
 
-    rpp_sci_printf((const char*)"Try to create task.\r\n");
     portBASE_TYPE task_created = xTaskCreate(ain_test_task,
                     (const signed char*)"ain_test_task",
                     TEST_TASK_STACK, NULL, TEST_TASK_PRIORITY,
                     &test_task_handle
             );
-    rpp_sci_printf((const char*)"After try to create task.\r\n");
 
     if(task_created != pdPASS) {
 
@@ -101,10 +106,27 @@ void test_ain(void)
         return;
 
     }
+    tasks_running = 1;
 
     wait_for_quit();
-    vTaskDelete(test_task_handle);
-    vTaskDelay(4); // Allow the idle task to free memory
+
+    // Stop tasks
+    // Note: Not an easy task. If we preempt delete the task from this context
+    // using vTaskDelete and the task is holding a semaphore, like in the middle
+    // of a SCI send, printf, or similar, the semaphore will never be released
+    // and the application will deadlock in the next call to that function.
+    // As a general rule of thumb just allow vTaskDelete on the tasks themselves
+    // and implement a synchronization mecanism. Here we just wait for them to
+    // finish and set a flag because is simpler, a more correct approach will
+    // be to have a set of semaphores or a counting semaphore that all the tasks
+    // can share.
+    stop_tasks = TRUE;
+    while(tasks_running > 0) {
+        taskYIELD();
+    }
+    // Reset stop flag
+    stop_tasks = FALSE;
+    rpp_sci_printf((const char*)"\r\n");
 
     // Reset module
     // - Not required