[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / utils / hlos / knl / osal / Qnx / OsalSemaphore.c
1 /**
2 * @file OsalSemaphore.c
3 *
4 * @brief Semaphore interface implementation.
5 *
6 * This abstracts the Semaphore interface in Kernel code and
7 * is implemented using the wait queues. It has interfaces
8 * for creating, destroying, waiting and triggering the Semaphores.
9 *
10 * @ver 02.00.00.46_alpha1
11 *
12 * ============================================================================
13 *
14 * Copyright (c) 2010-2011, Texas Instruments Incorporated
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * * Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 *
23 * * Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 *
27 * * Neither the name of Texas Instruments Incorporated nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
33 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
37 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
38 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
41 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * Contact information for paper mail:
43 * Texas Instruments
44 * Post Office Box 655303
45 * Dallas, Texas 75265
46 * Contact information:
47 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
48 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
49 * ============================================================================
50 *
51 */
54 /* Standard headers */
55 #include <ti/syslink/Std.h>
57 /* OSAL and utils headers */
58 #include <OsalSemaphore.h>
59 #include <ti/syslink/utils/Trace.h>
60 #include <ti/syslink/utils/Memory.h>
62 #include <pthread.h>
63 #include <time.h>
64 #include <inttypes.h>
65 #include <errno.h>
68 #if defined (__cplusplus)
69 extern "C" {
70 #endif
73 /* =============================================================================
74 * Macros and types
75 * =============================================================================
76 */
77 /*!
78 * @brief Defines object to encapsulate the Semaphore.
79 * The definition is OS/platform specific.
80 */
81 typedef struct OsalSemaphore_Object_tag {
82 OsalSemaphore_Type semType;
83 /*!< Indicates the type of the semaphore (binary or counting). */
84 /*!< List of waiting processes. */
85 UInt32 value;
86 /*!< Current status of semaphore (0,1) - binary and (0-n) counting. */
87 pthread_mutex_t lock;
88 pthread_cond_t cond;
89 /*!< lock on which this Semaphore is based. */
90 } OsalSemaphore_Object;
93 /* =============================================================================
94 * APIs
95 * =============================================================================
96 */
97 /*!
98 * @brief Creates an instance of Mutex object.
99 *
100 * @param semType Type of semaphore. This parameter is a mask of semaphore
101 * type and interruptability type.
102 *
103 * @sa OsalSemaphore_delete
104 */
105 OsalSemaphore_Handle
106 OsalSemaphore_create (UInt32 semType)
107 {
108 OsalSemaphore_Object * semObj = NULL;
110 GT_1trace (curTrace, GT_ENTER, "OsalSemaphore_create", semType);
112 /* Check for semaphore type (binary/counting) */
113 GT_assert (curTrace,
114 ( (OSALSEMAPHORE_TYPE_VALUE(semType))
115 < OsalSemaphore_Type_EndValue));
116 /* Check for semaphore interruptability */
117 GT_assert (curTrace,
118 ( (OSALSEMAPHORE_INTTYPE_VALUE(semType))
119 < OsalSemaphore_IntType_EndValue));
121 #if !defined(SYSLINK_BUILD_OPTIMIZE)
122 if (OSALSEMAPHORE_TYPE_VALUE(semType) >= OsalSemaphore_Type_EndValue) {
123 /*! @retval NULL Invalid semaphore type (OsalSemaphore_Type) provided */
124 GT_setFailureReason (curTrace,
125 GT_4CLASS,
126 "OsalSemaphore_create",
127 OSALSEMAPHORE_E_INVALIDARG,
128 "Invalid semaphore type (OsalSemaphore_Type) provided");
129 }
130 else if ( OSALSEMAPHORE_INTTYPE_VALUE(semType)
131 >= OsalSemaphore_IntType_EndValue) {
132 /*! @retval NULL Invalid semaphore interruptability type
133 (OsalSemaphore_IntType) provided */
134 GT_setFailureReason (curTrace,
135 GT_4CLASS,
136 "OsalSemaphore_create",
137 OSALSEMAPHORE_E_INVALIDARG,
138 "Invalid semaphore interruptability type "
139 "(OsalSemaphore_IntType) provided");
140 }
141 else {
142 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
143 semObj = calloc (1, sizeof (OsalSemaphore_Object));
144 #if !defined(SYSLINK_BUILD_OPTIMIZE)
145 if (semObj == NULL) {
146 /*! @retval NULL Failed to allocate memory for semaphore object. */
147 GT_setFailureReason (curTrace,
148 GT_4CLASS,
149 "OsalSemaphore_create",
150 OSALSEMAPHORE_E_MEMORY,
151 "Failed to allocate memory for semaphore object.");
152 }
153 else {
154 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
155 pthread_condattr_t attr;
156 semObj->semType = semType;
157 semObj->value = 0u;
158 pthread_mutex_init (&(semObj->lock), NULL);
159 pthread_condattr_init(&attr);
160 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
161 pthread_cond_init (&(semObj->cond), &attr);
162 pthread_condattr_destroy(&attr);
163 #if !defined(SYSLINK_BUILD_OPTIMIZE)
164 }
165 }
166 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
168 GT_1trace (curTrace, GT_LEAVE, "OsalSemaphore_create", semObj);
170 /*! @retval Semaphore-handle Operation successfully completed. */
171 return (OsalSemaphore_Handle) semObj;
172 }
175 /*!
176 * @brief Deletes an instance of Semaphore object.
177 *
178 * @param mutexHandle Semaphore object handle which needs to be deleted.
179 *
180 * @sa OsalSemaphore_create
181 */
182 Int
183 OsalSemaphore_delete (OsalSemaphore_Handle * semHandle)
184 {
185 Int status = OSALSEMAPHORE_SUCCESS;
186 OsalSemaphore_Object * semObj;
188 GT_1trace (curTrace, GT_ENTER, "OsalSemaphore_delete", semHandle);
190 GT_assert (curTrace, (semHandle != NULL));
192 #if !defined(SYSLINK_BUILD_OPTIMIZE)
193 if (semHandle == NULL) {
194 /*! @retval OSALSEMAPHORE_E_INVALIDARG NULL provided for argument
195 semHandle.*/
196 status = OSALSEMAPHORE_E_INVALIDARG;
197 GT_setFailureReason (curTrace,
198 GT_4CLASS,
199 "OsalSemaphore_delete",
200 status,
201 "NULL provided for argument semHandle");
202 }
203 else if (*semHandle == NULL) {
204 /*! @retval OSALSEMAPHORE_E_HANDLE NULL Semaphore handle provided. */
205 status = OSALSEMAPHORE_E_HANDLE;
206 GT_setFailureReason (curTrace,
207 GT_4CLASS,
208 "OsalSemaphore_delete",
209 status,
210 "NULL Semaphore handle provided.");
211 }
212 else {
213 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
214 semObj = (OsalSemaphore_Object *) *semHandle;
215 pthread_mutex_destroy(&semObj->lock);
216 pthread_cond_destroy(&semObj->cond);
217 free (semObj);
218 *semHandle = NULL;
219 #if !defined(SYSLINK_BUILD_OPTIMIZE)
220 }
221 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
223 GT_1trace (curTrace, GT_LEAVE, "OsalSemaphore_delete", status);
225 /*! @retval OSALSEMAPHORE_SUCCESS Operation successfully completed. */
226 return status;
227 }
230 /*!
231 * @brief Wait on the Semaphore in the kernel thread context
232 *
233 * @param semHandle Semaphore object handle
234 * @param timeout Timeout (in msec). Special values are provided for
235 * no-wait and infinite-wait.
236 *
237 * @sa OsalSemaphore_post
238 */
239 Int
240 OsalSemaphore_pend (OsalSemaphore_Handle semHandle, UInt32 timeout)
241 {
242 Int status = OSALSEMAPHORE_SUCCESS;
243 OsalSemaphore_Object * semObj = (OsalSemaphore_Object *) semHandle;
244 int osStatus = 0;
246 GT_2trace (curTrace, GT_ENTER, "OsalSemaphore_pend", semHandle, timeout);
248 GT_assert (curTrace, (semHandle != NULL));
250 #if !defined(SYSLINK_BUILD_OPTIMIZE)
251 if (semHandle == NULL) {
252 /*! @retval OSALSEMAPHORE_E_HANDLE NULL Semaphore handle provided. */
253 status = OSALSEMAPHORE_E_HANDLE;
254 GT_setFailureReason (curTrace,
255 GT_4CLASS,
256 "OsalSemaphore_pend",
257 status,
258 "NULL Semaphore handle provided.");
259 }
260 else {
261 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
262 /* Different handling for no-timeout case. */
263 if (timeout == OSALSEMAPHORE_WAIT_NONE) {
264 osStatus = pthread_mutex_lock(&(semObj->lock));
265 GT_assert (curTrace, (osStatus == 0));
266 if (semObj->value == 0u) {
267 /*! @retval OSALSEMAPHORE_E_WAITNONE WAIT_NONE timeout value was
268 provided, but semaphore was not available. */
269 status = OSALSEMAPHORE_E_WAITNONE ;
270 GT_1trace (curTrace,
271 GT_3CLASS,
272 "OsalSemaphore_pend: "
273 "WAIT_NONE timeout value was provided, but"
274 " semaphore was not available\n"
275 " Handle [0x%x]",
276 semObj);
277 }
278 else {
279 if ( OSALSEMAPHORE_TYPE_VALUE(semObj->semType)
280 == OsalSemaphore_Type_Binary) {
281 semObj->value = 0u;
282 }
283 else {
284 semObj->value--;
285 }
286 }
287 pthread_mutex_unlock (&semObj->lock);
288 }
289 /* Finite and infinite timeout cases */
290 else {
291 /* Get timeout value in OS-recognizable format. */
292 if (timeout == OSALSEMAPHORE_WAIT_FOREVER) {
293 pthread_mutex_lock(&semObj->lock);
294 while (semObj->value == 0u) {
295 pthread_cond_wait(&semObj->cond, &semObj->lock);
296 }
297 if ( OSALSEMAPHORE_TYPE_VALUE(semObj->semType)
298 == OsalSemaphore_Type_Binary) {
299 semObj->value = 0u;
300 }
301 else {
302 semObj->value--;
303 }
304 pthread_mutex_unlock(&semObj->lock);
305 }
306 else {
307 uint64_t nsecs;
308 struct timespec abstime;
309 int ret;
310 clock_gettime(CLOCK_MONOTONIC, &abstime);
311 nsecs = abstime.tv_sec * 1000000000ULL + abstime.tv_nsec;
312 nsecs += timeout * 1000000ULL;
313 nsec2timespec(&abstime, nsecs);
314 pthread_mutex_lock(&semObj->lock);
315 while (semObj->value == 0u) {
316 ret = pthread_cond_timedwait(&semObj->cond, &semObj->lock, &abstime);
317 if (ret == ETIMEDOUT) {
318 status = OSALSEMAPHORE_E_TIMEOUT ;
319 break;
320 }
321 }
322 if (status != OSALSEMAPHORE_E_TIMEOUT) {
323 if ( OSALSEMAPHORE_TYPE_VALUE(semObj->semType)
324 == OsalSemaphore_Type_Binary) {
325 semObj->value = 0u;
326 }
327 else {
328 semObj->value--;
329 }
330 }
331 else {
332 GT_1trace (curTrace,
333 GT_3CLASS,
334 "OsalSemaphore_pend: "
335 "Timeout occurred on semaphore pend\n"
336 " Handle [0x%x]",
337 semObj);
338 }
339 pthread_mutex_unlock(&semObj->lock);
340 }
341 }
342 #if !defined(SYSLINK_BUILD_OPTIMIZE)
343 }
344 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
346 GT_1trace (curTrace, GT_LEAVE, "OsalSemaphore_pend", status);
348 /*! @retval OSALSEMAPHORE_SUCCESS Operation successfully completed. */
349 return status;
350 }
352 /*!
353 * @brief Signals the semaphore and makes it available for other
354 * threads.
355 *
356 * @param semHandle Semaphore object handle
357 *
358 * @sa OsalSemaphore_pend
359 */
360 Int
361 OsalSemaphore_post (OsalSemaphore_Handle semHandle)
362 {
363 Int status = OSALSEMAPHORE_SUCCESS;
364 OsalSemaphore_Object * semObj = (OsalSemaphore_Object *) semHandle;
365 int osStatus = 0;
367 GT_1trace (curTrace, GT_ENTER, "OsalSemaphore_post", semHandle);
369 GT_assert (curTrace, (semHandle != NULL));
371 #if !defined(SYSLINK_BUILD_OPTIMIZE)
372 if (semHandle == NULL) {
373 /*! @retval OSALSEMAPHORE_E_HANDLE NULL Semaphore handle provided. */
374 status = OSALSEMAPHORE_E_HANDLE;
375 GT_setFailureReason (curTrace,
376 GT_4CLASS,
377 "OsalSemaphore_post",
378 status,
379 "NULL Semaphore handle provided.");
380 }
381 else {
382 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
383 osStatus = pthread_mutex_lock (&(semObj->lock));
384 GT_assert (curTrace, (osStatus == 0));
385 semObj->value = 1u;
386 osStatus = pthread_cond_signal (&(semObj->cond));
387 pthread_mutex_unlock(&(semObj->lock));
388 #if !defined(SYSLINK_BUILD_OPTIMIZE)
389 }
390 #endif /* #if !defined(SYSLINK_BUILD_OPTIMIZE) */
392 GT_1trace (curTrace, GT_LEAVE, "OsalSemaphore_post", status);
394 /*! @retval OSALSEMAPHORE_SUCCESS Operation successfully completed. */
395 return status;
396 }
399 #if defined (__cplusplus)
400 }
401 #endif /* defined (_cplusplus)*/