• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  ************************************************************************
18  * @file         M4OSA_Semaphore.c
19  * @brief        Semaphore for Windows
20  * @note         This file implements functions to manipulate semaphore
21  ************************************************************************
22 */
23 
24 
25 
26 #include "M4OSA_Debug.h"
27 #include "M4OSA_Types.h"
28 #include "M4OSA_Error.h"
29 #include "M4OSA_Memory.h"
30 #include "M4OSA_Semaphore.h"
31 
32 #include <semaphore.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <time.h>
38 
39 
40 /* Context for the semaphore */
41 typedef struct {
42    M4OSA_UInt32   coreID;     /* semaphore context identifiant */
43    sem_t          semaphore;  /* semaphore */
44 } M4OSA_SemaphoreContext;
45 
46 
47 
48 
49 /**
50  ************************************************************************
51  * @brief      This method creates a new semaphore with the "initialCounter"
52  *             value.
53  * @note       This function creates and allocates a unique context. It's the
54  *             OSAL real time responsibility for managing its context. It must
55  *             be freed by the M4OSA_semaphoreClose function. The context
56  *             parameter will be sent back to any OSAL core semaphore functions
57  *             to allow retrieving data associated to the opened semaphore.
58  * @param      context:(OUT) Context of the created semaphore
59  * @param      initial_count:(IN) Initial counter of the semaphore
60  * @return     M4NO_ERROR: there is no error
61  * @return     M4ERR_PARAMETER: provided context is NULL
62  * @return     M4ERR_ALLOC: there is no more available memory
63  * @return     M4ERR_CONTEXT_FAILED: the context creation failed
64  ************************************************************************
65 */
M4OSA_semaphoreOpen(M4OSA_Context * context,M4OSA_UInt32 initial_count)66 M4OSA_ERR M4OSA_semaphoreOpen(M4OSA_Context* context,
67                               M4OSA_UInt32 initial_count)
68 {
69    M4OSA_SemaphoreContext* semaphoreContext = M4OSA_NULL;
70 
71    M4OSA_TRACE1_2("M4OSA_semaphoreOpen\t\tM4OSA_Context* 0x%x\tM4OSA_UInt32 "
72                   "%d", context, initial_count);
73 
74    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
75                    M4ERR_PARAMETER, "M4OSA_semaphoreOpen");
76 
77    *context = M4OSA_NULL;
78 
79    semaphoreContext = (M4OSA_SemaphoreContext*) M4OSA_32bitAlignedMalloc(
80                       sizeof(M4OSA_SemaphoreContext), M4OSA_SEMAPHORE,
81                       (M4OSA_Char*)"M4OSA_semaphoreOpen: semaphore context");
82 
83    if(semaphoreContext == M4OSA_NULL)
84    {
85       M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_semaphoreOpen");
86 
87       return M4ERR_ALLOC;
88    }
89 
90    if (0 != sem_init(&semaphoreContext->semaphore, 0, initial_count))
91    {
92       free(semaphoreContext);
93 
94       M4OSA_DEBUG(M4ERR_CONTEXT_FAILED,
95          "M4OSA_semaphoreOpen: OS semaphore creation failed");
96 
97       return M4ERR_CONTEXT_FAILED;
98    }
99 
100    semaphoreContext->coreID = M4OSA_SEMAPHORE ;
101    *context = (M4OSA_Context)semaphoreContext;
102 
103    return M4NO_ERROR;
104 }
105 
106 
107 
108 
109 /**
110  ************************************************************************
111  * @brief      This method decrements (one by one) the semaphore counter. The
112  *             semaphore is identified by its context This call is not blocking
113  *             if the semaphore counter is positive or zero (after
114  *             decrementation). This call is blocking if the semaphore counter
115  *             is less than zero (after decrementation), until the semaphore is
116  *             upper than zero (see M4OSA_semaphorePost) or time_out is
117  *             reached.
118  * @note       If "timeout" value is M4OSA_WAIT_FOREVER, the calling thread
119  *             will block indefinitely until the semaphore  is unlocked.
120  * @param      context:(IN/OUT) Context of the semaphore
121  * @param      timeout:(IN) Time out in milliseconds
122  * @return     M4NO_ERROR: there is no error
123  * @return     M4ERR_PARAMETER: at least one parameter is NULL
124  * @return     M4WAR_TIME_OUT: time out is elapsed before semaphore has been
125  *             available.
126  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
127  ************************************************************************
128 */
M4OSA_semaphoreWait(M4OSA_Context context,M4OSA_Int32 timeout)129 M4OSA_ERR M4OSA_semaphoreWait(M4OSA_Context context, M4OSA_Int32 timeout)
130 {
131    M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context;
132    struct timespec         ts;
133    struct timespec         left;
134    int                     result;
135 
136    M4OSA_TRACE1_2("M4OSA_semaphoreWait\t\tM4OSA_Context 0x%x\tM4OSA_UInt32 %d",
137                   context, timeout);
138 
139    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
140                    M4ERR_PARAMETER, "M4OSA_semaphoreWait");
141 
142    M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE,
143                    M4ERR_BAD_CONTEXT, "M4OSA_semaphoreWait");
144 
145    if ( (M4OSA_Int32)M4OSA_WAIT_FOREVER == timeout)
146    {
147        if ( 0 != sem_wait(&semaphoreContext->semaphore) )
148        {
149            M4OSA_DEBUG(M4ERR_BAD_CONTEXT,
150                   "M4OSA_semaphoreWait: OS semaphore wait failed");
151 
152            return M4ERR_BAD_CONTEXT ;
153        }
154    }
155    else
156    {
157        result = sem_trywait(&semaphoreContext->semaphore);
158        while ( ((EBUSY == result) || (EAGAIN == result)) && ( 0 < timeout ) )
159        {
160            ts.tv_sec  = 0;
161            if (1 <= timeout)
162            {
163                ts.tv_nsec = 1000000;
164                timeout -= 1;
165            }
166            else
167            {
168                ts.tv_nsec = timeout * 1000000;
169                timeout = 0;
170            }
171            nanosleep(&ts, &left);
172            result = sem_trywait(&semaphoreContext->semaphore);
173        }
174        if (0 != result)
175        {
176            if ((EBUSY == result) || (EAGAIN == result))
177            {
178                return M4WAR_TIME_OUT;
179            }
180            else
181            {
182                M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_semaphoreWait: OS semaphore wait failed");
183                return M4ERR_BAD_CONTEXT;
184            }
185        }
186    }
187 
188    return M4NO_ERROR;
189 }
190 
191 
192 
193 
194 
195 /**
196  ************************************************************************
197  * @brief      This method increments the semaphore counter. The semaphore is
198  *             identified by its context
199  * @note       If the semaphore counter is upper than zero (after addition),
200  *             the M4OSA_semaphoreWait call of the thread with the highest
201  *             priority is unblocked and made ready to run.
202  * @note       No hypotheses can be made on which thread will be unblocked
203  *             between threads with the same priority.
204  * @param      context:(IN/OUT) Context of the semaphore
205  * @return     M4NO_ERROR: there is no error
206  * @return     M4ERR_PARAMETER: at least one parameter is NULL
207  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
208 ************************************************************************
209 */
M4OSA_semaphorePost(M4OSA_Context context)210 M4OSA_ERR M4OSA_semaphorePost(M4OSA_Context context)
211 {
212    M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context;
213 
214    M4OSA_TRACE1_1("M4OSA_semaphorePost\t\tM4OSA_Context 0x%x", context);
215 
216    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
217                    M4ERR_PARAMETER, "M4OSA_semaphorePost");
218 
219    M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE,
220                    M4ERR_BAD_CONTEXT, "M4OSA_semaphorePost");
221 
222    sem_post(&semaphoreContext->semaphore);
223 
224    return M4NO_ERROR;
225 }
226 
227 
228 
229 
230 
231 /**
232  ************************************************************************
233  * @brief      This method deletes a semaphore (identify by its context).
234  *             After this call the semaphore and its context is no more
235  *             useable. This function frees all the memory related to this
236  *             semaphore.
237  * @note       It is an application issue to warrant no more threads are locked
238  *             on the deleted semaphore.
239  * @param      context:(IN/OUT) Context of the semaphore
240  * @return     M4NO_ERROR: there is no error
241  * @return     M4ERR_PARAMETER: at least one parameter is NULL
242  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one.
243 ************************************************************************
244 */
M4OSA_semaphoreClose(M4OSA_Context context)245 M4OSA_ERR M4OSA_semaphoreClose(M4OSA_Context context)
246 {
247    M4OSA_SemaphoreContext* semaphoreContext = (M4OSA_SemaphoreContext*)context;
248 
249    M4OSA_TRACE1_1("M4OSA_semaphoreClose\t\tM4OSA_Context 0x%x", context);
250 
251    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
252                    M4ERR_PARAMETER, "M4OSA_semaphoreClose");
253 
254    M4OSA_DEBUG_IF2(semaphoreContext->coreID != M4OSA_SEMAPHORE,
255                    M4ERR_BAD_CONTEXT, "M4OSA_semaphoreClose");
256 
257    sem_destroy(&semaphoreContext->semaphore);
258 
259    free(semaphoreContext);
260 
261    return M4NO_ERROR;
262 }
263 
264