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