]> granicus.if.org Git - esp-idf/commitdiff
pthread: handle statically initialized mutexes
authorIvan Grokhotkov <ivan@espressif.com>
Fri, 1 Sep 2017 04:31:04 +0000 (12:31 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Wed, 6 Sep 2017 02:30:23 +0000 (10:30 +0800)
components/pthread/pthread.c

index f2409671adca07869df0b936ff72b9952cfade55..2cf66942588392b5663f30b7bee0cc10f9c0f94a 100644 (file)
@@ -42,6 +42,7 @@ typedef struct {
 
 static SemaphoreHandle_t s_once_mux = NULL;
 static SemaphoreHandle_t s_threads_mux = NULL;
+static portMUX_TYPE s_mutex_init_lock = portMUX_INITIALIZER_UNLOCKED;
 
 static List_t s_threads_list;
 
@@ -356,7 +357,8 @@ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
 
     TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
     // do not take mutex if OS is not running yet
-    if (!cur_task || xSemaphoreTake(s_once_mux, portMAX_DELAY) == pdTRUE)
+    if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED ||
+            !cur_task || xSemaphoreTake(s_once_mux, portMAX_DELAY) == pdTRUE)
     {
         if (!once_control->init_executed) {
             ESP_LOGV(TAG, "%s: call init_routine %p", __FUNCTION__, once_control);
@@ -472,12 +474,28 @@ static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickT
     return 0;
 }
 
+static int pthread_mutex_init_if_static(pthread_mutex_t *mutex) {
+    int res = 0;
+    if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) {
+        portENTER_CRITICAL(&s_mutex_init_lock);
+        if ((intptr_t) *mutex == PTHREAD_MUTEX_INITIALIZER) {
+            res = pthread_mutex_init(mutex, NULL);
+        }
+        portEXIT_CRITICAL(&s_mutex_init_lock);
+    }
+    return res;
+}
+
 int IRAM_ATTR pthread_mutex_lock(pthread_mutex_t *mutex)
 {
     if (!mutex) {
         errno = EINVAL;
         return EINVAL;
     }
+    int res = pthread_mutex_init_if_static(mutex);
+    if (res != 0) {
+        return res;
+    }
     return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, portMAX_DELAY);
 }
 
@@ -487,6 +505,10 @@ int IRAM_ATTR pthread_mutex_trylock(pthread_mutex_t *mutex)
         errno = EINVAL;
         return EINVAL;
     }
+    int res = pthread_mutex_init_if_static(mutex);
+    if (res != 0) {
+        return res;
+    }
     return pthread_mutex_lock_internal((esp_pthread_mutex_t *)*mutex, 0);
 }