[PATCH] libio: Add POSIX user environment to TCB

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Feb 14 18:38:56 UTC 2020


The IO library used a POSIX key to store an optional POSIX user
environment pointer.  This pulled in the POSIX keys support in every
application configuration.  Add a user environment pointer to the thread
control block (TCB) instead.  Applications which do not need the POSIX
user environment will just get an overhead of one pointer per thread.
---
 cpukit/include/rtems/confdefs.h            | 17 +-------
 cpukit/include/rtems/libio_.h              |  4 --
 cpukit/include/rtems/score/interr.h        |  2 +-
 cpukit/include/rtems/score/thread.h        |  7 ++++
 cpukit/include/rtems/sysinit.h             |  1 +
 cpukit/include/rtems/userenv.h             |  6 ++-
 cpukit/libcsupport/src/__usrenv.c          | 12 +++++-
 cpukit/libcsupport/src/libio_init.c        | 11 -----
 cpukit/libcsupport/src/privateenv.c        | 67 ++++++++++++++++++++----------
 cpukit/sapi/src/sysinitverbose.c           | 10 ++++-
 testsuites/psxtests/psxconfig01/init.c     |  2 +-
 testsuites/sptests/Makefile.am             |  9 ----
 testsuites/sptests/configure.ac            |  1 -
 testsuites/sptests/spfatal27/init.c        | 34 ---------------
 testsuites/sptests/spfatal27/spfatal27.doc | 23 ----------
 testsuites/sptests/spfatal27/spfatal27.scn |  3 --
 testsuites/sptests/spsysinit01/init.c      | 41 +++++++++++++++++-
 17 files changed, 121 insertions(+), 129 deletions(-)
 delete mode 100644 testsuites/sptests/spfatal27/init.c
 delete mode 100644 testsuites/sptests/spfatal27/spfatal27.doc
 delete mode 100644 testsuites/sptests/spfatal27/spfatal27.scn

diff --git a/cpukit/include/rtems/confdefs.h b/cpukit/include/rtems/confdefs.h
index 9b5549478c..bbbaa9d6d1 100644
--- a/cpukit/include/rtems/confdefs.h
+++ b/cpukit/include/rtems/confdefs.h
@@ -142,11 +142,6 @@ extern "C" {
   #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 3
 #endif
 
-/*
- * POSIX key count used by the IO library.
- */
-#define _CONFIGURE_LIBIO_POSIX_KEYS 1
-
 #ifdef CONFIGURE_INIT
   rtems_libio_t rtems_libio_iops[CONFIGURE_MAXIMUM_FILE_DESCRIPTORS];
 
@@ -2028,14 +2023,6 @@ struct _reent *__getreent(void)
      (CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_TASKS))
 #endif
 
-/*
- * This macro is calculated to specify the total number of
- * POSIX API keys required by the application and configured
- * system capabilities.
- */
-#define _CONFIGURE_POSIX_KEYS \
-  (CONFIGURE_MAXIMUM_POSIX_KEYS + _CONFIGURE_LIBIO_POSIX_KEYS)
-
 /**
  * This configuration parameter specifies the maximum number of
  * POSIX API threads.
@@ -2505,8 +2492,8 @@ struct _reent *__getreent(void)
       CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS;
   #endif
 
-  #if _CONFIGURE_POSIX_KEYS > 0
-    POSIX_KEYS_INFORMATION_DEFINE( _CONFIGURE_POSIX_KEYS );
+  #if CONFIGURE_MAXIMUM_POSIX_KEYS > 0
+    POSIX_KEYS_INFORMATION_DEFINE( CONFIGURE_MAXIMUM_POSIX_KEYS );
   #endif
 
   #if CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES > 0
diff --git a/cpukit/include/rtems/libio_.h b/cpukit/include/rtems/libio_.h
index cf80ea8075..2473bb5e5a 100644
--- a/cpukit/include/rtems/libio_.h
+++ b/cpukit/include/rtems/libio_.h
@@ -336,10 +336,6 @@ void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc );
  */
 #include <rtems/userenv.h>
 
-void rtems_libio_free_user_env( void *env );
-
-extern pthread_key_t rtems_current_user_env_key;
-
 void rtems_libio_lock( void );
 
 void rtems_libio_unlock( void );
diff --git a/cpukit/include/rtems/score/interr.h b/cpukit/include/rtems/score/interr.h
index e57c415eed..2f449deedb 100644
--- a/cpukit/include/rtems/score/interr.h
+++ b/cpukit/include/rtems/score/interr.h
@@ -197,7 +197,7 @@ typedef enum {
   INTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENT = 31,
   INTERNAL_ERROR_RTEMS_INIT_TASK_CREATE_FAILED = 32,
   INTERNAL_ERROR_POSIX_INIT_THREAD_CREATE_FAILED = 33,
-  INTERNAL_ERROR_LIBIO_USER_ENV_KEY_CREATE_FAILED = 34,
+  /* INTERNAL_ERROR_LIBIO_USER_ENV_KEY_CREATE_FAILED = 34, */
   /* INTERNAL_ERROR_LIBIO_SEM_CREATE_FAILED = 35, */
   INTERNAL_ERROR_LIBIO_STDOUT_FD_OPEN_FAILED = 36,
   INTERNAL_ERROR_LIBIO_STDERR_FD_OPEN_FAILED = 37,
diff --git a/cpukit/include/rtems/score/thread.h b/cpukit/include/rtems/score/thread.h
index 3e2e0638f8..2e7380f99a 100644
--- a/cpukit/include/rtems/score/thread.h
+++ b/cpukit/include/rtems/score/thread.h
@@ -43,6 +43,8 @@
 #include <rtems/score/processormask.h>
 #endif
 
+struct rtems_user_env_t;
+
 struct _pthread_cleanup_context;
 
 struct Per_CPU_Control;
@@ -858,6 +860,11 @@ struct _Thread_Control {
 
   Thread_Capture_control                Capture;
 
+  /**
+   * @brief Pointer to an optional thread-specific POSIX user environment.
+   */
+  struct rtems_user_env_t *user_environment;
+
   /**
    * @brief LIFO list of POSIX cleanup contexts.
    */
diff --git a/cpukit/include/rtems/sysinit.h b/cpukit/include/rtems/sysinit.h
index d181c42780..245da74f2c 100644
--- a/cpukit/include/rtems/sysinit.h
+++ b/cpukit/include/rtems/sysinit.h
@@ -68,6 +68,7 @@ extern "C" {
 #define RTEMS_SYSINIT_POSIX_CLEANUP              001c00
 #define RTEMS_SYSINIT_IDLE_THREADS               001d00
 #define RTEMS_SYSINIT_LIBIO                      001e00
+#define RTEMS_SYSINIT_USER_ENVIRONMENT           001e80
 #define RTEMS_SYSINIT_ROOT_FILESYSTEM            001f00
 #define RTEMS_SYSINIT_DRVMGR                     002000
 #define RTEMS_SYSINIT_MP_SERVER                  002100
diff --git a/cpukit/include/rtems/userenv.h b/cpukit/include/rtems/userenv.h
index 7d6ffb05a5..2b66ee0951 100644
--- a/cpukit/include/rtems/userenv.h
+++ b/cpukit/include/rtems/userenv.h
@@ -53,10 +53,12 @@ extern "C" {
   #endif
 #endif
 
+typedef struct rtems_user_env_t rtems_user_env_t;
+
 /**
  * @brief User environment.
  */
-typedef struct {
+struct rtems_user_env_t {
   /**
    * @brief The anchor directory for relative paths.
    */
@@ -111,7 +113,7 @@ typedef struct {
    * @brief The list of supplementary group IDs.
    */
   gid_t groups[NGROUPS];
-} rtems_user_env_t;
+};
 
 extern rtems_user_env_t rtems_global_user_env;
 
diff --git a/cpukit/libcsupport/src/__usrenv.c b/cpukit/libcsupport/src/__usrenv.c
index 611e0d7a92..922f7d696f 100644
--- a/cpukit/libcsupport/src/__usrenv.c
+++ b/cpukit/libcsupport/src/__usrenv.c
@@ -249,4 +249,14 @@ rtems_user_env_t rtems_global_user_env = {
   .umask = S_IWGRP | S_IWOTH
 };
 
-pthread_key_t rtems_current_user_env_key;
+rtems_user_env_t *rtems_current_user_env_get(void)
+{
+  Thread_Control *executing = _Thread_Get_executing();
+  rtems_user_env_t *env = executing->user_environment;
+
+  if (env == NULL) {
+    return &rtems_global_user_env;
+  }
+
+  return env;
+}
diff --git a/cpukit/libcsupport/src/libio_init.c b/cpukit/libcsupport/src/libio_init.c
index 5b951ef2be..5602a2021d 100644
--- a/cpukit/libcsupport/src/libio_init.c
+++ b/cpukit/libcsupport/src/libio_init.c
@@ -59,17 +59,6 @@ static void rtems_libio_init( void )
         iop->data1 = NULL;
         rtems_libio_iop_free_tail = &iop->data1;
     }
-
-  /*
-   *  Create the posix key for user environment.
-   */
-  eno = pthread_key_create(
-    &rtems_current_user_env_key,
-    rtems_libio_free_user_env
-  );
-  if (eno != 0) {
-    _Internal_error( INTERNAL_ERROR_LIBIO_USER_ENV_KEY_CREATE_FAILED );
-  }
 }
 
 RTEMS_SYSINIT_ITEM(
diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c
index d7f5090c33..cd0154ba38 100644
--- a/cpukit/libcsupport/src/privateenv.c
+++ b/cpukit/libcsupport/src/privateenv.c
@@ -24,23 +24,15 @@
 
 #include <rtems/libio_.h>
 #include <rtems/score/threadimpl.h>
+#include <rtems/score/userextimpl.h>
+#include <rtems/sysinit.h>
 
 /**
  *  Instantiate a private user environment for the calling thread.
  */
 
-rtems_user_env_t * rtems_current_user_env_get(void)
+static void rtems_libio_free_user_env(rtems_user_env_t *env)
 {
-  void *ptr = pthread_getspecific(rtems_current_user_env_key);
-  if (ptr == NULL) {
-    ptr = &rtems_global_user_env;
-  }
-  return (rtems_user_env_t *) ptr;
-}
-
-void rtems_libio_free_user_env(void *arg)
-{
-  rtems_user_env_t *env = arg;
   bool uses_global_env = env == &rtems_global_user_env;
 
   if (!uses_global_env) {
@@ -72,16 +64,9 @@ rtems_status_code rtems_libio_set_private_env(void)
         !rtems_filesystem_global_location_is_null(new_env->root_directory)
           && !rtems_filesystem_global_location_is_null(new_env->current_directory)
       ) {
-        int eno = pthread_setspecific(
-          rtems_current_user_env_key,
-          new_env
-        );
-
-        if (eno == 0) {
-          rtems_libio_free_user_env(old_env);
-        } else {
-          sc = RTEMS_TOO_MANY;
-        }
+        Thread_Control *executing = _Thread_Get_executing();
+
+        executing->user_environment = new_env;
       } else {
         sc = RTEMS_UNSATISFIED;
       }
@@ -107,10 +92,48 @@ void rtems_libio_use_global_env(void)
   if (uses_private_env) {
     Thread_Life_state life_state =
       _Thread_Set_life_protection(THREAD_LIFE_PROTECTED);
+    Thread_Control *executing;
 
     rtems_libio_free_user_env(env);
-    pthread_setspecific(rtems_current_user_env_key, NULL);
+    executing = _Thread_Get_executing();
+    executing->user_environment = NULL;
 
     _Thread_Set_life_protection(life_state);
   }
 }
+
+static void rtems_libio_env_thread_terminate(Thread_Control *the_thread)
+{
+  rtems_user_env_t *env = the_thread->user_environment;
+
+  if (env != NULL) {
+    rtems_libio_free_user_env(env);
+  }
+}
+
+static void rtems_libio_env_thread_restart(
+  Thread_Control *executing,
+  Thread_Control *the_thread
+)
+{
+  (void) executing;
+  rtems_libio_env_thread_terminate( the_thread );
+}
+
+static User_extensions_Control rtems_libio_env_extensions = {
+  .Callouts = {
+    .thread_restart = rtems_libio_env_thread_restart,
+    .thread_terminate = rtems_libio_env_thread_terminate
+  }
+};
+
+static void rtems_libio_env_init(void)
+{
+  _User_extensions_Add_API_set(&rtems_libio_env_extensions);
+}
+
+RTEMS_SYSINIT_ITEM(
+  rtems_libio_env_init,
+  RTEMS_SYSINIT_USER_ENVIRONMENT,
+  RTEMS_SYSINIT_ORDER_MIDDLE
+);
diff --git a/cpukit/sapi/src/sysinitverbose.c b/cpukit/sapi/src/sysinitverbose.c
index 7c8db2e5eb..50bc152bfd 100644
--- a/cpukit/sapi/src/sysinitverbose.c
+++ b/cpukit/sapi/src/sysinitverbose.c
@@ -86,6 +86,7 @@ SYSINIT_VERBOSE( POSIX_KEYS );
 SYSINIT_VERBOSE( POSIX_CLEANUP );
 SYSINIT_VERBOSE( IDLE_THREADS );
 SYSINIT_VERBOSE( LIBIO );
+SYSINIT_VERBOSE( USER_ENVIRONMENT );
 SYSINIT_VERBOSE( ROOT_FILESYSTEM );
 SYSINIT_VERBOSE( DRVMGR );
 SYSINIT_VERBOSE( MP_SERVER );
@@ -468,9 +469,16 @@ static void _Sysinit_Verbose_LIBIO( void )
   }
 }
 
+static void _Sysinit_Verbose_USER_ENVIRONMENT( void )
+{
+  if ( !SYSINIT_IS_ADJACENT( LIBIO, USER_ENVIRONMENT ) ) {
+    printk( "sysinit: USER_ENVIRONMENT: done\n" );
+  }
+}
+
 static void _Sysinit_Verbose_ROOT_FILESYSTEM( void )
 {
-  if ( !SYSINIT_IS_ADJACENT( LIBIO, ROOT_FILESYSTEM ) ) {
+  if ( !SYSINIT_IS_ADJACENT( USER_ENVIRONMENT, ROOT_FILESYSTEM ) ) {
     printk( "sysinit: ROOT_FILESYSTEM: done\n" );
   }
 }
diff --git a/testsuites/psxtests/psxconfig01/init.c b/testsuites/psxtests/psxconfig01/init.c
index c17c433ff1..2d0a0df497 100644
--- a/testsuites/psxtests/psxconfig01/init.c
+++ b/testsuites/psxtests/psxconfig01/init.c
@@ -301,7 +301,7 @@ static rtems_task Init(rtems_task_argument argument)
   rtems_test_assert(eno == EAGAIN);
   rtems_resource_snapshot_take(&snapshot);
   rtems_test_assert(
-    snapshot.active_posix_keys == _CONFIGURE_POSIX_KEYS
+    snapshot.active_posix_keys == CONFIGURE_MAXIMUM_POSIX_KEYS
   );
   rtems_test_assert(
     snapshot.active_posix_key_value_pairs == CONFIGURE_MAXIMUM_POSIX_KEYS
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 1b47cad4a9..071ce13216 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -1030,15 +1030,6 @@ spfatal26_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_spfatal26) \
 	$(support_includes)
 endif
 
-if TEST_spfatal27
-sp_tests += spfatal27
-sp_screens += spfatal27/spfatal27.scn
-sp_docs += spfatal27/spfatal27.doc
-spfatal27_SOURCES = spfatal27/init.c
-spfatal27_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_spfatal27) \
-	$(support_includes)
-endif
-
 if TEST_spfatal28
 sp_tests += spfatal28
 sp_screens += spfatal28/spfatal28.scn
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index e30f96d1c4..9476e3b0d7 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -152,7 +152,6 @@ RTEMS_TEST_CHECK([spfatal16])
 RTEMS_TEST_CHECK([spfatal24])
 RTEMS_TEST_CHECK([spfatal25])
 RTEMS_TEST_CHECK([spfatal26])
-RTEMS_TEST_CHECK([spfatal27])
 RTEMS_TEST_CHECK([spfatal28])
 RTEMS_TEST_CHECK([spfatal29])
 RTEMS_TEST_CHECK([spfatal30])
diff --git a/testsuites/sptests/spfatal27/init.c b/testsuites/sptests/spfatal27/init.c
deleted file mode 100644
index 7f2cf8668f..0000000000
--- a/testsuites/sptests/spfatal27/init.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "../spfatal_support/spfatal.h"
-
-/*
- * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
- *
- *  embedded brains GmbH
- *  Dornierstrasse 4
- *  82178 Puchheim
- *  Germany
- *  <rtems at embedded-brains.de>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#define FATAL_ERROR_TEST_NAME            "27"
-#define FATAL_ERROR_DESCRIPTION          "libio init no posix key left"
-#define FATAL_ERROR_EXPECTED_SOURCE      INTERNAL_ERROR_CORE
-#define FATAL_ERROR_EXPECTED_ERROR       INTERNAL_ERROR_LIBIO_USER_ENV_KEY_CREATE_FAILED
-
-#define CONFIGURE_MAXIMUM_POSIX_KEYS (-1)
-#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS (0)
-
-static void force_error(void)
-{
-  /* we should not reach this */
-}
-
-#include "../spfatal_support/spfatalimpl.h"
diff --git a/testsuites/sptests/spfatal27/spfatal27.doc b/testsuites/sptests/spfatal27/spfatal27.doc
deleted file mode 100644
index f8da1bfbc9..0000000000
--- a/testsuites/sptests/spfatal27/spfatal27.doc
+++ /dev/null
@@ -1,23 +0,0 @@
-#  Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
-#
-#   embedded brains GmbH
-#   Dornierstrasse 4
-#   82178 Puchheim
-#   Germany
-#   <rtems at embedded-brains.de>
-#
-#  The license and distribution terms for this file may be
-#  found in the file LICENSE in this distribution or at
-#  http://www.rtems.org/license/LICENSE.
-
-This file describes the directives and concepts tested by this test set.
-
-test set name:  spfatal27
-
-directives:
-
-  rtems_libio_init
-
-concepts:
-
-+ Force the fatal error when no POSIX key is left.
diff --git a/testsuites/sptests/spfatal27/spfatal27.scn b/testsuites/sptests/spfatal27/spfatal27.scn
deleted file mode 100644
index 41f6ae58bc..0000000000
--- a/testsuites/sptests/spfatal27/spfatal27.scn
+++ /dev/null
@@ -1,3 +0,0 @@
-*** BEGIN OF TEST FATAL 27 ***
-Fatal error (libio init no posix key left) hit
-*** END OF TEST FATAL 27 ***
diff --git a/testsuites/sptests/spsysinit01/init.c b/testsuites/sptests/spsysinit01/init.c
index 224eac468f..0aa9917feb 100644
--- a/testsuites/sptests/spsysinit01/init.c
+++ b/testsuites/sptests/spsysinit01/init.c
@@ -125,6 +125,8 @@ typedef enum {
   IDLE_THREADS_POST,
   LIBIO_PRE,
   LIBIO_POST,
+  USER_ENVIRONMENT_PRE,
+  USER_ENVIRONMENT_POST,
   ROOT_FILESYSTEM_PRE,
   ROOT_FILESYSTEM_POST,
   BSP_PRE_DRIVERS_PRE,
@@ -513,7 +515,7 @@ FIRST(RTEMS_SYSINIT_POSIX_KEYS)
 
 LAST(RTEMS_SYSINIT_POSIX_KEYS)
 {
-  assert(info_is_init(&_POSIX_Keys_Information, 2));
+  assert(info_is_init(&_POSIX_Keys_Information, 1));
   next_step(POSIX_KEYS_POST);
 }
 
@@ -541,6 +543,24 @@ LAST(RTEMS_SYSINIT_LIBIO)
   next_step(LIBIO_POST);
 }
 
+static size_t user_extensions_pre_user_env;
+
+FIRST(RTEMS_SYSINIT_USER_ENVIRONMENT)
+{
+  user_extensions_pre_user_env =
+    _Chain_Node_count_unprotected(&_User_extensions_List.Active);
+  next_step(USER_ENVIRONMENT_PRE);
+}
+
+LAST(RTEMS_SYSINIT_USER_ENVIRONMENT)
+{
+  assert(
+    user_extensions_pre_user_env + 1 ==
+      _Chain_Node_count_unprotected(&_User_extensions_List.Active)
+  );
+  next_step(USER_ENVIRONMENT_POST);
+}
+
 FIRST(RTEMS_SYSINIT_ROOT_FILESYSTEM)
 {
   struct stat st;
@@ -842,6 +862,18 @@ static void do_cleanup_push_pop(void)
   pthread_cleanup_pop(0);
 }
 
+static void do_posix_key_create(void)
+{
+  pthread_key_t key;
+  int eno;
+
+  eno = pthread_key_create(&key, NULL);
+  rtems_test_assert(eno == 0);
+
+  eno = pthread_key_delete(key);
+  rtems_test_assert(eno == 0);
+}
+
 static void do_posix_mq_open(void)
 {
   struct mq_attr attr;
@@ -925,6 +957,11 @@ static void check_config(void)
   rtems_test_assert(config->User_initialization_tasks_table != NULL);
 }
 
+static void do_use_global_user_env(void)
+{
+  rtems_libio_use_global_env(void)
+}
+
 static void Init(rtems_task_argument arg)
 {
   next_step(INIT_TASK);
@@ -939,10 +976,12 @@ static void Init(rtems_task_argument arg)
   do_task_create();
   do_timer_create();
   do_cleanup_push_pop();
+  do_posix_key_create();
   do_posix_mq_open();
   do_posix_sem_open();
   do_posix_shm_open();
   do_posix_timer_create();
+  do_use_global_user_env();
   check_config();
   TEST_END();
   exit(0);
-- 
2.16.4



More information about the devel mailing list