1 /*******************************
2 * FILE: netapi_timer.c
3 * Purpose: implementation of user space timers
4 **************************************************************
5 * FILE: netapi.c
6 *
7 * DESCRIPTION: user space timers main 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 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 *
43 ***************************************************************/
44 #include "netapi.h"
45 #include "netapi_timer.h"
46 #include "timer_loc.h"
49 /*******************************************************************
50 * hash function: returns cell to place timer object in
51 *
52 ******************************************************************/
53 /* static */ int our_hash(
54 unsigned long long ct,
55 int n_cells,
56 unsigned int cell_width)
57 {
58 int c;
59 //simple hash function
60 c= (ct/cell_width) % n_cells;
61 return c;
63 }
65 //iterator on TIMER_LIST_T
66 NETAPI_TIMER_T netapi_TimerGetFirst( NETAPI_TIMER_LIST_T list)
67 { return (NETAPI_TIMER_T) ((TIM_LIST_T *)list)->head; }
69 NETAPI_TIMER_T netapi_TimerGetNext( NETAPI_TIMER_LIST_T list,NETAPI_TIMER_T prev)
70 {return prev ? (NETAPI_TIMER_T) ((TIM_T*) prev)->next:NULL ;}
72 //return cookie associated with timer object
73 void * netapi_TimerGetCookie(NETAPI_TIMER_T timer)
74 { return ((TIM_T*) timer)->cookie; }
76 //return timeer value associated with timer object
77 unsigned long long netapi_TimerGetTs(NETAPI_TIMER_T timer)
78 { return ((TIM_T*) timer)->t; }
80 #if 0
81 //timer callback
82 typedef void (*NETAPI_TIMER_CB_T) (
83 NETAPI_TIMER_GROUP_HANDLE_T th,
84 int n_fired, //# timers fired
85 NETAPI_TIMER_LIST_T fired_list,
86 uint64_t currentTime);
87 #endif
89 static TIMER_GROUP_T temp_g; //temp. todo: put inot netHandle
91 //create a timer group
92 NETAPI_TIMER_GROUP_HANDLE_T netapi_TimerGroupCreate(
93 NETAPI_T netHandle,
94 char * name,
95 NETAPI_TIMER_CB_T cb,
96 int local, //1 if timers local to thread
97 int exp2cancel,//1 if expect to cancel
98 int cell_width, //in ticks
99 int tol, //in ticks
100 int maxTimers,
101 int *pErr)
102 {
103 int ret= tim_group_create(&temp_g, TUNE_NETAPI_NUM_TIMER_CELLS, maxTimers);
104 if (!ret) {*pErr = NETAPI_ERR_NOMEM; return NULL;}
105 *pErr=0;
106 temp_g.cb = cb;
107 temp_g.local = local;
108 temp_g.exp2cancel= exp2cancel;
109 temp_g.cell_width=cell_width;
110 temp_g.tol=tol;
111 temp_g.h = netHandle;
112 temp_g.last_polled=(netapi_getTimestamp()/cell_width) * cell_width + (cell_width-1);
113 printf(">timer group %s created. width = %d (ticks)\n", name, cell_width);
114 return (NETAPI_TIMER_GROUP_HANDLE_T) &temp_g;
115 }
117 //open a [global] timer group
118 NETAPI_TIMER_GROUP_HANDLE_T netapi_TimerGroupOpen(
119 NETAPI_T netHandle,
120 char * name,
121 NETAPI_TIMER_CB_T cb,
122 int *pErr)
123 {
124 printf(">timer group open not implemented \n");
126 }
128 //start an individual timer
129 NETAPI_TIMER_T netapi_TimerGroupStartTimer(
130 NETAPI_TIMER_GROUP_HANDLE_T th,
131 void * cookie,
132 uint64_t offs2fire, //offset in group ticks
133 int * pErr)
134 {
135 TIM_T * timer_obj;
136 unsigned long long ct= netapi_getTimestamp() + offs2fire* ((TIMER_GROUP_T*) th)->cell_width;
137 int cell;
138 *pErr=0;
140 //find cell where to insert
141 cell = our_hash(ct,((TIMER_GROUP_T*) th)->n_cells , ((TIMER_GROUP_T*) th)->cell_width);
143 //get object and insert into this cell
144 timer_obj =tim_set(
145 &((TIMER_GROUP_T*) th)->cells[cell],
146 &((TIMER_GROUP_T*) th)->free ,
147 ct,
148 cookie,
149 pErr);
150 if (!timer_obj) {return NULL;}
151 printf(">timer: setting timer %x for %lld ticks -> hased to cell %d\n",cookie, ct,cell);
152 return (NETAPI_TIMER_T) timer_obj;
153 }
155 //Cancel a timer
156 void netapi_TimerGroupCancel(
157 NETAPI_TIMER_GROUP_HANDLE_T th,
158 NETAPI_TIMER_T timerId,
159 int *pErr)
160 {
161 tim_cancel((TIM_T *) timerId, pErr);
162 }
164 //close an opened timer group
165 void netapi_TimerGroupClose(
166 NETAPI_TIMER_GROUP_HANDLE_T th,
167 int *pErr){}
169 //delete atimer group
170 void netapi_TimerGroupDelete(
171 NETAPI_TIMER_GROUP_HANDLE_T th,
172 int *pErr) {printf(">timer group delete not implemented\n");}
174 //extract netapi handle from timer group handle
175 NETAPI_T netap_TimerGroupGetNH( NETAPI_TIMER_GROUP_HANDLE_T th) { return ((TIMER_GROUP_T*) th)->h; }
178 //-----for timer debuggingi-------
179 struct
180 {
181 //last poll stats
182 int n_tot;
183 int c_seen;
185 int max_c_seen;
186 int max_n_tot;
188 } timer_poll_stats;
189 void dump_poll_stats(void)
190 {
191 printf("debug timer poll> n_tot=%d c_seen=%d mnt=%d mcs=%d\n",
192 timer_poll_stats.n_tot, timer_poll_stats.c_seen,
193 timer_poll_stats.max_n_tot, timer_poll_stats.max_c_seen);
194 }
195 //-------end timer debugging----
197 //poll a specific timer group
198 int netapi_TimerGroupPoll(NETAPI_TIMER_GROUP_HANDLE_T th, int maxTimers)
199 {
200 unsigned long long ct= netapi_getTimestamp();
201 unsigned long long i;
202 int cell;
203 TIM_LIST_T res;
204 int n;
205 int n_tot=0;
206 int c_seen=0;
208 for(i=((TIMER_GROUP_T*) th)->last_polled; (i<= ct) && (n_tot<maxTimers); )
209 {
210 cell = our_hash(i,((TIMER_GROUP_T*) th)->n_cells , ((TIMER_GROUP_T*) th)->cell_width);
211 tim_return_fired_list(&((TIMER_GROUP_T*) th)->cells[cell],
212 &res,
213 &((TIMER_GROUP_T*) th)->free,
214 i,
215 &n);
216 if (n)
217 {
218 ((TIMER_GROUP_T*) th)->cb(th, n, (NETAPI_TIMER_LIST_T) &res, ct);
219 tim_return_free(&((TIMER_GROUP_T*) th)->free,&res,n);
220 n_tot+=n;
221 }
222 i += ((TIMER_GROUP_T*) th)->cell_width;
223 c_seen+=1;
224 }
225 ((TIMER_GROUP_T*) th)->last_polled = i;
226 timer_poll_stats.n_tot = n_tot;
227 timer_poll_stats.c_seen = c_seen;
228 if (n_tot > timer_poll_stats.max_n_tot) timer_poll_stats.max_n_tot = n_tot;
229 if (c_seen > timer_poll_stats.max_c_seen) timer_poll_stats.max_c_seen = c_seen;
230 return n_tot;
231 }
233 //poll all timers
234 int netapi_TimerGroupPollAll(NETAPI_T nh, NETAPI_TIMER_FILTER_T f, int maxTimers)
235 {
236 //todo: use filters and poll global, local lists in nh
237 if (temp_g.h)
238 netapi_TimerGroupPoll(&temp_g, maxTimers);
239 return 0;
240 }