This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/TMS320C6678: OpenMP can not work with POSIX Threads

Part Number: TMS320C6678
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Dear all:

when I follow the user guide(downloads.ti.com/.../index.html) to create OpenMP project , I found when I selected "Enable support for OpenMP 3.0" ,it will automaticlly selected "Muli-threading is assumed"(Build->Advanced options ->Advanced Optimizations). The problem is that when "Muli-threading is assumed" is selected , I can't use POSIX Threads. The project can build correctly, however it will die in _c_int00() when it run. Can you tell me the solution to the problem.

Thanks and best regards.

  • I've notified the sw team. Their feedback will be posted here.

    Best Regards,
    Yordan
  • Hi qq,

    Can you upload your CCS project to illustrate the problem? Any reason you have to mix the pthreads and OpenMP?

    Regards,
    Garrett
  • Hi Garrett:
    Because I transplanted a Open source project which use mang pthreads to implement multithreading ,when i transplanted to TMS320C6678 i want to use OpenMP, but i don't want to modify the original code.
    Regards.
  • Hi qq,


    The OpenMP runtime is not built on top of posix threads.  In fact, the default configuration of the OpenMP runtime does not start BIOS running.  You have to modify the boot code to start up BIOS and then run the master thread and the worker threads each on their own cores inside a BIOS task or a pthread.  For example see the following file:

    /*
     * Copyright (c) 2013, Texas Instruments Incorporated
     * http://www.ti.com
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include <c6x.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ti/runtime/openmp/src/tomp_init.h>
    #include <ti/runtime/openmp/src/tomp_config.h>
    
    /* xdctools header files */
    #include <xdc/std.h>
    #include <xdc/runtime/Diags.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/Log.h>
    #include <xdc/runtime/System.h>
    
    /* package header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/posix/pthread.h>
    
    extern far int main(int argc, char *argv[]);
    
    static void entryFuncBios(void);
    
    
    /**
     * RTSC mode: Custom _args_main to switch SP (if specified) and call main
     *
     * Replaces _args_main from C6000 RTS in RTSC mode. Cannot call main via a 
     * XDC Startup.lastFxns hook because any entry in lastFxns after the OpenMP
     * runtime entry calling main call will NOT be executed. 
     */
    #if 0
    void _args_main(void)
    {
        tomp_OmpStartCommon(&entryFuncBios);
    }
    #else
    void _args_main_task(void)
    {
       tomp_OmpStartCommon(&entryFuncBios);
    }
    void *_args_main_pthread(void* arg)
    {
       tomp_OmpStartCommon(&entryFuncBios);
    
       return NULL;
    }
    #define DEFAULT_STACK_SIZE 0x8000
    
    void _args_main(void)
    {
    #if 0
       Error_Block     eb;
       Task_Params     taskParams;
    
       /* must initialize the error block before using it */
       Error_init(&eb);
    
       /* create main thread (interrupts not enabled in main on BIOS) */
       Task_Params_init(&taskParams);
       taskParams.instance->name = "_args_main_task";
       taskParams.priority = 5;
       Task_create(_args_main_task, &taskParams, &eb);
    
       if (Error_check(&eb)) {
          System_abort("main: failed to create application startup thread");
       }
    
       /* start scheduler, this never returns */
       BIOS_start();
    #else
       int max_priority, err;
       pthread_attr_t attr;
       struct sched_param param;
       pthread_t thread;
    
       max_priority = sched_get_priority_max();
       max_priority--;
       pthread_attr_init(&attr);
       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
       pthread_attr_setstacksize(&attr, DEFAULT_STACK_SIZE);
       memset(&param, 0, sizeof(param));
       param.sched_priority = max_priority;
       pthread_attr_setschedparam(&attr, &param);
    
       if ((err = pthread_create(&thread, &attr, _args_main_pthread, (void*)NULL)))
       {
          abort();
       }
    
       /* start scheduler, this never returns */
       BIOS_start();
    #endif
    
       /* should never get here */
       return;
    }
    #endif
    
    typedef struct { int argc; char *argv[1]; } ARGS;
    extern ARGS __c_args__;
    #define NO_C_ARGS   ((unsigned int)-1)
    
    void entryFuncBios(void)
    {
        if (DNUM == TOMP_MASTER_CORE_IDX)
        {
    #pragma diag_suppress 1107,173
            register ARGS *pargs = (ARGS*)_symval(&__c_args__);
    #pragma diag_default 1107,173
            register int    argc = 0;
            register char **argv = 0;
       
    
            if (_symval(&__c_args__) != NO_C_ARGS)
            { argc = pargs->argc; argv = pargs->argv; }
    
            main(argc, argv);
    
            // Terminate dispatch loops on worker cores and free up hardware
            // resources.
            __TI_omp_terminate();
    
            exit(0);
        }
        else
        {
            // Never returns. Worker cores exit when they get an exit event
            while(1) 
                tomp_dispatch_once();
        }
    }
    
    
    

    In addition, each DSP Core is running it's own version of BIOS.  It is not SMP across all the cores.  The OpenMP runtime manages the synchronization of the threads across the different cores.  So, don't expect the pthread API to work across threads running on different cores.

    When you use the --openmp switch the compiler by default includes the multi-threaded version of the RTS library.

    When I enabled posix support in the config file via Posix = xdc.useModule('ti.sysbios.posix.Settings') I saw the same crash you were reporting.  There was a bug in one of the RTS files. I've attached a fixed version here:

    /****************************************************************************/
    /*  _mutex.c v#####                                                         */
    /*  Copyright (c) 2012@%%%% Texas Instruments Incorporated                  */
    /****************************************************************************/
    #include <_mutex.h>
    #include <_pthread.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "file.h"
    
    /****************************************************************************/
    /* To enable use of recursive resource mutexes, the library builder must    */
    /* define the "__TI_RECURSIVE_RESOURCE_MUTEXES" compile-time symbol.        */
    /****************************************************************************/
    #if defined(__TI_RECURSIVE_RESOURCE_MUTEXES)
    
    
    /****************************************************************************/
    /* Recursive Mutex Implementation                                           */
    /*                                                                          */
    /* This file contains an implementation of recursvie mutexes. This          */
    /* implementation is used by the public interface for locking and unlocking */
    /* accesses to RTS-owned global resources (__TI_resource_lock() and         */
    /* __TI_resource_unlock() below). The implementation uses a subset of the   */
    /* POSIX Threads API that supplies the underlying OS-provided mutex         */
    /* functionality.                                                           */
    /****************************************************************************/
    
    /****************************************************************************/
    /* Recursive Mutex Object Specification                                     */
    /****************************************************************************/
    typedef struct {
       unsigned int    count;	/* recursive nesting level                  */
       pthread_t       owner;	/* unique thread ID of mutex owner          */
       pthread_mutex_t mutex;	/* handle to underlying mutex (OS-provided) */
    } recursive_mutex_t;
    
    /****************************************************************************/
    /* Statically Allocated Array of Recursive Mutexes                          */
    /****************************************************************************/
    #define TI_NLOCKS	(__TI_LOCK_MAX + _NFILE)
    _DATA_ACCESS static recursive_mutex_t ti_locks[TI_NLOCKS];
    _DATA_ACCESS static size_t            ti_lockno = 0;
    
    /****************************************************************************/
    /* resource_mutexes[]                                                       */
    /*                                                                          */
    /* Array of unique opaque mutex handles for each global shared resource     */
    /* that the TI RTS source owns. These mutexes are used to prevent possible  */
    /* race conditions that may arise if two or more threads attempt to access  */
    /* a shared resource at the same time.                                      */
    /****************************************************************************/
    static void *resource_mutexes[__TI_LOCK_MAX];
    
    /****************************************************************************/
    /* file_mutexes[]                                                           */
    /*                                                                          */
    /* Array of unique opaque mutex handles for each file that is managed by    */
    /* the RTS. These mutexes are used to prevent possible race conditions that */
    /* may arise if two or more threads attempt to access a file stream at the  */
    /* same time. file_mutexes[i] is the mutex for file _ftable[i].             */
    /****************************************************************************/
    static void *file_mutexes[_NFILE];
    
    /****************************************************************************/
    /* Recursive Mutex Implementation - Function Prototypes                     */
    /****************************************************************************/
    static void create_resource_mutexes(void);
    static void destroy_resource_mutexes(void);
    
    static void init_mutexes(void);
    static void delete_mutexes(void);
    
    static void mutex_init(void **mtx);
    static void mutex_destroy(void **mtx);
    static void mutex_lock(void *mtx);
    static void mutex_unlock(void *mtx);
    
    /****************************************************************************/
    /* Control Variable - used by TI RTS as argument to pthread_once() function */
    /* to ensure that mutex creation / initialization only happens once during  */
    /* the execution of an application.                                         */
    /****************************************************************************/
    static pthread_once_t ti_mutex_control = PTHREAD_ONCE_INIT;
    
    /****************************************************************************/
    /* Resource Mutex - Public Interface                                        */
    /*                                                                          */
    /* __TI_resource_lock() and __TI_resource_unlock() are the only two         */
    /* functions used by the RTS to protect access to RTS-owned global shared   */
    /* objects. The only other part of the public interface is the list of      */
    /* available resource IDs.                                                  */
    /****************************************************************************/
    
    /****************************************************************************/
    /* __TI_resource_lock()                                                     */
    /*                                                                          */
    /* Acquire a lock on a global shared resource using the unique mutex handle */
    /* stored in the resource_mutexes[] array. The array is indexed by the      */
    /* resource_type provided.                                                  */
    /****************************************************************************/
    _CODE_ACCESS void __TI_resource_lock(int resource_type)
    {
       /*-----------------------------------------------------------------------*/
       /* Do we have a legal resource ID?                                       */
       /*-----------------------------------------------------------------------*/
       if (resource_type >= __TI_LOCK_MAX) abort();
    
       /*-----------------------------------------------------------------------*/
       /* The "once" function guarantees that the mutex initialization          */
       /* function, init_mutexes(), will only be called once during the life of */
       /* the application.                                                      */
       /*-----------------------------------------------------------------------*/
       pthread_once(&ti_mutex_control, init_mutexes);
       
       /*-----------------------------------------------------------------------*/
       /* Get the handle of the recursive mutex associated with the specified   */
       /* resource ID, and request a lock on it.                                */
       /*-----------------------------------------------------------------------*/
       if (resource_mutexes[resource_type]) 
          mutex_lock(resource_mutexes[resource_type]);
    }
    
    /****************************************************************************/
    /* __TI_resource_unlock()                                                   */
    /*                                                                          */
    /* Release a lock on a global shared resource using the unique mutex handle */
    /* stored in the resource_mutexes[] array. The array is indexed by the      */
    /* resourc_type provided.                                                   */
    /****************************************************************************/
    _CODE_ACCESS void __TI_resource_unlock(int resource_type)
    {
       /*-----------------------------------------------------------------------*/
       /* Do we have a legal resource ID?                                       */
       /*-----------------------------------------------------------------------*/
       if (resource_type >= __TI_LOCK_MAX) abort();
    
       /*-----------------------------------------------------------------------*/
       /* Get the handle of the recursive mutex associated with the specified   */
       /* resource ID, and release the lock on it.                              */
       /*-----------------------------------------------------------------------*/
       if (resource_mutexes[resource_type]) 
          mutex_unlock(resource_mutexes[resource_type]);
    }
    
    /****************************************************************************/
    /* __TI_file_lock()                                                         */
    /*                                                                          */
    /* Acquire a lock on a file using the unique mutex handle stored in the     */
    /* file_mutexes[] array. The array is indexed by FILE's index in _ftable.   */
    /****************************************************************************/
    _CODE_ACCESS void __TI_file_lock(FILE *_fp)
    {
       int idx = _fp - _ftable; 
       /*-----------------------------------------------------------------------*/
       /* The "once" function guarantees that the mutex initialization          */
       /* function, init_mutexes(), will only be called once during the life of */
       /* the application.                                                      */
       /*-----------------------------------------------------------------------*/
       pthread_once(&ti_mutex_control, init_mutexes);
    
       /*-----------------------------------------------------------------------*/
       /* Get the handle of the recursive mutex associated with the specified   */
       /* file stream and request a lock on it. mutex_lock() will only be       */
       /* called on valid file streams.                                         */
       /*-----------------------------------------------------------------------*/
       if (_fp && idx < _NFILE && idx >= 0 && file_mutexes[idx])
          mutex_lock(file_mutexes[idx]);
    }
    
    /****************************************************************************/
    /* __TI_file_unlock()                                                       */
    /*                                                                          */
    /* Release a lock on a file using the unique mutex handle stored in the     */
    /* file_mutexes[] array. The array is indexed by FILE's index in _ftable.   */
    /****************************************************************************/
    _CODE_ACCESS void __TI_file_unlock(FILE *_fp)
    {
       int idx = _fp - _ftable; 
       /*-----------------------------------------------------------------------*/
       /* Get the handle of the recursive mutex associated with the specified   */
       /* file stream and release the lock on it. mutex_unlock() will only be   */
       /* called on valid file streams.                                         */
       /*-----------------------------------------------------------------------*/
       if (_fp && idx < _NFILE && idx >= 0 && file_mutexes[idx])
          mutex_unlock(file_mutexes[idx]);
    }
    
    /****************************************************************************/
    /* create_resource_mutexes()                                                */
    /*                                                                          */
    /* Create a mutex for each global shared resource that the TI RTS source    */
    /* owns. These are global objects that are used to manage things like heap  */
    /* memory or device I/O. Accesses to these global shared objects must be    */
    /* protected to avoid race conditions in a multi-threaded environment.      */
    /* For a full list of the resource types, see __TI_LOCK_* in _mutex.h.      */
    /****************************************************************************/
    static void create_resource_mutexes()
    {
       int i;
       for (i = 0; i < __TI_LOCK_MAX; i++)
          mutex_init(&resource_mutexes[i]);
       
       for (i = 0; i < _NFILE; i++)
          mutex_init(&file_mutexes[i]);
    }
    
    /****************************************************************************/
    /* delete_resource_mutexes()                                                */
    /*                                                                          */
    /* Delete all resource mutexes that were created by the TI RTS to guard     */
    /* accesses to global shared objects.                                       */
    /****************************************************************************/
    static void destroy_resource_mutexes()
    {
       int i;
       for (i = 0; i < __TI_LOCK_MAX; i++)
          if (resource_mutexes[i])
          {
             // here
             mutex_destroy(&resource_mutexes[i]);
             resource_mutexes[i] = NULL;
          }
       
       for (i = 0; i < _NFILE; i++)
          if (file_mutexes[i])
          {
             mutex_destroy(&file_mutexes[i]);
             file_mutexes[i] = NULL;
          }
    }
    
    
    /****************************************************************************/
    /* Recursive Mutex Implementation                                           */
    /****************************************************************************/
    
    /****************************************************************************/
    /* Creation and Deletion of Mutexes (Initialization / Termination).         */
    /****************************************************************************/
    
    /****************************************************************************/
    /* Global function pointer to delete_mutexes() setup if/when resource       */
    /* mutexes are initialized.                                                 */
    /****************************************************************************/
    extern _DATA_ACCESS void (*__TI_delete_mutexes_ptr)(void);
    
    /****************************************************************************/
    /* init_mutexes()                                                           */
    /*                                                                          */
    /* Create all mutexes that are needed by the TI RTS to protect accesses to  */
    /* shared global resources.                                                 */ 
    /*                                                                          */
    /* This function may only be called once during the life of an application. */
    /* To enforce this constraint, we use the pthread_once() function interface */
    /* to call it (from __TI_resource_lock()). The first time pthread_once() is */
    /* called on behalf of init_mutexes(), the pthread_once() function will     */
    /* actually call init_mutexes() to set up the resource_mutexes[] array.     */
    /* Each subsequent call to pthread_once() will observe that the init        */
    /* function has already been executed and return without calling it again.  */
    /****************************************************************************/
    static void init_mutexes()
    {
       /*-----------------------------------------------------------------------*/
       /* Create a mutex for each global shared resource that the TI RTS source */
       /* owns.                                                                 */
       /*-----------------------------------------------------------------------*/
       create_resource_mutexes();
    
       /*-----------------------------------------------------------------------*/
       /* We maintain a function pointer in exit.c as part of the resource      */
       /* mutexes implementation. It allows delete_mutexes() to be called       */
       /* indirectly from exit() only if the resource mutexes infrastructure    */
       /* has been initialized.                                                 */
       /*-----------------------------------------------------------------------*/
       /* Note that the recursive resource mutex API is intended for use ONLY   */
       /* within the RTS.                                                       */
       /*-----------------------------------------------------------------------*/
       __TI_delete_mutexes_ptr = delete_mutexes;
    }
    
    /****************************************************************************/
    /* delete_mutexes()                                                         */
    /*                                                                          */
    /* Delete all mutexes that were created by the TI RTS to protect accesses   */
    /* to shared global resources.                                              */
    /****************************************************************************/
    static void delete_mutexes()
    {
       /*-----------------------------------------------------------------------*/
       /* Delete any resource mutex that was created by the TI RTS.             */
       /*-----------------------------------------------------------------------*/
       destroy_resource_mutexes();
    }
    
    /****************************************************************************/
    /* mutex_init()                                                             */
    /*                                                                          */
    /* Initialize a mutex structure with a default owner thread ID, and get a   */
    /* handle for the underlying OS-provided mutex.                             */
    /****************************************************************************/
    static void mutex_init(void **mtx)
    {
       recursive_mutex_t *mp;
    
       if (ti_lockno < TI_NLOCKS)
          mp = *(recursive_mutex_t **)mtx = &ti_locks[ti_lockno++];
       else
          abort();
    
       mp->count = 0;
       mp->owner = 0;
       pthread_mutex_init(&mp->mutex, NULL);
    }
    
    /****************************************************************************/
    /* mutex_destroy()                                                          */
    /*                                                                          */
    /* Destroy the underlying mutex associated with this mutex.                 */
    /****************************************************************************/
    static void mutex_destroy(void **mtx)
    {
       recursive_mutex_t *mp = *(recursive_mutex_t **)mtx;
       pthread_mutex_destroy(&mp->mutex);
    }
    
    /****************************************************************************/
    /* mutex_lock()                                                             */
    /*                                                                          */
    /* Request to lock a recursive mutex via pthread_mutex_lock(). If noone is  */
    /* currently using the lock or the current thread is not the owner of the   */
    /* mutex, then we'll use pthread_mutex_lock() to acquire a lock on the      */
    /* underlying OS-provided mutex. The call to pthread_mutex_lock() will      */
    /* block until the lock is acquired.                                        */
    /*                                                                          */
    /* If the current thread already owns this mutex, then we simply bump the   */
    /* use count to keep track of the nesting level of this lock request.       */
    /****************************************************************************/
    static void mutex_lock(void *mtx)
    {
       pthread_t cur_thread_id = pthread_self();
       recursive_mutex_t *mp = (recursive_mutex_t *)mtx;
    
       if (!mp) return;
    
       /*-----------------------------------------------------------------------*/
       /* If lock is not being used or the lock request is being made on behalf */
       /* of a thread that is not the current owner of the lock, then we will   */
       /* use pthread_mutex_lock() to acquire the underlying OS-provided lock.  */
       /*-----------------------------------------------------------------------*/
       /* An OS-provided lock function underlies the pthread_mutex_lock() and   */
       /* will block until the requested resource lock is acquired. A thread    */
       /* that newly acquires a lock on a resource becomes the owner of the     */
       /* lock.                                                                 */
       /*-----------------------------------------------------------------------*/
       if ((mp->count == 0) || !pthread_equal(mp->owner, cur_thread_id))
       {
          pthread_mutex_lock(&mp->mutex);
          mp->owner = cur_thread_id;
       }
    
       ++mp->count;
    }
    
    /****************************************************************************/
    /* mutex_unlock()                                                           */
    /*                                                                          */
    /* Request to release a lock on a mutex. Assuming that the request is       */
    /* coming from the current owner of the mutex, we decrement the use count,  */
    /* which indicates the nesting level of this unlock request, and if it hits */
    /* zero (top-level lock/unlock) we use pthread_mutex_unlock() to release    */
    /* the lock on the underlying OS-provided mutex.                            */
    /****************************************************************************/
    static void mutex_unlock(void *mtx)
    {
       pthread_t cur_thread_id = pthread_self();
       recursive_mutex_t *mp = (recursive_mutex_t *)mtx;
    
       /*-----------------------------------------------------------------------*/
       /* If request to unlock a mutex comes from a different thread than the   */
       /* thread that currently owns the mutex, then we have some invalid       */
       /* nesting of critical sections somewhere in the RTS source. Panic!      */
       /*-----------------------------------------------------------------------*/
       if (!mp || (mp->count && !pthread_equal(mp->owner, cur_thread_id)))
          abort();
    
       /*-----------------------------------------------------------------------*/
       /* Decrement the recursive mutex's count to zero before releasing the    */
       /* lock on the underlying OS-provided mutex.                             */
       /*-----------------------------------------------------------------------*/
       if (--mp->count == 0) pthread_mutex_unlock(&mp->mutex);
    }
    
    #endif /* defined(__TI_RECURSIVE_RESOURCE_MUTEXES) */
    
    

    You need to modify the linker command file (or rebuild the RTS library with this new file) to place the .far section from this file in L2SRAM.

        .localfar :
        {
            "*rts*.lib" (.far)
            "*rts*.lib" (.fardata)
            "*_mutex.*" (.far)
            "*_mutex.*" (.fardata)
            "ti.drv.qmss*.ae66" (.far:local)
            "omp_config_pe66.oe66" (.far)
            "omp_config_pe66.oe66" (.fardata)

        } > L2SRAM

    In addition there was an issue with the OpenMP runtime calling getenv before args_main() is called (it would occur outside of a pthread).  You can work around that by disabling the getenv() routine:

    /*****************************************************************************/
    /*  GETENV.C v#####                                                          */
    /*  Copyright (c) 2012@%%%% Texas Instruments Incorporated                   */
    /*****************************************************************************/
    #include <stdlib.h> 
    #include <_tls.h>
    
    extern _CODE_ACCESS char *HOSTgetenv(const char *_string, char *pout);
    
    #if defined(REDUCE_GETENV_BUFSIZE)
    #define GETENV_VALUE_BUFSIZE 128
    #else
    #define GETENV_VALUE_BUFSIZE 200
    #endif
    
    /****************************************************************************/
    /* Each thread maintains its own copy of getenv_out so that overlapping     */
    /* calls from different threads will not overwrite each other.              */
    /****************************************************************************/
    // __TI_TLS_ARR_DEF(static, char, getenv_out, GETENV_VALUE_BUFSIZE);
    
    /****************************************************************************/
    /* GETENV()  -  Get the environment value for the passed variable name      */
    /****************************************************************************/
    _CODE_ACCESS char *getenv(const char *env_var_name)
    {
       // return HOSTgetenv(env_var_name, __TI_TLS_ARR(getenv_out));
       return NULL;
    }
    
    

    I will submit bug reports for these problems.  I hope this information can get your project working.

    Best regards, Eric

  • Thank you very much!

    I seriously read your explanation, but I still do not know how to fix this bug. Following your suggestions, I replace the _mutex.c/getenv.c file in compiler and then rebuild the RTS library . Then replace args_main_rtsc.c file in OpenMP. When I add " var Settings = xdc.useModule('ti.sysbios.posix.Settings'); " in omp_config.cfg file ,it also can not work. Is that where i did woring?
  • Thank you very much!

    I seriously read your explanation, but I still do not know how to fix this bug. Following your suggestions, I replace the _mutex.c/getenv.c file in compiler and then rebuild the RTS library . Then replace args_main_rtsc.c file in OpenMP. When I add " var Settings = xdc.useModule('ti.sysbios.posix.Settings'); " in omp_config.cfg file ,it also can not work. Is that where i did woring?