1    /* 
     2     * Copyright (c) 2011, 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     *  ======== Semaphore.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.knl;
    38    
    39    import xdc.rov.ViewInfo;
    40    
    41    import xdc.runtime.Diags;
    42    import xdc.runtime.Log;
    43    import xdc.runtime.Assert;
    44    
    45    import ti.sysbios.knl.Queue;
    46    import ti.sysbios.knl.Task;
    47    import ti.sysbios.knl.Clock;
    48    
    49    /*!
    50     *  ======== Semaphore ========
    51     *  Semaphore Manager.
    52     *
    53     *  The Semaphore manager makes available a set of functions that manipulate 
    54     *  semaphore objects. Semaphores can be used for task synchronization and 
    55     *  mutual exclusion.
    56     *
    57     *  Semaphores can be counting semaphores or binary semaphores. Counting 
    58     *  semaphores keep track of the number of times the semaphore has been posted 
    59     *  with post(). This is useful, for example, if you have a group of resources 
    60     *  that are shared between tasks. Such tasks might call pend() to see if a 
    61     *  resource is available before using one. 
    62     *
    63     *  Binary semaphores can have only two states: available (count = 1) and 
    64     *  unavailable (count = 0). They can be used to share a single resource 
    65     *  between 
    66     *  tasks. They can also be used for a basic signaling mechanism, where the 
    67     *  semaphore can be posted multiple times. Binary semaphores do not keep track 
    68     *  of the count; they simply track whether the semaphore has been posted 
    69     *  or not.
    70     *
    71     *  The Mailbox module uses a counting semaphore internally to manage the
    72     *  count of free (or full) mailbox elements. Another example of a counting
    73     *  semaphore is an ISR that might fill multiple buffers of data for
    74     *  consumption by a task. After filling each buffer, the ISR puts the buffer on
    75     *  a queue and calls post(). The task waiting for the data calls pend(), which
    76     *  simply decrements the semaphore count and returns or blocks if the count is
    77     *  0. The semaphore count thus tracks the number of full buffers available for
    78     *  the task. 
    79     *
    80     *  pend() is used to wait for a semaphore. The timeout parameter allows the 
    81     *  task to wait until a timeout, wait indefinitely, or not wait at all. The 
    82     *  return value is used to indicate if the semaphore was signaled successfully.
    83     *
    84     *  post() is used to signal a semaphore. If a task is waiting for the 
    85     *  semaphore, post() removes the task from the semaphore queue and puts it on 
    86     *  the ready queue. If no tasks are waiting, post() simply increments the 
    87     *  semaphore count and returns.  For a binary semaphore the count is always
    88     *  set to one.
    89     *
    90     *  @p(html)
    91     *  <h3> Calling Context </h3>
    92     *  <table border="1" cellpadding="3">
    93     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    94     *    </colgroup>
    95     *    
    96     *    <tr><th> Function               </th><th>  Hwi   </th><th>  Swi   </th>
    97     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    98     *    <!--                                                                  -->
    99     *    <tr><td> {@link #Params_init}   </td><td>   Y    </td><td>   Y    </td>
   100     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   101     *    <tr><td> {@link #construct}     </td><td>   N    </td><td>   N    </td>
   102     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> {@link #create}        </td><td>   N    </td><td>   N    </td>
   104     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   105     *    <tr><td> {@link #delete}        </td><td>   N    </td><td>   N    </td>
   106     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #destruct}      </td><td>   N    </td><td>   N    </td>
   108     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #getCount}      </td><td>   Y    </td><td>   Y    </td>
   110     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   111     *    <tr><td> {@link #pend}          </td><td>   N    </td><td>   N    </td>
   112     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   113     *    <tr><td> {@link #post}          </td><td>   Y    </td><td>   Y    </td>
   114     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   115     *    <tr><td> {@link #registerEvent} </td><td>   N    </td><td>   N    </td>
   116     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   117     *    <tr><td> {@link #reset}         </td><td>   N    </td><td>   N    </td>
   118     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   119     *    <tr><td colspan="6"> Definitions: <br />
   120     *       <ul>
   121     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   122     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   123     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   124     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   125     *           <ul>
   126     *             <li> In your module startup after this module is started 
   127     *    (e.g. Semaphore_Module_startupDone() returns TRUE). </li>
   128     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   129     *             <li> During main().</li>
   130     *             <li> During BIOS.startupFxns.</li>
   131     *           </ul>
   132     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   133     *           <ul>
   134     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   135     *             <li> In your module startup before this module is started 
   136     *    (e.g. Semaphore_Module_startupDone() returns FALSE).</li>
   137     *           </ul>
   138     *       </ul>
   139     *    </td></tr>
   140     *  
   141     *  </table>
   142     *  @p
   143     */
   144    
   145    @InstanceFinalize       /* to destruct queue */
   146    
   147    module Semaphore
   148    {
   149        /*! Types of semaphores. */
   150        enum Mode {
   151            Mode_COUNTING,  /*! Counting semaphore. */
   152            Mode_BINARY     /*! Binary Semaphore. */
   153        };
   154     
   155        metaonly struct BasicView {
   156            String          label;
   157            String          event;
   158            String          eventId;
   159            String          mode;
   160            Int             count;
   161            String          pendedTasks[];
   162        };
   163        
   164        @Facet
   165        metaonly config ViewInfo.Instance rovViewInfo = 
   166            ViewInfo.create({
   167                viewMap: [
   168                    ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}]
   169                ]
   170            });
   171        
   172        // -------- Module Parameters --------
   173    
   174        // Logs
   175    
   176        /*! Logged on calls to Semaphore_post() */
   177        config Log.Event LM_post = {
   178            mask: Diags.USER1 | Diags.USER2,
   179            msg: "LM_post: sem: 0x%x, count: %d"
   180        };
   181    
   182        /*! Logged on calls to Semaphore_pend() */
   183        config Log.Event LM_pend = {
   184            mask: Diags.USER1 | Diags.USER2,
   185            msg: "LM_pend: sem: 0x%x, count: %d, timeout: %d"
   186        };
   187    
   188        // Asserts
   189    
   190        /*! 
   191         *  Generated by {@link #create} if {@link #supportsEvents} is false
   192         *  and an {@link ti.sysbios.knl.Event} object is passed to 
   193         *  {@link #create}.
   194         */
   195        config Assert.Id A_noEvents = {
   196            msg: "A_noEvents: The Event.supportsEvents flag is disabled."
   197        };
   198    
   199        /*! 
   200         *  Generated by {@link #pend} if BIOS_EVENT_ACQUIRED timeout is used
   201         *  with a Semaphore that has not been configured with an Event object
   202         */
   203        config Assert.Id A_invTimeout = {
   204            msg: "A_invTimeout: Can't use BIOS_EVENT_ACQUIRED with this Semaphore."
   205        };
   206    
   207        /*!
   208         * Asserted when {@link #pend} is called with non-zero timeout from other
   209         * than a Task context.
   210         */
   211        config Assert.Id A_badContext = {
   212            msg: "A_badContext: bad calling context. Must be called from a Task."
   213        };
   214    
   215        /*! Support Semaphores with Events? Default is false. */
   216        config Bool supportsEvents = false;
   217    
   218    instance:
   219    
   220        /*!
   221         *  ======== create ========
   222         *  Create a Semaphore object.
   223         *
   224         *  This function creates a new Semaphore object which is initialized to
   225         *  count.
   226         *
   227         *  @param(count)                   initial semaphore count
   228         */
   229        @DirectCall
   230        create(Int count);
   231    
   232        /*!
   233         *  ======== event ========
   234         *  event if using Events. Default is null.
   235         *
   236         *  If event is non-null:
   237         * 
   238         *  Event_post(sem->event, sem->eventId) will be invoked when 
   239         *  Semaphore_post() is called.
   240         *
   241         *  Event_pend(sem->event, 0, sem->eventId, timeout) will be 
   242         *  invoked when Semaphore_pend() is called.
   243         */
   244        config Event.Handle event = null;
   245    
   246        /*!
   247         *  ======== eventId ========
   248         *  eventId if using Events. Default is 1.
   249         */
   250        config UInt eventId = 1;
   251    
   252        /*! 
   253         *  ======== mode ========
   254         *  Semaphore mode. Default is COUNTING.
   255         *
   256         *  When mode is BINARY , the semaphore has only two states, available
   257         *  and unavailable. When mode is COUNTING, the semaphore keeps track of
   258         *  number of times a semaphore is posted.
   259         */
   260        config Mode mode = Mode_COUNTING;
   261    
   262        /*!
   263         *  ======== getCount ========
   264         *  Get current semaphore count.
   265         *
   266         *  This function returns the current value of the semaphore specified by
   267         *  the handle.
   268         *
   269         *  @b(returns)             current semaphore count
   270         */
   271        @DirectCall
   272        Int getCount();
   273    
   274        /*!
   275         *  ======== pend ========
   276         *  Wait for a semaphore.
   277         *
   278         *  If the semaphore count is greater than zero (available), this function
   279         *  decrements the count and returns TRUE. If the semaphore count is zero
   280         *  (unavailable), this function suspends execution of the current task 
   281         *  until post() is called or the timeout expires.
   282         *
   283         *  A timeout value of 
   284         *  {@link ti.sysbios.BIOS#WAIT_FOREVER, BIOS_WAIT_FOREVER} causes 
   285         *  the task to wait indefinitely for its semaphore to be posted. 
   286         *
   287         *  A timeout value of {@link ti.sysbios.BIOS#NO_WAIT, BIOS_NO_WAIT} 
   288         *  causes Semaphore_pend to return immediately. 
   289         *
   290         *  @param(timeout)                 return after this many system time units
   291         *
   292         *  @b(returns)                     TRUE if successful, FALSE if timeout
   293         */
   294        @DirectCall
   295        Bool pend(UInt timeout);
   296    
   297        /*!
   298         *  ======== post ========
   299         *  Signal a semaphore.
   300         *
   301         *  Readies the first task waiting for the semaphore. If no task is
   302         *  waiting, This function simply increments the semaphore count and returns
   303         *  In case of binary semaphore the count has a maximum value of one.
   304         */
   305        @DirectCall
   306        Void post();
   307    
   308        /*!
   309         *  ======== registerEvent ========
   310         *  Register an Event Object with a semaphore.
   311         *
   312         *  Ordinarily, an Event object and eventId are configured at 
   313         *  Semaphore create time.
   314         *
   315         *  This API is provided so that Semaphore-using middleware
   316         *  can support implicit Event posting without having to be
   317         *  retrofitted.
   318         *
   319         *  After the Event object and eventId are registered with the
   320         *  Semaphore:
   321    
   322         *  Event_post(event, eventId) will be invoked when 
   323         *  Semaphore_post(sem) is called.
   324         *
   325         *  Event_pend(event, eventId, 0, timeout) will be invoked when 
   326         *  Semaphore_pend(sem, timeout) is called.
   327         *
   328         *  @param(event)                     Ptr to Event Object
   329         *  @param(eventId)                   Event ID
   330         *
   331         */
   332        @DirectCall
   333        Void registerEvent(Event.Handle event, UInt eventId);
   334    
   335        /*!
   336         *  ======== reset ========
   337         *  Reset semaphore count.
   338         *
   339         *  Resets the semaphore count to count.
   340         *  No task switch occurs when calling SEM_reset.
   341         *
   342         *  @a(constraints)
   343         *  count must be greater than or equal to 0.
   344         *
   345         *  No tasks should be waiting on the semaphore when 
   346         *  Semaphore_reset is called.
   347         *
   348         *  Semaphore_reset cannot be called by a Hwi or a Swi.
   349         *
   350         *  @param(count)                   semaphore count
   351         *
   352         */
   353        @DirectCall
   354        Void reset(Int count);
   355    
   356    internal:
   357    
   358        /* 
   359         * Event module function pointers. Used to decouple
   360         * Semaphore from Event when supportsEvents is false
   361         */
   362        config Void (*eventPost)(Event.Handle, UInt);
   363    
   364        config Void (*eventSync)(Event.Handle, UInt, UInt);
   365    
   366        /*!
   367         *  ======== pendTimeout ========
   368         *  This function is the clock event handler for pend
   369         */
   370        Void pendTimeout(UArg arg);
   371    
   372        /* pendQ Element PendStates */
   373        enum PendState {
   374            PendState_TIMEOUT = 0,          /* Clock timeout */
   375            PendState_POSTED = 1,           /* posted by post */
   376            PendState_CLOCK_WAIT = 2,       /* in Clock queue */
   377            PendState_WAIT_FOREVER = 3      /* not in Clock queue */
   378        };
   379        
   380        /* Semaphore pendQ Element */
   381        struct PendElem {
   382            Task.PendElem           tpElem;
   383            PendState               pendState;
   384        };
   385    
   386        struct Instance_State {
   387            Event.Handle            event;
   388            UInt                    eventId;
   389            Mode                    mode;   /* binary or counting */
   390            volatile UInt16         count;  /* curr semaphore count */
   391            Queue.Object            pendQ;  /* queue of PendElems */
   392        };
   393    }
   394    /*
   395     *  @(#) ti.sysbios.knl; 2, 0, 0, 0,451; 2-2-2011 15:07:14; /db/vtree/library/trees/avala/avala-o27x/src/ xlibrary
   396    
   397     */
   398