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 */ 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 */ 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 */ 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 */ 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