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