This is the initial commit.
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / timlist.c
1 /******************************************
2  * FILE:timlist.c 
3  * Purpose:  timer low level primitives
4  ***********************************************
5 * FILE:timlist.c
6  * 
7  * DESCRIPTION:  netapi timer library source file for user space transport
8  *               library
9  * 
10  * REVISION HISTORY:  rev 0.0.1 
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2010-2011
13  * 
14  *  Redistribution and use in source and binary forms, with or without 
15  *  modification, are permitted provided that the following conditions 
16  *  are met:
17  *
18  *    Redistributions of source code must retain the above copyright 
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  *    Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the 
23  *    documentation and/or other materials provided with the   
24  *    distribution.
25  *
26  *    Neither the name of Texas Instruments Incorporated nor the names of
27  *    its contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  ***************************************/
43 #include "netapi_timer.h"
44 #include "timer_loc.h"
45 #include "netapi_err.h"
47 #ifndef NULL
48 #define NULL 0
49 #endif
52 //create a timer group
53 int tim_group_create(TIMER_GROUP_T *g, int n_cells, int n_timers)
54 {
55 char * mem= (char *) malloc(n_timers * sizeof (TIM_T));
56 if (!mem) return -1;
57 g->n_cells = n_cells;
58 tim_build_free(&g->free, mem, sizeof(TIM_T) * n_timers);
59 g->cells=(TIM_LIST_T *) malloc(n_cells * sizeof(TIM_LIST_T));
60 if (!g->cells) {free(mem);  return -1;}
61 g->n_timers=n_timers;
62 g->last_polled=0;
63 return 1;
64 }
66 //return as single timer to end of free list, zero cookie, etc
67 void tim_return_single_free(TIM_LIST_T *ftl,  TIM_T *p)
68 {
69 TIM_T * pt;
70 int i;
71 pt = ftl->tail;
72 if (!pt)
73 {
74 ftl->head=p;
75 ftl->tail=p;
76 }
77 else
78 {
79 pt->next=p;
80 ftl->tail = p;
81 }
82   p->t=0LL;
83   p->cookie=NULL;
84   p->next=NULL;
85 }
88 //return a list of N timers to  end of [free] list.  zero cookie, etc 
89 void tim_return_free(TIM_LIST_T *ftl,  TIM_LIST_T *p, int n)
90 {
91 TIM_T * pt;
92 int i;
93 pt = ftl->tail;
94 if (!pt) 
95 {
96 ftl->head=p->head;
97 ftl->tail=p->tail;
98 }
99 else 
101 pt->next=p->head;
102 ftl->tail = p->tail;
105 pt= p->head;
106 for(i=0;i<n;i++)
108   pt->t=0LL;
109   pt->cookie=NULL;
110   pt= pt->next;
112 ftl->tail->next=NULL;
115 //get a [free] entry from front of a list 
116 TIM_T * tim_get_free(TIM_LIST_T *tl, void *cookie, unsigned long long t)
118 TIM_T *p = tl->head;
119 if  (p)
121    tl->head=p->next;
122    p->next=NULL;
123    p->cookie = cookie;
124    p->t = t;
125    if (!tl->head) tl->tail=NULL;
127 return p;
130 //build a timer list from chunk of memory
131 int tim_build_free(TIM_LIST_T *tl, char *p_mem, int mem_size)
133 TIM_T * p = (TIM_T*) p_mem;
134 TIM_T * p_old = (TIM_T*) p_mem;
135 int i=0;
136 tl->head = p;
137 while(mem_size)
139    p_old = p;
140    p->cookie=NULL;
141    p->t = 0LL;
142    mem_size -= sizeof(TIM_T);
143    p+=1;
144    i+=1;
145    p_old->next=p;
147 p_old->next = NULL;
148 tl->tail = p_old;
149 return i;
152 //return a list of timers that have fired
153 void tim_return_fired_list(TIM_LIST_T *tl, TIM_LIST_T * pr, TIM_LIST_T * ftl, unsigned long long t,  int * p_nf)
155 int i=0;
156 int got_start=0;
157 int found_end=0;
158 TIM_T * p_last, *p, *temp_p_next;
159 TIM_LIST_T p_free={NULL,NULL};
160 pr->head=pr->tail=NULL;
161 if (! tl->head) { *p_nf=0; return ;}
163 p =  tl->head;
164 p_last= NULL; 
166 for(i=0;p;)
168   if(p->t <= t) 
169   {
170     if(!got_start)
171     {
172        if(p->cookie)
173        {
174        //start results chain
175          got_start=1;
176          pr->head=pr->tail = p;
177          i+=1;
178          p_last=p;
179          p=p->next;
180          continue;
181        }
182        else //skip over cancelled timer..
183        {
184          //skip & free
185          if (p_last){
186              p_last->next=p->next; 
187          }
188          else {
189             tl->head = p->next;
190          }
191          temp_p_next=p->next;
192          tim_return_single_free(ftl,p);
193          p=temp_p_next; 
194          /*keep p_last the same! */
195          continue;     
196        }
197     } 
198     else
199     {
200       if(!p->cookie)
201       {
202          //skip & free
203          if (p_last){ 
204              p_last->next=p->next; 
205          }
206          else {
207             tl->head = p->next;
208          }
209          temp_p_next=p->next;
210          tim_return_single_free(ftl,p);
211          p=temp_p_next;      
212          /*keep p_last the same! */
213          continue;
214       }  
215       else { //valid entry for list.
216         p_last=p; 
217         p=p->next;
218         i+=1;
219         continue;
220       }  
221     }
222   }
223   else  /* p->t > t */
224   {
225     if(got_start)
226     {
227        found_end =1; //found end of chain to return.  All is good
228        pr->tail = p_last;
229        p_last->next=NULL;
230        tl->head=p;
231     }
232     // done
233     break;
234   }
237 *p_nf=i;
238 if ((got_start) && (!found_end)) 
240   //cleared the list
241   printf("clearingthelist\n");
242   tl->head = tl->tail=NULL;
244 return;
247 //cancel a timer
248 void tim_cancel(TIM_T * p, int *pErr)
250  *pErr =0;
251  if (!p) {*pErr = NETAPI_ERR_BAD_INPUT; return; }
252  if (!p->cookie) {*pErr= NETAPI_ERR_ALREADY_CANCELLED; return;}
253  p->cookie = NULL;
254  return;
257 //set a timer 
258 TIM_T *tim_set(TIM_LIST_T *tl, TIM_LIST_T *free_tl, unsigned long long t, void *cookie, int *pErr)
260 TIM_T *pt = tl->head;
261 TIM_T *p = tim_get_free(free_tl, cookie, t);
262 TIM_T *pt_last= NULL;
263 int i;
264 *pErr=0;
265 if (!p ) { *pErr=NETAPI_ERR_NOMEM; return NULL;}  
267 if (!pt) //first one
269   tl->head = p;
270   tl->tail =p;
271   return p;  
274 //see if we can place at front of list
275 if (pt->t >=t)
277   tl->head=p;
278   p->next=pt;
279   return p;
282  //timer has hashed into this chain.  find out where
283 for(;pt;)
285    if (pt->t >= t)       
286    {
287       if (pt_last) {
288         pt_last->next = p;
289         p->next=pt;
290         return p;
291       }
292       else
293       {
294         tl->head=p;
295         p->next=pt;
296         return p;
297       }
298    }
299    else {pt_last=pt;pt=pt->next;}
301 //last one
302 pt_last->next=p;
303 p->next=NULL;
304 tl->tail=p;
305 return p;
308 //#define TEST_DRIVER
309 #ifdef TEST_DRIVER
310 TIM_LIST_T the_base={NULL,NULL};
311 TIM_LIST_T cell_base={NULL,NULL};
312 char *mem;
313 TIM_T * timers[10];
314 TIM_LIST_T res;
315 main()
317  int err;
318  mem= malloc(100*sizeof(TIM_T));
319  TIM_T *p;
320  int n;
321  int i;
322  
323  tim_build_free(&the_base, mem , 100*sizeof(TIM_T));
325  timers[0]=tim_set(&cell_base, &the_base, 100LL, (void *) 1, &err);
326  timers[1]=tim_set(&cell_base, &the_base, 101LL, (void *) 2, &err);
327  timers[2]=tim_set(&cell_base, &the_base, 105LL, (void *) 3, &err);
328  timers[3]=tim_set(&cell_base, &the_base,  95LL, (void *) 4, &err);
329  timers[4]=tim_set(&cell_base, &the_base,  95LL, (void *) 5, &err);
330  timers[5]=tim_set(&cell_base, &the_base,  95LL, (void *) 6, &err);
331  timers[6]=tim_set(&cell_base, &the_base,  104LL, (void *) 7, &err);
332  timers[7]=tim_set(&cell_base, &the_base,  104LL, (void *) 8, &err);
333  timers[8]=tim_set(&cell_base, &the_base,  104LL, (void *) 9, &err);
335  tim_cancel(timers[6], &err);
337 for(i=90;i<106;i++)
338  {
339 tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) i,  &n);
340  printf("at %d got %d\n", i, n);
341  if (n) tim_return_free(&the_base,&res,n);
342  }
343  
344  
346 #endif