pkarashchenko commented on a change in pull request #5498:
URL: https://github.com/apache/incubator-nuttx/pull/5498#discussion_r807698825



##########
File path: sched/task/task_tls_alloc.c
##########
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * sched/task/task_tls_alloc.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <errno.h>
+
+#include <nuttx/tls.h>
+#include <nuttx/semaphore.h>
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if CONFIG_TLS_TASK_NELEM > 0
+
+static int g_tlsset = 0;
+static sem_t g_tlssem = SEM_INITIALIZER(1);
+static tls_dtor_t g_tlsdtor[CONFIG_TLS_TASK_NELEM];
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int task_tls_alloc(tls_dtor_t dtor)
+{
+  int ret;
+  int candidate;
+
+  ret = nxsem_wait(&g_tlssem);
+
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = -EAGAIN;
+
+  for (candidate = 0; candidate < CONFIG_TLS_TASK_NELEM; candidate++)
+    {
+      int mask = 1 << candidate;
+      if ((g_tlsset & mask) == 0)
+        {
+          g_tlsset |= mask;
+          g_tlsdtor[candidate] = dtor;
+          ret = candidate;
+          break;
+        }
+    }
+
+  nxsem_post(&g_tlssem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: task_tls_destruct
+ *
+ * Description:
+ *   Destruct all TLS data element associated with allocated key
+ *
+ * Input Parameters:
+ *    None
+ *
+ * Returned Value:
+ *   A set of allocated TLS index
+ *
+ ****************************************************************************/
+
+void task_tls_destruct(void)

Review comment:
       I would like to get some more explanation about operation of this API. 
Maybe I'm missing something and that brings my concerns up.
   For example `CONFIG_TLS_TASK_NELEM` is configured to `3`. Then each task 
(`struct task_info_s`) will be equipped with additional `3` elements of 
`uintptr_t` while globally we can have only `CONFIG_TLS_TASK_NELEM` number of 
destructors (`static tls_dtor_t g_tlsdtor[CONFIG_TLS_TASK_NELEM];`). So if I'm 
having `10` tasks the `3 * 10 * sizeof(uintptr_t)` will be additionally 
allocated for tasks and `3 * sizeof(tls_dtor_t)` for destructors. For example 
`task_A` call `task_tls_alloc()` one time and `task_B` call `task_tls_alloc()` 
two times. Then `task_A` exits and `task_tls_destruct` is called. The loop will 
iterate `3` times and globally `if ((g_tlsset & mask) != 0)` will always hit a 
`true` condition (one time for `task_A` and two times for `task_B`) and 
`dtor((void *)elem);` will be called `3` times passing 2 times `(void *)0` to 
`dtor()`. So the questions are next:
   1. Is it expected that `task_tls_destruct()` will call TLS destructors for 
other tasks?
   2. If yes, then should we have a prerequisite that `dtor()` should check for 
`NULL` inside that call?
   3. Is it expected that after `task_tls_destruct()` is called the while all 
`CONFIG_TLS_TASK_NELEM` are allocated the new `task_tls_alloc()` will always 
fail because `g_tlsset` never resets bits?
   4. What it `task_tls_destruct()` is called in the middle of 
`task_tls_alloc()`, for example after `g_tlsdtor[candidate] = dtor;` and before 
`ret = candidate;`? Will the `dtor` be ready to accept `NULL` (that actually 
comes back to 2)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to