1 /*
2 * Copyright (C) 2013 SAMSUNG S.LSI
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 /************************************************************************
20 ** OS interface for task handling
21 *************************************************************************/
22 #include <errno.h>
23 #include <pthread.h>
24 #include <string.h>
25 #include <sys/time.h>
26 #include "osi.h"
27
28 /************************************************************************
29 ** Internal function prototype
30 *************************************************************************/
31 void timer_thread(void);
32
33 /************************************************************************
34 ** Public functions
35 *************************************************************************/
OSI_timer_allocate(const char * timer_name)36 tOSI_TIMER_HANDLER OSI_timer_allocate(const char* timer_name) {
37 tOSI_TIMER_HANDLER free_timer = NULL;
38 int index;
39
40 osi_lock();
41 for (index = 0; index < OSI_MAX_TIMER; index++) {
42 if (osi_info.timer[index].state == OSI_FREE) {
43 if (free_timer == NULL)
44 free_timer = (tOSI_TIMER_HANDLER)&osi_info.timer[index];
45 } else {
46 if ((char const*)osi_info.timer[index].name == NULL) continue;
47
48 if (strcmp((char const*)osi_info.timer[index].name,
49 (char const*)timer_name) == 0) {
50 OSI_loge("%s : %s timer is already allocated [%d]", __func__,
51 timer_name, index);
52 free_timer = NULL;
53 break;
54 }
55 }
56 }
57
58 if (free_timer == NULL) {
59 OSI_loge("%s : Failed to find free timer(max: %d)", __func__,
60 OSI_MAX_TIMER);
61 } else {
62 free_timer->timeout = 0;
63 free_timer->name = timer_name;
64 free_timer->callback = NULL;
65 free_timer->callback_param = NULL;
66 free_timer->state = OSI_ALLOCATED;
67 }
68 osi_unlock();
69
70 return free_timer;
71 }
72
OSI_timer_start(tOSI_TIMER_HANDLER timer,uint32_t timeout,tOSI_TIMER_CALLBACK callback,void * param)73 int OSI_timer_start(tOSI_TIMER_HANDLER timer, uint32_t timeout,
74 tOSI_TIMER_CALLBACK callback, void* param) {
75 pthread_attr_t attr;
76 int ret_th;
77
78 if (timer == NULL) {
79 OSI_loge("%s : Invalid parameters", __func__);
80 return 0;
81 } else if (timer->state == OSI_FREE) {
82 OSI_loge("%s : The timer is not allocated", __func__);
83 return 0;
84 } else {
85 osi_lock();
86 OSI_logt("enter,osi_lock");
87 timer->timeout = timeout;
88 timer->exact_time = OSI_timer_get_current_time();
89 timer->init_timeout = timeout - 10;
90 timer->callback = callback;
91 timer->callback_param = param;
92
93 if (timer->state != OSI_RUN) {
94 timer->state = OSI_RUN;
95
96 /* start timer thread */
97 if (osi_info.usingTimer < 1) {
98 osi_info.timer_thread_flag |= OSI_TIMER_THREAD_FLAG_DETACH;
99 //[START] S.LSI - To increase usingTimer prior to timer_thread
100 osi_info.usingTimer++;
101 //[END] S.LSI - To increase usingTimer prior to timer_thread
102 ret_th = pthread_attr_init(&attr);
103 if (ret_th != 0)
104 OSI_loge("%s : Error pthread_attr_init! ,erron: %d", __func__,
105 ret_th);
106
107 OSI_logt("before pthread_create for timer thread");
108 ret_th = pthread_create(&osi_info.timer_thread, &attr,
109 (void* (*)(void*))timer_thread, NULL);
110 OSI_logt("after pthread_create for timer thread");
111 if (ret_th != 0)
112 OSI_loge("%s : Error to create timer_thread! ,erron: %d", __func__,
113 ret_th);
114
115 ret_th = pthread_attr_destroy(&attr);
116 if (ret_th != 0)
117 OSI_loge("%s : Error pthread_arrt_destroy ,erron: %d", __func__,
118 ret_th);
119 } else
120 osi_info.usingTimer++;
121 }
122 OSI_logt("before osi_unlock");
123 osi_unlock();
124 OSI_logt("exit");
125 return timeout;
126 }
127 }
128
OSI_timer_stop(tOSI_TIMER_HANDLER timer)129 void OSI_timer_stop(tOSI_TIMER_HANDLER timer) {
130 if (timer == NULL) {
131 OSI_loge("%s : Invalid parameters", __func__);
132 } else if (timer->state != OSI_RUN) {
133 OSI_logd("%s : This timer is not running", __func__);
134 } else {
135 osi_lock();
136 timer->state = OSI_STOP;
137 osi_info.usingTimer--;
138 if (osi_info.usingTimer <= 0) {
139 /* Cancle pthread_detach */
140 osi_info.timer_thread_flag &= ~OSI_TIMER_THREAD_FLAG_DETACH;
141 osi_unlock();
142 pthread_join(osi_info.timer_thread, NULL);
143 } else
144 osi_unlock();
145 }
146 }
147
OSI_timer_free(tOSI_TIMER_HANDLER timer)148 void OSI_timer_free(tOSI_TIMER_HANDLER timer) {
149 if (timer) {
150 osi_lock();
151
152 if (timer->state == OSI_RUN) osi_info.usingTimer--;
153
154 timer->state = OSI_FREE;
155 timer->name = NULL;
156 timer->callback = NULL;
157 timer->callback_param = NULL;
158
159 osi_unlock();
160 }
161 }
162
OSI_timer_get_handler(char * name)163 tOSI_TIMER_HANDLER OSI_timer_get_handler(char* name) {
164 tOSI_TIMER_HANDLER timer = NULL;
165 int index;
166
167 if (name == NULL) return NULL;
168
169 osi_lock();
170 for (index = 0; index < OSI_MAX_TIMER; index++) {
171 if ((char const*)osi_info.timer[index].name == NULL) continue;
172
173 if (strcmp((char const*)osi_info.timer[index].name, (char const*)name) ==
174 0) {
175 timer = &osi_info.timer[index];
176 break;
177 }
178 }
179 osi_unlock();
180
181 return timer;
182 }
183
OSI_timer_get_current_time()184 int32_t OSI_timer_get_current_time() {
185 struct timeval sec;
186 struct tm* now;
187 time_t rawtime;
188
189 gettimeofday(&sec, NULL);
190 time(&rawtime);
191 now = gmtime(&rawtime);
192
193 return (((now->tm_hour * 3600) + (now->tm_min * 60) + (now->tm_sec)) * 1000) +
194 (sec.tv_usec / 1000);
195 }
196 /************************************************************************
197 ** Internal function
198 *************************************************************************/
OSI_timer_update(int32_t tick)199 void OSI_timer_update(int32_t tick) {
200 int index;
201
202 osi_lock();
203
204 /* timer is not using */
205 if (osi_info.usingTimer <= 0) {
206 osi_unlock();
207 return;
208 }
209
210 for (index = 0; index < OSI_MAX_TIMER; index++) {
211 if (osi_info.timer[index].state == OSI_RUN) {
212 osi_info.timer[index].timeout -= tick;
213
214 if (osi_info.timer[index].timeout <= 0) {
215 /* START [16051100] - RTCC Patch */
216 if (((OSI_timer_get_current_time() - osi_info.timer[index].exact_time) >
217 osi_info.timer[index].init_timeout) ||
218 (OSI_timer_get_current_time() < osi_info.timer[index].exact_time))
219 /* END [16051100] - RTCC Patch */
220 {
221 osi_info.timer[index].state = OSI_STOP;
222 osi_info.usingTimer--;
223
224 if (osi_info.timer[index].callback != NULL)
225 osi_info.timer[index].callback(
226 osi_info.timer[index].callback_param);
227 } else {
228 osi_info.timer[index].timeout =
229 osi_info.timer[index].init_timeout -
230 (OSI_timer_get_current_time() - osi_info.timer[index].exact_time);
231 }
232 }
233 }
234 }
235 osi_unlock();
236 }
237
timer_thread(void)238 void timer_thread(void) {
239 struct timespec delay;
240 int err;
241
242 while (osi_info.usingTimer > 0) {
243 /* delay */
244 // OSI_delay(1);
245 {
246 /* 1ms sleep for nanosleep()*/
247 delay.tv_sec = 0;
248 delay.tv_nsec = 1000 * 1000;
249
250 do {
251 err = nanosleep(&delay, &delay);
252 if (err < 0) OSI_loge("%s:Fail nanosleep", __func__);
253 } while (err < 0 && errno == EINTR);
254 }
255
256 OSI_timer_update(1);
257 }
258
259 if (osi_info.timer_thread_flag & OSI_TIMER_THREAD_FLAG_DETACH)
260 pthread_detach(pthread_self());
261
262 pthread_exit(NULL);
263 }
264