1 /*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
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
19 #include "Semaphore.h"
20 #include "ErrorUtils.h"
21 #include <utils/Log.h>
22 #include <time.h>
23
24 namespace Ti {
25 namespace Utils {
26
27 /**
28 @brief Constructor for the semaphore class
29
30 @param none
31 @return none
32 */
Semaphore()33 Semaphore::Semaphore()
34 {
35 ///Initialize the semaphore to NULL
36 mSemaphore = NULL;
37 }
38
39 /**
40 @brief Destructor of the semaphore class
41
42 @param none
43 @return none
44
45 */
~Semaphore()46 Semaphore::~Semaphore()
47 {
48 Release();
49 }
50
51 /**
52 @brief: Releases semaphore
53
54 @param count >=0
55 @return NO_ERROR On Success
56 @return One of the android error codes based on semaphore de-initialization
57 */
58
Release()59 status_t Semaphore::Release()
60 {
61 int status = 0;
62
63 ///Destroy only if the semaphore has been created
64 if(mSemaphore)
65 {
66 status = sem_destroy(mSemaphore);
67
68 free(mSemaphore);
69
70 mSemaphore = NULL;
71 }
72
73 ///Initialize the semaphore and return the status
74 return ErrorUtils::posixToAndroidError(status);
75
76 }
77
78 /**
79 @brief Create the semaphore with initial count value
80
81 @param count >=0
82 @return NO_ERROR On Success
83 @return NO_MEMORY If unable to allocate memory for the semaphore
84 @return BAD_VALUE If an invalid count value is passed (<0)
85 @return One of the android error codes based on semaphore initialization
86 */
87
Create(int count)88 status_t Semaphore::Create(int count)
89 {
90 status_t ret = NO_ERROR;
91
92 ///count cannot be less than zero
93 if(count<0)
94 {
95 return BAD_VALUE;
96 }
97
98 ret = Release();
99 if ( NO_ERROR != ret )
100 {
101 return ret;
102 }
103
104 ///allocate memory for the semaphore
105 mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ;
106
107 ///if memory is unavailable, return error
108 if(!mSemaphore)
109 {
110 return NO_MEMORY;
111 }
112
113 ///Initialize the semaphore and return the status
114 return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count));
115
116 }
117
118 /**
119 @brief Wait operation
120
121 @param none
122 @return BAD_VALUE if the semaphore is not initialized
123 @return NO_ERROR On success
124 @return One of the android error codes based on semaphore wait operation
125 */
Wait()126 status_t Semaphore::Wait()
127 {
128 ///semaphore should have been created first
129 if(!mSemaphore)
130 {
131 return BAD_VALUE;
132 }
133
134 ///Wait and return the status after signalling
135 return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore));
136
137
138 }
139
140
141 /**
142 @brief Signal operation
143
144 @param none
145 @return BAD_VALUE if the semaphore is not initialized
146 @return NO_ERROR On success
147 @return One of the android error codes based on semaphore signal operation
148 */
149
Signal()150 status_t Semaphore::Signal()
151 {
152 ///semaphore should have been created first
153 if(!mSemaphore)
154 {
155 return BAD_VALUE;
156 }
157
158 ///Post to the semaphore
159 return ErrorUtils::posixToAndroidError(sem_post(mSemaphore));
160
161 }
162
163 /**
164 @brief Current semaphore count
165
166 @param none
167 @return Current count value of the semaphore
168 */
Count()169 int Semaphore::Count()
170 {
171 int val;
172
173 ///semaphore should have been created first
174 if(!mSemaphore)
175 {
176 return BAD_VALUE;
177 }
178
179 ///get the value of the semaphore
180 sem_getvalue(mSemaphore, &val);
181
182 return val;
183 }
184
185 /**
186 @brief Wait operation with a timeout
187
188 @param timeoutMicroSecs The timeout period in micro seconds
189 @return BAD_VALUE if the semaphore is not initialized
190 @return NO_ERROR On success
191 @return One of the android error codes based on semaphore wait operation
192 */
193
WaitTimeout(int timeoutMicroSecs)194 status_t Semaphore::WaitTimeout(int timeoutMicroSecs)
195 {
196 status_t ret = NO_ERROR;
197
198 struct timespec timeSpec;
199 struct timeval currentTime;
200
201 ///semaphore should have been created first
202 if( NULL == mSemaphore)
203 {
204 ret = BAD_VALUE;
205 }
206
207 if ( NO_ERROR == ret )
208 {
209
210 ///setup the timeout values - timeout is specified in seconds and nanoseconds
211 gettimeofday(¤tTime, NULL);
212 timeSpec.tv_sec = currentTime.tv_sec;
213 timeSpec.tv_nsec = currentTime.tv_usec * 1000;
214 timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 );
215 timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000;
216
217 ///Wait for the timeout or signal and return the result based on whichever event occurred first
218 ret = sem_timedwait(mSemaphore, &timeSpec);
219 }
220
221 if ( NO_ERROR != ret )
222 {
223 Signal();
224 Create(0);
225 }
226
227 return ret;
228 }
229
230
231 } // namespace Utils
232 } // namespace Ti
233