1    /*
     2     * Copyright (c) 2013-2018, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    /*
    33     *  ======== MultithreadSupport.xdc ========
    34     */
    35    
    36    package ti.sysbios.rts.iar;
    37    
    38    import xdc.runtime.Error;
    39    import xdc.runtime.Assert;
    40    
    41    import ti.sysbios.knl.Task;
    42    import ti.sysbios.knl.Semaphore;
    43    
    44    /*!
    45     *  ======== MultithreadSupport ========
    46     *  Provide the kernel support needed for IAR re-entrant C run-time
    47     *
    48     *  This multi-thread support module uses hook functions, hook context,
    49     *  and an overloaded implementation of the C library's lock and thread
    50     *  local storage access functions to make C run-time library calls
    51     *  re-entrant.
    52     *
    53     *  This module is used only with the IAR compiler.
    54     *
    55     *  To enable multi-thread support, load this module in your application
    56     *  configuration script.
    57     *
    58     *  @p(code)
    59     *  xdc.useModule('ti.sysbios.rts.iar.MultithreadSupport');
    60     *  @p
    61     *
    62     *  If your application is using a module which requires multi-thread
    63     *  support, then that module is responsible for loading this module.
    64     *  For example, the `ti.posix.tirtos.Settings` module will load this
    65     *  module. In this case, it is not necessary to load it explicitly.
    66     *
    67     *  When this module is used, it will contribute the IAR linker option
    68     *  `--threaded_lib` to the linker command.
    69     *
    70     *  When using the IAR Embedded Workbench IDE, if you enable thread support
    71     *  in your project settings, you must also include this module in your
    72     *  configuration (unless it is already used as described above). There is
    73     *  no mechanism for the IAR IDE to communicate the project selections to
    74     *  this module.
    75     *
    76     *  On memory limited devices, it is possible to disable the re-entrant
    77     *  support in order to minimize the memory footprint. See
    78     *  {@link #metaenableMultithreadSupport enableMultithreadSupport} for
    79     *  details.
    80     *
    81     *  @a(note)
    82     *  Calling C run-time functions from SWI or HWI threads is not supported
    83     *  and will generate an exception if  multi-thread support is enabled.
    84     */
    85    
    86    @Template ("./MultithreadSupport.xdt")
    87    
    88    module MultithreadSupport
    89    {
    90        /*!
    91         *  ======== enableMultithreadSupport ========
    92         *  Disable the multi-thread support feature
    93         *
    94         *  When necessary, it is possible to disable the re-entrant support in
    95         *  order to minimize the memory footprint. For example, if using POSIX
    96         *  support on a memory limited device, you may disable re-entrant support
    97         *  by adding the following to your application configuration script.
    98         *
    99         *  @p(code)
   100         *  var MultithreadSupport = xdc.useModule('ti.sysbios.rts.iar.MultithreadSupport');
   101         *  MultithreadSupport.enableMultithreadSupport = false;
   102         *  @p
   103         *
   104         *  @a(note)
   105         *  When multi-thread support is disabled, errno will be a global
   106         *  symbol. If multiple threads are referencing errno, it will not
   107         *  be thread-safe.
   108         */
   109        config Bool enableMultithreadSupport = true;
   110    
   111        /*!
   112         *  ======== A_badThreadType ========
   113         *  Asserted in MultithreadSupport_perThreadAccess()
   114         *
   115         *  @_nodoc
   116         */
   117        config Assert.Id A_badThreadType = {
   118            msg: "A_badThreadType: Cannot call a C runtime library API from a Hwi or Swi thread."
   119        };
   120    
   121        /*!
   122         *  ======== A_badLockRelease ========
   123         *  Asserted in MultithreadSupport_releaseLock()
   124         *
   125         *  @_nodoc
   126         */
   127        config Assert.Id A_badLockRelease = {
   128            msg: "A_badLockRelease: Trying to release a lock not owned by this thread."
   129        };
   130    
   131    internal:   /* not for client use */
   132    
   133        /*
   134         *  ======== perThreadAccess ========
   135         *  Returns a pointer the symbol in the current task's TLS memory
   136         *
   137         *  Calculates the symbol address based on the input symbol pointer
   138         *  in main task's TLS memory and returns the address to the symbol
   139         *  in the current task's TLS memory.
   140         *
   141         *  @param(symbp) Pointer to symbol in the main task's TLS memory.
   142         *
   143         */
   144        Void *perThreadAccess(Void *symbp);
   145    
   146        /*
   147         *  ======== getTlsPtr ========
   148         *  Returns a pointer to the current task's TLS memory
   149         */
   150        void *getTlsPtr();
   151    
   152        /*
   153         *  ======== getTlsAddr ========
   154         *  Return address of thread-local storage buffer
   155         *
   156         *  This function is generated. It's implementation differs depending
   157         *  if SYS/BIOS is in ROM or not.
   158         */
   159        void *getTlsAddr();
   160    
   161        /*
   162         *  ======== initLock ========
   163         *  Initializes a system lock
   164         *
   165         *  Creates a system lock and assigns it to the pointer passed as input.
   166         *
   167         *  @param(ptr) Pointer to a lock struct pointer.
   168         *
   169         */
   170        Void initLock(Void **ptr);
   171    
   172        /*
   173         *  ======== destroyLock ========
   174         *  Destroy a system lock
   175         *
   176         *  Deletes the semaphore in the lock and frees the lock.
   177         *
   178         *  @param(ptr) Pointer to a lock struct pointer.
   179         *
   180         */
   181        Void destroyLock(Void **ptr);
   182    
   183        /*
   184         *  ======== acquireLock ========
   185         *  Acquire a system lock
   186         *
   187         *  Blocks the task if lock is not available. Supports nested calls.
   188         *
   189         *  @param(ptr) Pointer to a lock struct pointer.
   190         *
   191         */
   192        Void acquireLock(Void **ptr);
   193    
   194        /*
   195         *  ======== releaseLock ========
   196         *  Release a system lock
   197         *
   198         *  Releases the lock to other waiting task if any. Supports nested calls.
   199         *
   200         *  @param(ptr) Pointer to a lock struct pointer.
   201         *
   202         */
   203        Void releaseLock(Void **ptr);
   204    
   205        /*
   206         *  ======== taskCreateHook ========
   207         *  Create task hook function
   208         *
   209         *  It is used to create and initialize all task's hook context.
   210         *
   211         *  @param(task) Handle of the Task to initialize.
   212         *  @param(eb) Error block.
   213         *
   214         */
   215        Void taskCreateHook(Task.Handle task, Error.Block *eb);
   216    
   217        /*
   218         *  ======== taskDeleteHook ========
   219         *  Delete hook function used to remove the task's hook context
   220         *
   221         *  @param(task) Handle of the Task to delete.
   222         *
   223         */
   224        Void taskDeleteHook(Task.Handle task);
   225    
   226        /*
   227         *  ======== taskRegHook ========
   228         *  Registration function for the module's hook
   229         *
   230         *  @param(id) The id of the hook for use in load.
   231         *
   232         */
   233        Void taskRegHook(Int id);
   234    
   235        /* -------- Internal Module Types -------- */
   236    
   237        struct Module_State {
   238            Int taskHId;    /* Task Hook Context Id for this module */
   239            Ptr deletedTaskTLSPtr;
   240            Task.Handle curTaskHandle;
   241            Semaphore.Handle lock;
   242        };
   243    }