00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "timer.h"
00039 #include "timer_funcs.h"
00040 #include "dprint.h"
00041 #include "tcp_conn.h"
00042 #include "mem/mem.h"
00043 #include "compiler_opt.h"
00044
00045 #include "local_timer.h"
00046
00047
00048
00049
00050
00051 int init_local_timer(struct local_timer *t, ticks_t crt_ticks)
00052 {
00053 int r;
00054
00055
00056 memset(t, 0, sizeof(*t));
00057 t->prev_ticks=crt_ticks;
00058
00059 for (r=0; r<H0_ENTRIES; r++)
00060 _timer_init_list(&t->timer_lst.h0[r]);
00061 for (r=0; r<H1_ENTRIES; r++)
00062 _timer_init_list(&t->timer_lst.h1[r]);
00063 for (r=0; r<H2_ENTRIES; r++)
00064 _timer_init_list(&t->timer_lst.h2[r]);
00065 _timer_init_list(&t->timer_lst.expired);
00066 DBG("init_local_timer: timer_list between %p and %p\n",
00067 &t->timer_lst.h0[0], &t->timer_lst.h2[H2_ENTRIES]);
00068 return 0;
00069 }
00070
00071
00072
00073 void destroy_local_timer(struct local_timer* lt)
00074 {
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084 static inline int _local_timer_dist_tl(struct local_timer* h,
00085 struct timer_ln* tl, ticks_t delta)
00086 {
00087 if (likely(delta<H0_ENTRIES)){
00088 if (unlikely(delta==0)){
00089 LOG(L_WARN, "WARNING: local_timer: add_timeout: 0 expire timer"
00090 " added\n");
00091 _timer_add_list(&h->timer_lst.expired, tl);
00092 }else{
00093 _timer_add_list( &h->timer_lst.h0[tl->expire & H0_MASK], tl);
00094 }
00095 }else if (likely(delta<(H0_ENTRIES*H1_ENTRIES))){
00096 _timer_add_list(&h->timer_lst.h1[(tl->expire & H1_H0_MASK)>>H0_BITS],
00097 tl);
00098 }else{
00099 _timer_add_list(&h->timer_lst.h2[tl->expire>>(H1_BITS+H0_BITS)], tl);
00100 }
00101 return 0;
00102 }
00103
00104
00105
00106 static inline void local_timer_redist(struct local_timer* l,
00107 ticks_t t, struct timer_head *h)
00108 {
00109 struct timer_ln* tl;
00110 struct timer_ln* tmp;
00111
00112 timer_foreach_safe(tl, tmp, h){
00113 _local_timer_dist_tl(l, tl, tl->expire-t);
00114 }
00115
00116 _timer_init_list(h);
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126 static inline int _local_timer_add(struct local_timer *h, ticks_t t,
00127 struct timer_ln* tl)
00128 {
00129 ticks_t delta;
00130
00131 delta=tl->initial_timeout;
00132 tl->expire=t+delta;
00133 return _local_timer_dist_tl(h, tl, delta);
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 int local_timer_add(struct local_timer* h, struct timer_ln* tl, ticks_t delta,
00146 ticks_t crt_ticks)
00147 {
00148 int ret;
00149
00150 if (unlikely(tl->flags & F_TIMER_ACTIVE)){
00151 DBG("timer_add called on an active timer %p (%p, %p),"
00152 " flags %x\n", tl, tl->next, tl->prev, tl->flags);
00153 ret=-1;
00154 goto error;
00155 }
00156 tl->initial_timeout=delta;
00157 if (unlikely((tl->next!=0) || (tl->prev!=0))){
00158 LOG(L_CRIT, "BUG: tcp_timer_add: called with linked timer:"
00159 " %p (%p, %p)\n", tl, tl->next, tl->prev);
00160 ret=-1;
00161 goto error;
00162 }
00163 tl->flags|=F_TIMER_ACTIVE;
00164 ret=_local_timer_add(h, crt_ticks, tl);
00165 error:
00166 return ret;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void local_timer_del(struct local_timer* h, struct timer_ln* tl)
00178 {
00179
00180 if (unlikely(!(tl->flags & F_TIMER_ACTIVE))){
00181 DBG("timer_del called on an inactive timer %p (%p, %p),"
00182 " flags %x\n", tl, tl->next, tl->prev, tl->flags);
00183 return;
00184 }
00185 if (likely((tl->next!=0)&&(tl->prev!=0))){
00186 _timer_rm_list(tl);
00187 tl->next=tl->prev=0;
00188 }else{
00189 DBG("timer_del: (f) timer %p (%p, %p) flags %x "
00190 "already detached\n",
00191 tl, tl->next, tl->prev, tl->flags);
00192 }
00193 }
00194
00195
00196
00197
00198 inline static void local_timer_list_expire(struct local_timer* l,
00199 ticks_t t, struct timer_head* h)
00200 {
00201 struct timer_ln * tl;
00202 ticks_t ret;
00203
00204
00205
00206
00207 while(h->next!=(struct timer_ln*)h){
00208 tl=h->next;
00209 _timer_rm_list(tl);
00210 tl->next=tl->prev=0;
00211
00212 ret=tl->f(t, tl, tl->data);
00213 if (ret!=0){
00214
00215 if (ret!=(ticks_t)-1)
00216 tl->initial_timeout=ret;
00217 _local_timer_add(l, t, tl);
00218 }
00219 }
00220 }
00221
00222
00223
00224
00225 static inline void local_timer_expire(struct local_timer* h, ticks_t t)
00226 {
00227
00228 if (unlikely((t & H0_MASK)==0)){
00229 if (unlikely((t & H1_H0_MASK)==0)){
00230 local_timer_redist(h, t, &h->timer_lst.h2[t>>(H0_BITS+H1_BITS)]);
00231 }
00232
00233 local_timer_redist(h, t, &h->timer_lst.h1[(t & H1_H0_MASK)>>H0_BITS]);
00234
00235 }
00236
00237
00238 local_timer_list_expire(h, t, &h->timer_lst.h0[t & H0_MASK]);
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 void local_timer_run(struct local_timer* lt, ticks_t saved_ticks)
00248 {
00249
00250
00251 if (unlikely(lt->prev_ticks>=saved_ticks)){
00252 LOG(L_CRIT, "BUG: local_timer: backwards or still time\n");
00253
00254 lt->prev_ticks=saved_ticks-1;
00255 return;
00256 }
00257
00258
00259 for (lt->prev_ticks=lt->prev_ticks+1; lt->prev_ticks!=saved_ticks;
00260 lt->prev_ticks++)
00261 local_timer_expire(lt, lt->prev_ticks);
00262 local_timer_expire(lt, lt->prev_ticks);
00263 local_timer_list_expire(lt, saved_ticks, <->timer_lst.expired);
00264
00265
00266
00267 }
00268