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