1    /* --COPYRIGHT--,ESD
     2     *  Copyright (c) 2008 Texas Instruments. All rights reserved. 
     3     *  This program and the accompanying materials are made available under the 
     4     *  terms of the Eclipse Public License v1.0 and Eclipse Distribution License
     5     *  v. 1.0 which accompanies this distribution. The Eclipse Public License is
     6     *  available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse
     7     *  Distribution License is available at 
     8     *  http://www.eclipse.org/org/documents/edl-v10.php.
     9     *
    10     *  Contributors:
    11     *      Texas Instruments - initial implementation
    12     * --/COPYRIGHT--*/
    13    /*
    14     *  ======== Thread.xdc ========
    15     */
    16     
    17    import xdc.runtime.Error;
    18    import xdc.runtime.Assert;
    19    import xdc.runtime.knl.IThreadSupport;
    20    
    21    /*!
    22     *  ======== Thread ========
    23     *  Thread services. [EXPERIMENTAL]
    24     *
    25     *  This module manages threads through a proxy which inherits from
    26     *  IThreadSupport interface. It has a module wide config parameter 
    27     *  {@link #Proxy} which needs to be bound to an OS specific delegate before 
    28     *  this module can be used.
    29     *  
    30     *  Here is an example showing how the proxy is bound to a BIOS 6.x specific 
    31     *  delegate.
    32     *
    33     *  var Thread = xdc.useModule('xdc.runtime.knl.Thread');
    34     *  Thread.Proxy = xdc.useModule('ti.sysbios.xdcruntime.ThreadSupport');
    35     *
    36     *  Typically a package containing the delegates has a Settings module that 
    37     *  will bind all {@link xdc.runtime.knl} proxies. The following
    38     *  example sets up all the xdc.runtime.knl proxies.
    39     *  
    40     *  xdc.useModule('ti.sysbios.xdcruntime.Settings');
    41     *  
    42     */
    43    
    44    @InstanceInitError      /* because initialization can fail */
    45    @InstanceFinalize       /* have to Thread_Proxy_delete(sem) on delete */
    46    
    47    module Thread
    48    {
    49        /*! Thread priorities which are mapped to OS specific value by Proxy */
    50        enum Priority {
    51            Priority_INVALID,
    52            Priority_LOWEST,
    53            Priority_BELOW_NORMAL,
    54            Priority_NORMAL,
    55            Priority_ABOVE_NORMAL,
    56            Priority_HIGHEST
    57        };
    58        
    59        /*! Invalid OS priority value */
    60        const Int INVALID_OS_PRIORITY = 0;
    61    
    62        /*! Status returned by {@link #getPri} when an error occurs */
    63        const Int GETPRI_FAILED = -2;
    64    
    65        /*! Status returned by {@link #compareOsPriorities} when an error occurs */
    66        enum CompStatus {
    67            CompStatus_ERROR = -2,
    68            CompStatus_LOWER = -1,
    69            CompStatus_EQUAL = 0,
    70            CompStatus_HIGHER = 1
    71        };
    72    
    73        /*! Proxy that needs to be bound to an OS specific delegate. */
    74        proxy Proxy inherits IThreadSupport;
    75    
    76        /*! Typedef for thread function */
    77        typedef Void (*RunFxn)(IArg);
    78    
    79        /*! Struct to hold thread statistics from {@link #stat} */
    80        struct Stat {
    81            SizeT stackSize;
    82            SizeT stackUsed;
    83        }
    84    
    85        /*! Assert when  timeout passed to {@link #sleep} is zero */
    86        config Assert.Id A_zeroTimeout= {
    87            msg: "A_zeroTimeout: Timeout value annot be zero"
    88        };
    89    
    90        /*! Default thread stack size. */
    91        config SizeT defaultStackSize = 0;
    92    
    93        /*!
    94         *  ======== self ========
    95         *  Return the currently executing thread's handle
    96         *
    97         *  @param(eb)      Pointer to Error.Block
    98         *  @a(returns)     Returns a handle to the currently executing thread.  
    99         *                  If the current thread is the main thread, this function 
   100         *                  returns `NULL`. NULL is also returned in case of error.
   101         */
   102        Handle self(Error.Block *eb);
   103    
   104        /*!
   105         *  ======== start ========
   106         *  Start threads running
   107         *
   108         *  This function can be used to start all statically created threads,
   109         *  and all threads created dynamically before this function is called.
   110         *  Any thread created after this function is called, starts automatically.
   111         *  (i.e., there is no need to call Thread_start() more than once).
   112         *
   113         *  @param(eb)      Pointer to Error.Block
   114         *  @a(returns)     true for success; false for error
   115         */
   116        Bool start(Error.Block *eb);
   117    
   118        /*!
   119         *  ======== yield ========
   120         *  Yield the currently scheduled thread
   121         *
   122         *  @param(eb)      Pointer to Error.Block
   123         *  @a(returns)     true for success; false for error
   124         */
   125        Bool yield(Error.Block *eb);
   126    
   127        /*!
   128         *  ======== compareOsPriorities ========
   129         *  Compare two os specific priority values and find out which one 
   130         *  represents a higher priority.
   131         *
   132         *  @p(blist)
   133         *  -{@link #CompStatus_ERROR} if an error occured
   134         *  -{@link #CompStatus_LOWER} if p1 is lower than p2
   135         *  -{@link #CompStatus_EQUAL} if p1=p2
   136         *  -{@link #CompStatus_HIGHER} if p1 is higher than p2
   137         *    details.
   138         *  @p
   139         *
   140         *  @param(p1)      priority one
   141         *  @param(p2)      priority two
   142         *  @param(eb)      Pointer to Error.Block
   143         *  @a(returns)     refer to description above
   144         */
   145        Int compareOsPriorities(Int p1, Int p2, Error.Block *eb);
   146        
   147        /*!
   148         *  ======== sleep ========
   149         *  Sleep for given number of microseconds
   150         *
   151         *  This function is gauranteed to sleep for at least as long as the 
   152         *  timeout value but the actual sleep time may be longer. NOTE:
   153         *  The timeout value cannot be zero.
   154         *
   155         *  @param(timeout)     timeout in microseconds
   156         *  @param(eb)          Pointer to Error.Block
   157         *  @a(returns)         true for success; false for error
   158         */
   159        Bool sleep(UInt timeout, Error.Block *eb);
   160    
   161    instance:
   162    
   163        /*! Thread function argument. Default is 0. */
   164        config IArg arg = 0;
   165    
   166        /*!
   167         *  ======== priority ========
   168         *  Specify the new thread's priority
   169         *
   170         *  Thread defines several constants which allows applications to select
   171         *  a priority in an OS independent way: Priority_LOWEST, 
   172         *  Priority_BELOW_NORMAL, Priority_NORMAL, Priority_ABOVE_NORMAL and 
   173         *  Priority_HIGHEST. These values get mapped to OS specific priorities 
   174         *  by the OS specific delegate.
   175         */
   176        config Priority priority = Priority_NORMAL;
   177    
   178        /*!
   179         *  ======== osPriority ========
   180         *  OS specific thread priority
   181         *
   182         *  Used to specify an OS specific value for priority. If set this value
   183         *  takes precedence over {@link #priority}.
   184         */
   185        config Int osPriority = INVALID_OS_PRIORITY;
   186    
   187        /*!
   188         *  ======== stackSize ========
   189         *  Thread stack size
   190         *
   191         *  The default value of 0 means that `{@link #defaultStackSize}` is used.
   192         */
   193        config SizeT stackSize = 0;
   194        
   195        /*! 
   196         *  ======== tls ========
   197         *  Thread local storage.
   198         *
   199         *  User data associated with a thread. Must persist for the life of
   200         *  the thread.
   201         */
   202        config Ptr tls = null;
   203    
   204        /*!
   205         *  ======== create ========
   206         *  Create a Thread object
   207         *
   208         *  This function spawns a new thread calling the function fxn.
   209         *
   210         *  @param(fxn)     function for new thread to begin execution
   211         */
   212        create(RunFxn fxn);
   213    
   214        /*!
   215         *  ======== join ========
   216         *  Block calling thread until given thread terminates.
   217         *
   218         *  Use this functions to ensure that a thread has terminated. It is OK to
   219         *  call this function on a thread that has already terminated.
   220         *
   221         *  @param(eb)      Pointer to Error.Block
   222         *  @a(returns)     true for success; false for error
   223         */
   224        Bool join(Error.Block *eb);
   225    
   226        /*!
   227         *  ======== getPriority ========
   228         *  Obtain a thread's priority.
   229         *
   230         *  For OSes that support dynamic priority boosting, this function
   231         *  retrieves the base priority of the thread.
   232         *
   233         *  @param(eb)      Pointer to Error.Block
   234         *  @a(returns)     thread priority in case of success; PRIORITY_INVALID in
   235         *                  case of error;
   236         */
   237        Priority getPriority(Error.Block *eb);
   238    
   239        /*!
   240         *  ======== setPriority ========
   241         *  Set a thread's priority.
   242         *
   243         *  For OSes that support dynamic priority boosting, this function
   244         *  changes the base priority of the thread.
   245         *
   246         *  @param(newPri)  new thread priority
   247         *  @param(eb)      Pointer to Error.Block
   248         *  @a(returns)     true for success; false for error
   249         */
   250        Bool setPriority(Priority newPri, Error.Block *eb);
   251    
   252        /*!
   253         *  ======== getOsPriority ========
   254         *  Obtain a thread's OS specific priority.
   255         *
   256         *  For OSes that support dynamic priority boosting, the value returned 
   257         *  is the base priority of the thread.
   258         *
   259         *  @param(eb)      Pointer to Error.Block
   260         *  @a(returns)     thread priority in case of success; GETPRI_FAILED in
   261         *                  case of error;
   262         */
   263        Int getOsPriority(Error.Block *eb);
   264    
   265        /*!
   266         *  ======== setOsPriority ========
   267         *  Set a thread's priority.
   268         *
   269         *  This API sets the base priority of the thread on OSes that
   270         *  support dynamic priority boosting
   271         *
   272         *  @param(newPri)  new thread priority
   273         *  @param(eb)      Pointer to Error.Block
   274         *  @a(returns)     true for success; false for error
   275         */
   276        Bool setOsPriority(Int newPri, Error.Block *eb);
   277    
   278        /*!
   279         *  ======== getOsHandle ========
   280         *  Get the OS thread handle
   281         *
   282         *   @a(returns)     OS thread handle
   283         */
   284        Ptr getOsHandle();
   285    
   286        /*!
   287         *  ======== getTls ========
   288         *  Obtain a thread's local storage.
   289         *
   290         *   @a(returns)     null when tls has not been set.
   291         */
   292        Ptr getTls();
   293    
   294        /*!
   295         *  ======== setTls ========
   296         *  Change a thread's local storage.
   297         *
   298         *  @param(tls)     tls
   299         */
   300        Void setTls(Ptr tls);
   301    
   302        /*!
   303         *  ======== stat ========
   304         *  Get thread statistics
   305         *
   306         *  @param(buf)     Pointer to Stat
   307         *  @param(eb)      Pointer to Error.Block
   308         *  @a(returns)     true for success; false for failure
   309         */
   310        Bool stat(Stat* buf, Error.Block *eb);
   311    
   312    internal:
   313    
   314        struct Instance_State {
   315            Thread.Proxy.Handle proxyHandle; /*! handle for real implementation */
   316            Ptr                 tls;         /*! store tls parameter */
   317        }
   318    }
   319    
   320    /*
   321     *! Revision History
   322     *! ================
   323     *! 17-Apr-2009 nitya    Review updates
   324     */
   325    /*
   326     *  @(#) xdc.runtime.knl; 1, 0, 0,23; 7-29-2009 14:53:49; /db/ztree/library/trees/xdc-t56x/src/packages/
   327     */
   328