]> granicus.if.org Git - esp-idf/commitdiff
newlib: Fix UT adjtime
authorKonstantin Kondrashov <konstantin@espressif.com>
Wed, 7 Nov 2018 11:47:51 +0000 (19:47 +0800)
committerAngus Gratton <gus@projectgus.com>
Mon, 26 Nov 2018 04:55:17 +0000 (15:55 +1100)
components/newlib/test/test_time.c

index aab7ff53feabf61f3f1824d47e877989c750dcf4..4a55b303e735d031e85a655a5c51c32b5ce1fe11 100644 (file)
@@ -11,7 +11,7 @@
 #include "sdkconfig.h"
 #include "soc/rtc.h"
 #include "esp_clk.h"
-
+#include "esp_system.h"
 
 #if portNUM_PROCESSORS == 2
 
@@ -133,8 +133,6 @@ TEST_CASE("test adjtime function", "[newlib]")
 }
 
 static volatile bool exit_flag;
-static bool adjtime_test_result;
-static bool gettimeofday_test_result;
 
 static void adjtimeTask2(void *pvParameters)
 {
@@ -205,26 +203,51 @@ TEST_CASE("test for no interlocking adjtime, gettimeofday and settimeofday funct
     }
 }
 
+#ifndef CONFIG_FREERTOS_UNICORE
+static xSemaphoreHandle gettime_start_sema;
+static xSemaphoreHandle adjtime_continue_sema;
 static void adjtimeTask(void *pvParameters)
 {
-    struct timeval delta = {.tv_sec = 0, .tv_usec = 0};
-    struct timeval outdelta = {.tv_sec = 0, .tv_usec = 0};
+    const uint64_t adjtime_us = 2000000000; // 2000 sec
+    struct timeval delta = {.tv_sec = adjtime_us / 1000000, .tv_usec = 900000};
+    struct timeval outdelta;
+    struct timeval tv_time;
+    int shift = 1;
+    int cycle = 0;
 
     // although exit flag is set in another task, checking (exit_flag == false) is safe
     while (exit_flag == false) {
-        delta.tv_sec = 1000;
-        delta.tv_usec = 0;
-        if(adjtime(&delta, &outdelta) != 0) {
-            adjtime_test_result = true;
-            exit_flag = true;
+        gettimeofday(&tv_time, NULL);
+        uint64_t start_time_us = (uint64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec;
+
+        ++cycle;
+        if (shift > 3000) {
+            shift = 1;
         }
-        delta.tv_sec = 0;
-        delta.tv_usec = 1000;
-        if(adjtime(&delta, &outdelta) != 0) {
-            adjtime_test_result = true;
-            exit_flag = true;
+        int i_shift = shift++;
+
+        xSemaphoreGive(gettime_start_sema);
+        while (--i_shift) {
+            __asm__ __volatile__ ("nop": : : "memory");
+        };
+        adjtime(&delta, &outdelta);
+        xSemaphoreTake(adjtime_continue_sema, portMAX_DELAY);
+
+        gettimeofday(&tv_time, NULL);
+        uint64_t end_time_us = (uint64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec;
+
+        if (!(start_time_us < end_time_us) || (end_time_us - start_time_us > adjtime_us)
+                || (end_time_us - start_time_us > 300) || (end_time_us - start_time_us < 30)) {
+            printf("ERROR: start_time_us %lld usec.\n", start_time_us);
+            printf("ERROR: end_time_us   %lld usec.\n", end_time_us);
+            printf("ERROR: dt            %lld usec.\n", end_time_us - start_time_us);
+            printf("ERROR: cycle         %d\n", cycle);
+            printf("ERROR: shift         %d\n", shift);
+            TEST_FAIL_MESSAGE("The time is corrupted due to the lack of locks for the adjtime function.");
         }
     }
+    xSemaphoreGive(adjtime_continue_sema);
+    xSemaphoreGive(gettime_start_sema);
     vTaskDelete(NULL);
 }
 
@@ -232,52 +255,48 @@ static void gettimeofdayTask(void *pvParameters)
 {
     struct timeval tv_time;
 
-    gettimeofday(&tv_time, NULL);
-    uint64_t time_old = (uint64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec;
     // although exit flag is set in another task, checking (exit_flag == false) is safe
     while (exit_flag == false) {
+        xSemaphoreTake(gettime_start_sema, portMAX_DELAY);
         gettimeofday(&tv_time, NULL);
-        uint64_t time   = (uint64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec;
-        if(((time - time_old) > 1000000LL) || (time_old > time)) {
-            printf("ERROR: time jumped for %lld/1000 seconds. No locks. Need to use locks.\n", (time - time_old)/1000000LL);
-            gettimeofday_test_result = true;
-            exit_flag = true;
-        }
-        time_old = time;
+        xSemaphoreGive(adjtime_continue_sema);
     }
+    xSemaphoreGive(adjtime_continue_sema);
+    xSemaphoreGive(gettime_start_sema);
     vTaskDelete(NULL);
 }
 
 TEST_CASE("test for thread safety adjtime and gettimeofday functions", "[newlib]")
 {
-    TaskHandle_t th[4];
     exit_flag = false;
-    adjtime_test_result = false;
-    gettimeofday_test_result = false;
 
-    struct timeval tv_time = { .tv_sec = 1520000000, .tv_usec = 900000 };
-    TEST_ASSERT_EQUAL(settimeofday(&tv_time, NULL), 0);
+    struct timeval tv_time = { .tv_sec = 1520000000, .tv_usec = 0 };
+    TEST_ASSERT_EQUAL(0, settimeofday(&tv_time, NULL));
+
+    gettime_start_sema = xSemaphoreCreateBinary();
+    adjtime_continue_sema = xSemaphoreCreateBinary();
 
-#ifndef CONFIG_FREERTOS_UNICORE
     printf("CPU0 and CPU1. Tasks run: 1 - adjtimeTask, 2 - gettimeofdayTask\n");
-    xTaskCreatePinnedToCore(adjtimeTask, "adjtimeTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[0], 0);
-    xTaskCreatePinnedToCore(gettimeofdayTask, "gettimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[1], 1);
-    xTaskCreatePinnedToCore(gettimeofdayTask, "gettimeofdayTask2", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[2], 0);
-#else
-    printf("Only one CPU. Tasks run: 1 - adjtimeTask, 2 - gettimeofdayTask\n");
-    xTaskCreate(adjtimeTask, "adjtimeTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[0]);
-    xTaskCreate(gettimeofdayTask, "gettimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[1]);
-#endif
+    xTaskCreatePinnedToCore(adjtimeTask, "adjtimeTask", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
+    xTaskCreatePinnedToCore(gettimeofdayTask, "gettimeofdayTask", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
 
-    printf("start wait for 5 seconds\n");
-    vTaskDelay(5000 / portTICK_PERIOD_MS);
+    printf("start wait for 10 seconds\n");
+    vTaskDelay(10000 / portTICK_PERIOD_MS);
 
     // set exit flag to let thread exit
     exit_flag = true;
-    vTaskDelay(20 / portTICK_PERIOD_MS);
+    vTaskDelay(2000 / portTICK_PERIOD_MS);
 
-    TEST_ASSERT(adjtime_test_result == false && gettimeofday_test_result == false);
+    if (!xSemaphoreTake(gettime_start_sema, 1000 / portTICK_PERIOD_MS)) {
+        TEST_FAIL_MESSAGE("gettime_start_semaphore not released by test task");
+    }
+    if (!xSemaphoreTake(adjtime_continue_sema, 1000 / portTICK_PERIOD_MS)) {
+        TEST_FAIL_MESSAGE("adjtime_continue_semaphore not released by test task");
+    }
+    vSemaphoreDelete(gettime_start_sema);
+    vSemaphoreDelete(adjtime_continue_sema);
 }
+#endif
 
 #if defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC ) || defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 )
 #define WITH_RTC 1