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 <pthread.h>
23 #include <sched.h>
24 #include <string.h>
25 #include "osi.h"
26 
27 /************************************************************************
28 ** Internal function prototype
29 *************************************************************************/
30 
31 /************************************************************************
32 ** Public functions
33 *************************************************************************/
OSI_mem_get(size_t size)34 tOSI_MEM_HANDLER OSI_mem_get(size_t size) {
35   tOSI_MEM_HANDLER free_mem = NULL;
36   int index, err_cnt = 3;
37 
38   if (size > OSI_MEM_POOL_SIZE) {
39     OSI_loge("%s : memory getting failed. Max size=%d, Requested size=%d",
40              __func__, OSI_MEM_POOL_SIZE, (int)size);
41     return NULL;
42   }
43 
44 /* Try 3 times to get memory */
45 retry_getting:
46 
47   osi_lock();
48   for (index = 0; index < osi_info.mem_max_cnt; index++) {
49 #ifdef OSI_USE_DYNAMIC_BUF
50     if (osi_info.mem[index]->state == OSI_FREE)
51       free_mem = (tOSI_MEM_HANDLER)osi_info.mem[index];
52 #else
53     if (osi_info.mem[index].state == OSI_FREE)
54       free_mem = (tOSI_MEM_HANDLER)&osi_info.mem[index];
55 #endif
56   }
57 
58   if (free_mem == NULL) {
59     /* Not found free memory handler */
60     OSI_loge("%s : Failed to find free memory pool(max: %d)", __func__,
61              osi_info.mem_max_cnt);
62 #ifdef OSI_USE_DYNAMIC_BUF
63     /* get a new buffer */
64     free_mem = osi_info.mem[index] =
65         (tOSI_MEM_HANDLER)malloc(OSI_MEM_POOL_SIZE);
66     if (osi_info.mem[index] != NULL) {
67       osi_info.mem[index]->state = OSI_FREE;
68       osi_info.mem_max_cnt++;
69       OSI_loge("%s : get a new buffer (max: %d)", __func__,
70                osi_info.mem_max_cnt);
71     } else
72 #endif
73         if (--err_cnt > 0) {
74       OSI_loge("%s : try %d time(s) more!", __func__, err_cnt + 1);
75       osi_unlock();
76       sched_yield();
77       OSI_delay(20);
78       goto retry_getting;
79     }
80   } else {
81     free_mem->state = OSI_ALLOCATED;
82     memset(free_mem->buffer, 0, OSI_MEM_POOL_SIZE);
83   }
84   osi_unlock();
85 
86   return free_mem;
87 }
88 
OSI_mem_free(tOSI_MEM_HANDLER target)89 void OSI_mem_free(tOSI_MEM_HANDLER target) {
90   if (!target) return;
91 
92   osi_lock();
93   target->state = OSI_FREE;
94   osi_unlock();
95 }
96 
OSI_queue_allocate(const char * que_name)97 tOSI_QUEUE_HANDLER OSI_queue_allocate(const char* que_name) {
98   tOSI_QUEUE_HANDLER free_que = NULL;
99   int index;
100 
101   osi_lock();
102   for (index = 0; index < osi_info.queue_max_cnt; index++) {
103     if (osi_info.queue[index].state == OSI_FREE) {
104       if (free_que == NULL)
105         free_que = (tOSI_QUEUE_HANDLER)&osi_info.queue[index];
106     } else {
107       if (osi_info.queue[index].name == NULL) continue;
108 
109       if (strcmp((char const*)osi_info.queue[index].name,
110                  (char const*)que_name) == 0) {
111         OSI_loge("%s : %s queue is already allocated [%d]", __func__, que_name,
112                  index);
113         free_que = NULL;
114         break;
115       }
116     }
117   }
118 
119   if (free_que == NULL) {
120     OSI_loge("%s : Failed to find free queue(max: %d)", __func__,
121              OSI_MAX_QUEUE);
122   } else {
123     memset(free_que->queue, 0, OSI_QUEUE_SIZE);
124     free_que->name = que_name;
125     free_que->state = OSI_ALLOCATED;
126     free_que->head = 0;
127     free_que->tail = OSI_QUEUE_SIZE;
128   }
129   osi_unlock();
130 
131   return free_que;
132 }
133 
OSI_queue_put(tOSI_QUEUE_HANDLER queue,void * p_data)134 int OSI_queue_put(tOSI_QUEUE_HANDLER queue, void* p_data) {
135   int ret;
136 
137   osi_lock();
138 
139   if (!queue || queue->state != OSI_ALLOCATED) {
140     OSI_loge("%s : queue is not allocated", __func__);
141     return -1;
142   }
143 
144   if (queue->head == queue->tail) {
145     OSI_loge("%s : queue is overflower (max: %d)", __func__, OSI_QUEUE_SIZE);
146   } else {
147     queue->queue[queue->head++] = p_data;
148     if (queue->head >= OSI_QUEUE_SIZE) queue->head = 0;
149 
150     // pthread_cond_broadcast(&queue->cond);
151     pthread_cond_signal(&queue->cond);
152   }
153 
154   ret = (queue->head) - (queue->tail);
155 
156   osi_unlock();
157 
158   if (ret < 0) ret += OSI_QUEUE_SIZE;
159 
160   return ret;
161 }
162 
queue_get(tOSI_QUEUE_HANDLER queue)163 void* queue_get(tOSI_QUEUE_HANDLER queue) {
164   void* data = NULL;
165 
166   if (!queue || queue->state != OSI_ALLOCATED) {
167     OSI_loge("%s : queue is not allocated", __func__);
168     return NULL;
169   }
170 
171   if (queue->tail + 1 >= OSI_QUEUE_SIZE) {
172     if (queue->head == 0) {
173       // empty
174       // OSI_loge("%s : queue is empty", __func__);
175       return NULL;
176     }
177   } else {
178     if (queue->tail + 1 == queue->head) {
179       // empty
180       // OSI_loge("%s : queue is empty", __func__);
181       return NULL;
182     }
183   }
184 
185   queue->tail++;
186   if (queue->tail >= OSI_QUEUE_SIZE) queue->tail = 0;
187   data = queue->queue[queue->tail];
188 
189   return data;
190 }
191 
OSI_queue_get(tOSI_QUEUE_HANDLER queue)192 void* OSI_queue_get(tOSI_QUEUE_HANDLER queue) {
193   void* data = NULL;
194 
195   osi_lock();
196   data = queue_get(queue);
197   osi_unlock();
198 
199   return data;
200 }
201 
OSI_queue_get_wait(tOSI_QUEUE_HANDLER queue)202 void* OSI_queue_get_wait(tOSI_QUEUE_HANDLER queue) {
203   void* ret;
204 
205   osi_lock();
206 
207   if (!queue || queue->state != OSI_ALLOCATED) {
208     OSI_loge("%s : queue is not allocated", __func__);
209     return NULL;
210   }
211 
212   ret = queue_get(queue);
213   if (ret == NULL) {
214     pthread_cond_wait(&queue->cond, &osi_info.mutex);
215     ret = queue_get(queue);
216   }
217 
218   osi_unlock();
219 
220   return ret;
221 }
222 
OSI_queue_free(tOSI_QUEUE_HANDLER target)223 void OSI_queue_free(tOSI_QUEUE_HANDLER target) {
224   if (target) {
225     target->name = NULL;
226     target->state = OSI_FREE;
227   }
228 }
229 
OSI_queue_get_handler(const char * name)230 tOSI_QUEUE_HANDLER OSI_queue_get_handler(const char* name) {
231   tOSI_QUEUE_HANDLER queue = NULL;
232   int index;
233 
234   if (name == NULL) return NULL;
235 
236   osi_lock();
237   for (index = 0; index < OSI_MAX_QUEUE; index++) {
238     if (osi_info.queue[index].name == NULL) continue;
239 
240     if (strcmp((char const*)osi_info.queue[index].name, (char const*)name) ==
241         0) {
242       queue = (tOSI_QUEUE_HANDLER)&osi_info.queue[index];
243       break;
244     }
245   }
246   osi_unlock();
247 
248   return queue;
249 }
250