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
24namespace Ti {
25namespace Utils {
26
27/**
28   @brief Constructor for the semaphore class
29
30   @param none
31   @return none
32 */
33Semaphore::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 */
46Semaphore::~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
59status_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
88status_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 */
126status_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
150status_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 */
169int 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
194status_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(&currentTime, 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