1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 // -*- c++ -*-
19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
20
21
22 // OSCL_S E M A P H O R E (S E M A P H O R E I M P L E M E N T A T I O N)
23
24
25 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
26
27 /*! \file oscl_semaphore.cpp .This file provides SEMAPHORE implementation that can be ported
28 to three OS LINUX, SYMBIAN, WIN32
29 */
30
31 // Implementation file for OSCL Semaphores
32 #include "oscl_semaphore.h"
33 #include "oscl_assert.h"
34
35
36
37 // Class contructor
OsclSemaphore()38 OSCL_EXPORT_REF OsclSemaphore::OsclSemaphore()
39 {
40 bCreated = false;
41 }
42
~OsclSemaphore()43 OSCL_EXPORT_REF OsclSemaphore::~OsclSemaphore()
44 {
45 //make sure it was closed
46 OSCL_ASSERT(!bCreated);
47 }
48
49
50 /**
51 * Creates the Semaphore
52 *
53 * @param Intialcount & Maximum count
54 *
55 * @return Returns the Error whether it is success or failure.
56 * Incase of failure it will return what is the specific error
57 */
Create(uint32 InitialCount)58 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Create(uint32 InitialCount)
59 {
60 if (bCreated)
61 return OsclProcStatus::INVALID_OPERATION_ERROR;
62
63
64 iCount = InitialCount;
65 if (pthread_cond_init(&ObjCondition, NULL) == 0
66 && pthread_mutex_init(&ObjMutex, NULL) == 0)
67 {
68 bCreated = true;
69 return OsclProcStatus::SUCCESS_ERROR;
70 }
71 return OsclProcStatus::OTHER_ERROR;
72
73 }
74
75
76 /**
77 * Closes the Semaphore
78 *
79 * @param It wont take any parameters
80 *
81 * @return Returns the Error whether it is success or failure.
82 * Incase of failure it will return what is the specific error
83 */
Close(void)84 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Close(void)
85 {
86 if (!bCreated)
87 return OsclProcStatus::INVALID_OPERATION_ERROR;
88
89 bCreated = false;
90 return OsclProcStatus::SUCCESS_ERROR;
91
92 }
93
94
95
96 /**
97 * Waits for access to the Semaphore
98 *
99 * @param It wont take any parameters
100 *
101 * @return Returns the Error whether it is success or failure
102 * Incase of failure it will return what is the specific error
103 */
Wait()104 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Wait()
105 {
106 if (!bCreated)
107 return OsclProcStatus::INVALID_OPERATION_ERROR;
108
109
110 int res = pthread_mutex_lock(&ObjMutex);
111 if (res != 0)
112 return OsclProcStatus::OTHER_ERROR;
113 while (iCount == 0 && res == 0)
114 { // wait till the semaphore is signaled
115 // or an error has occurred
116 res = pthread_cond_wait(&ObjCondition, &ObjMutex);
117 }
118 if (res == 0)
119 { // signaled
120 iCount--;
121 }
122 pthread_mutex_unlock(&ObjMutex);
123 if (res != 0)
124 { // error occurred
125 // invalid condition or mutex
126 return OsclProcStatus::OTHER_ERROR;
127 }
128 return OsclProcStatus::SUCCESS_ERROR;
129
130 }
131
132 #include "osclconfig_time.h"
getAbsTime(struct timespec & abs,uint32 timeout_msec)133 static void getAbsTime(struct timespec &abs, uint32 timeout_msec)
134 {
135 //convert timeout msec to sec + usec.
136 uint32 timeout_sec = timeout_msec / 1000;
137 uint32 timeout_usec = (timeout_msec % 1000) * 1000;
138
139 //compute target time = time now plus timeout.
140
141 struct timeval timenow;
142 gettimeofday(&timenow, NULL);
143
144 uint32 targ_sec = timenow.tv_sec + timeout_sec;
145 uint32 targ_usec = timenow.tv_usec + timeout_usec;
146 while (targ_usec >= 1000000)
147 {
148 targ_sec++;
149 targ_usec -= 1000000;
150 }
151
152 //convert target time to timespec.
153 abs.tv_sec = targ_sec;
154 abs.tv_nsec = targ_usec * 1000;
155 }
156
157 /**
158 * Makes the thread to wait on the Semaphore, with a timeout.
159 *
160 * @param timeout in milliseconds.
161 *
162 * @return Returns WAIT_TIMEOUT_ERROR if the timeout expires,
163 * SUCCESS_ERROR if the semaphore is obtained, or in
164 * case of failure it will return what is the specific error
165 */
Wait(uint32 timeout_msec)166 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Wait(uint32 timeout_msec)
167 {
168 if (!bCreated)
169 return OsclProcStatus::INVALID_OPERATION_ERROR;
170
171
172 int res = pthread_mutex_lock(&ObjMutex);
173 if (res != 0)
174 return OsclProcStatus::OTHER_ERROR;
175 if (iCount > 0)
176 {
177 iCount--;
178 pthread_mutex_unlock(&ObjMutex);
179 return OsclProcStatus::SUCCESS_ERROR;
180 }
181
182 struct timespec abs;
183 getAbsTime(abs, timeout_msec);
184
185 while ((iCount == 0) && (res == 0))
186 { // wait till semaphore is signaled
187 // or time runs out
188 res = pthread_cond_timedwait(&ObjCondition, &ObjMutex, &abs);
189 }
190 if (res == 0)
191 { // signalied
192 iCount--;
193 }
194 pthread_mutex_unlock(&ObjMutex);
195 if (res == ETIMEDOUT)
196 { // timeour occurred
197 return OsclProcStatus::WAIT_TIMEOUT_ERROR;
198 }
199 else if (res != 0)
200 { // error occurred
201 return OsclProcStatus::OTHER_ERROR;
202 }
203 return OsclProcStatus::SUCCESS_ERROR;
204
205 }
206
207 /**
208 * Try to acquire semaphore, if the semaphore is already acquired by another thread,
209 * calling thread immediately returns with out blocking
210 *
211 * @param It wont take any parameters
212 *
213 * @return Returns the Error whether it is success or failure
214 * Incase of failure it will return what is the specific error
215 */
TryWait()216 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::TryWait()
217 {
218 if (!bCreated)
219 return OsclProcStatus::INVALID_OPERATION_ERROR;
220
221
222 int res = pthread_mutex_lock(&ObjMutex);
223 if (res != 0)
224 return OsclProcStatus::OTHER_ERROR;
225 if (iCount > 0)
226 {//take it
227 iCount--;
228 pthread_mutex_unlock(&ObjMutex);
229 return OsclProcStatus::SUCCESS_ERROR;
230 }
231 else
232 {//can't take it now so don't block.
233 pthread_mutex_unlock(&ObjMutex);
234 return OsclProcStatus::SEM_NOT_SIGNALED_ERROR;
235 }
236
237 }
238
239
240 /**
241 * Signals that the thread is finished with the Semaphore
242 *
243 * @param It wont take any parameters
244 *
245 * @return Returns the Error whether it is success or failure
246 * Incase of failure it will return what is the specific error
247 */
Signal()248 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclSemaphore::Signal()
249 {
250 if (!bCreated)
251 return OsclProcStatus::INVALID_OPERATION_ERROR;
252
253
254 int res = pthread_mutex_lock(&ObjMutex);
255 if (res != 0)
256 return OsclProcStatus::OTHER_ERROR;
257 iCount++;
258 res = pthread_cond_signal(&ObjCondition);
259 pthread_mutex_unlock(&ObjMutex);
260 if (res != 0)
261 return OsclProcStatus::OTHER_ERROR;
262 return OsclProcStatus::SUCCESS_ERROR;
263
264
265 }
266
267