Makefile-> change name of netapi lib
[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 //#define TEST_DRIVER
44 #ifdef TEST_DRIVER
45 typedef void * NETAPI_T;
46 typedef void * NETAPI_TIMER_CB_T;
47 #else
48 #include "../netapi_timer.h"
49 #endif
50 #include "timer_loc.h"
51 #include "../netapi_err.h"
53 #ifndef NULL
54 #define NULL 0
55 #endif
58 //create a timer group
59 int tim_group_create(TIMER_GROUP_T *g, int n_cells, int n_timers)
60 {
61 char * mem= (char *) malloc(n_timers * sizeof (TIM_T));
62 if (!mem) return -1;
63 g->n_cells = n_cells;
64 tim_build_free(&g->free, mem, sizeof(TIM_T) * n_timers);
65 g->cells=(TIM_LIST_T *) malloc(n_cells * sizeof(TIM_LIST_T));
66 if (!g->cells) {free(mem);  return -1;}
67 g->n_timers=n_timers;
68 g->last_polled=0;
69 return 1;
70 }
72 //return as single timer to end of free list, zero cookie, etc
73 void tim_return_single_free(TIM_LIST_T *ftl,  TIM_T *p)
74 {
75 TIM_T * pt;
76 int i;
77 pt = ftl->tail;
78 if (!pt)
79 {
80 ftl->head=p;
81 ftl->tail=p;
82 }
83 else
84 {
85 pt->next=p;
86 ftl->tail = p;
87 }
88   p->t=0LL;
89   p->cookie=NULL;
90   p->next=NULL;
91 }
94 //return a list of N timers to  end of [free] list.  zero cookie, etc 
95 void tim_return_free(TIM_LIST_T *ftl,  TIM_LIST_T *p, int n)
96 {
97 TIM_T * pt;
98 int i;
99 pt = ftl->tail;
100 if (!pt) 
102 ftl->head=p->head;
103 ftl->tail=p->tail;
105 else 
107 pt->next=p->head;
108 ftl->tail = p->tail;
111 pt= p->head;
112 for(i=0;i<n;i++)
114   pt->t=0LL;
115   pt->cookie=NULL;
116   pt= pt->next;
118 ftl->tail->next=NULL;
121 //get a [free] entry from front of a list 
122 TIM_T * tim_get_free(TIM_LIST_T *tl, void *cookie, unsigned long long t)
124 TIM_T *p = tl->head;
125 if  (p)
127    tl->head=p->next;
128    p->next=NULL;
129    p->cookie = cookie;
130    p->t = t;
131    if (!tl->head) tl->tail=NULL;
133 return p;
136 //build a timer list from chunk of memory
137 int tim_build_free(TIM_LIST_T *tl, char *p_mem, int mem_size)
139 TIM_T * p = (TIM_T*) p_mem;
140 TIM_T * p_old = (TIM_T*) p_mem;
141 int i=0;
142 tl->head = p;
143 while(mem_size)
145    p_old = p;
146    p->cookie=NULL;
147    p->t = 0LL;
148    mem_size -= sizeof(TIM_T);
149    p+=1;
150    i+=1;
151    p_old->next=p;
153 p_old->next = NULL;
154 tl->tail = p_old;
155 return i;
158 //return a list of timers that have fired
159 void tim_return_fired_list(TIM_LIST_T *tl, TIM_LIST_T * pr, TIM_LIST_T * ftl, unsigned long long t,  int * p_nf)
161 int i=0;
162 int got_start=0;
163 int found_end=0;
164 TIM_T * p_last, *p, *temp_p_next;
165 TIM_LIST_T p_free={NULL,NULL};
166 pr->head=pr->tail=NULL;
167 if (! tl->head) { *p_nf=0; return ;}
169 p =  tl->head;
170 p_last= NULL; 
172 for(i=0;p;)
174   if(p->t <= t) 
175   {
176     if(!got_start)
177     {
178        if(p->cookie)
179        {
180        //start results chain
181          got_start=1;
182          pr->head=pr->tail = p;
183          i+=1;
184          p_last=p;
185          p=p->next;
186          continue;
187        }
188        else //skip over cancelled timer..
189        {
190          //skip & free. make sure we adjust head or tail if necessary
191          if (p_last){
192              p_last->next=p->next; 
193          }
194          else {
195             tl->head = p->next; /* we are freeing old head..*/
196          }
197          if (tl->tail ==p)  tl->tail=p_last; /* we are freeing old tail */
198          temp_p_next=p->next;
199          tim_return_single_free(ftl,p);
200          p=temp_p_next; 
201          /*keep p_last the same! */
202          continue;     
203        }
204     } 
205     else
206     {
207       if(!p->cookie)
208       {
209          //skip & free
210          if (p_last){ 
211              p_last->next=p->next; 
212          }
213          else {
214             tl->head = p->next;
215          }
216          if (tl->tail ==p)  tl->tail=p_last; /* we are freeing old tail */
217          temp_p_next=p->next;
218          tim_return_single_free(ftl,p);
219          p=temp_p_next;      
220          /*keep p_last the same! */
221          continue;
222       }  
223       else { //valid entry for list.
224         p_last=p; 
225         p=p->next;
226         i+=1;
227         continue;
228       }  
229     }
230   }
231   else  /* p->t > t */
232   {
233     if(got_start)
234     {
235        found_end =1; //found end of chain to return.  All is good
236        pr->tail = p_last;
237        p_last->next=NULL;
238        tl->head=p;
239     }
240     // done
241     break;
242   }
245 *p_nf=i;
246 if ((got_start) && (!found_end)) 
248   //cleared the list
249   printf("clearingthelist\n");
250   tl->head = tl->tail=NULL;
252 return;
255 //cancel a timer
256 void tim_cancel(TIM_T * p, int *pErr)
258  *pErr =0;
259  if (!p) {*pErr = NETAPI_ERR_BAD_INPUT; return; }
260  if (!p->cookie) {*pErr= NETAPI_ERR_ALREADY_CANCELLED; return;}
261  p->cookie = NULL;
262  return;
265 //set a timer 
266 TIM_T *tim_set(TIM_LIST_T *tl, TIM_LIST_T *free_tl, unsigned long long t, void *cookie, int *pErr)
268 TIM_T *pt = tl->head;
269 TIM_T *p = tim_get_free(free_tl, cookie, t);
270 TIM_T *pt_last= NULL;
271 int i;
272 *pErr=0;
273 if (!p ) { *pErr=NETAPI_ERR_NOMEM; return NULL;}  
275 if (!pt) //first one
277   tl->head = p;
278   tl->tail =p;
279   return p;  
282 //see if we can place at front of list
283 if (pt->t >=t)
285   tl->head=p;
286   p->next=pt;
287   return p;
290  //timer has hashed into this chain.  find out where
291 for(;pt;)
293    if (pt->t >= t)       
294    {
295       if (pt_last) {
296         pt_last->next = p;
297         p->next=pt;
298         return p;
299       }
300       else
301       {
302         tl->head=p;
303         p->next=pt;
304         return p;
305       }
306    }
307    else {pt_last=pt;pt=pt->next;}
309 //last one
310 pt_last->next=p;
311 p->next=NULL;
312 tl->tail=p;
313 return p;
316 #ifdef TEST_DRIVER
317 TIM_LIST_T the_base={NULL,NULL};
318 TIM_LIST_T cell_base={NULL,NULL};
319 char *mem;
320 TIM_T * timers[10];
321 TIM_LIST_T res;
322 main()
324  int err;
325  mem= malloc(100*sizeof(TIM_T));
326  TIM_T *p;
327  int n;
328  int i;
329  
330  tim_build_free(&the_base, mem , 100*sizeof(TIM_T));
332  timers[0]=tim_set(&cell_base, &the_base, 100LL, (void *) 1, &err);
333  timers[1]=tim_set(&cell_base, &the_base, 101LL, (void *) 2, &err);
334  timers[2]=tim_set(&cell_base, &the_base, 105LL, (void *) 3, &err);
335  timers[3]=tim_set(&cell_base, &the_base,  95LL, (void *) 4, &err);
336  timers[4]=tim_set(&cell_base, &the_base,  95LL, (void *) 5, &err);
337  timers[5]=tim_set(&cell_base, &the_base,  95LL, (void *) 6, &err);
338  timers[6]=tim_set(&cell_base, &the_base,  104LL, (void *) 7, &err);
339  timers[7]=tim_set(&cell_base, &the_base,  104LL, (void *) 8, &err);
340  timers[8]=tim_set(&cell_base, &the_base,  104LL, (void *) 9, &err);
342  tim_cancel(timers[6], &err);
344 for(i=90;i<106;i++)
345  {
346 tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) i,  &n);
347  printf("at %d got %d\n", i, n);
348  if (n) tim_return_free(&the_base,&res,n);
349  }
351 //special cases..
353  timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
354  tim_cancel(timers[0],&err);
355  tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);
356  
357  timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
358  timers[1]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
359  tim_cancel(timers[0],&err);
360  tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);
362  timers[0]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
363  timers[1]=tim_set(&cell_base, &the_base, 106LL, (void *)10, &err);
364  tim_cancel(timers[0],&err);
365  tim_cancel(timers[1],&err);
366  tim_return_fired_list(&cell_base, &res, &the_base, (unsigned long long) 106,  &n);
367  
369 #endif