Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

timer_funcs.h

Go to the documentation of this file.
00001 /*
00002  * $Id: timer_funcs.h,v 1.2 2006/02/14 18:04:17 andrei Exp $
00003  *
00004  *
00005  * timer related functions (internal)
00006  *
00007  * Copyright (C) 2005 iptelorg GmbH
00008  *
00009  * This file is part of ser, a free SIP server.
00010  *
00011  * ser is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * For a license to use the ser software under conditions
00017  * other than those described here, or to purchase support for this
00018  * software, please contact iptel.org by e-mail at the following addresses:
00019  *    info@iptel.org
00020  *
00021  * ser is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  * GNU General Public License for more details.
00025  *
00026  * You should have received a copy of the GNU General Public License 
00027  * along with this program; if not, write to the Free Software 
00028  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00029  */
00030 /* History:
00031  * --------
00032  *  2005-07-27  complete re-design/re-implemnetation (andrei)
00033  */
00034 
00035 
00036 #ifndef timer_funcs_h
00037 #define timer_funcs_h
00038 
00039 #include "timer.h"
00040 
00041 
00042 struct timer_head{
00043         struct timer_ln* volatile next;
00044         struct timer_ln* volatile prev;
00045 };
00046 
00047 
00048 
00049 /* hierarchical timing wheel with 3 levels
00050  * Most timeouts should go in the first "wheel" (h0)
00051  * h0 will contain timers expiring from crt. time up to
00052  * crt. time + (1<<H0_BITS)/TICKS_HZ s and will use
00053  * (1<<H0_BITS)*sizeof(struct timer_head) bytes of memory, so arrange it
00054  * accordingly
00055  */
00056 
00057 #define H0_BITS 14
00058 #define H1_BITS  9 
00059 #define H2_BITS  (32-H1_BITS-H0_BITS)
00060 /* Uses ~280K on a 64 bits system and ~140K on a 32 bit system; for TICKS_HZ=10
00061  * holds ~ 30 min in the first hash/wheel and ~233h in the first two.
00062  * More perfomant arrangement: 16, 8, 8 (but eats 1 MB on a 64 bit system, and
00063  *  512K on a 32 bit one). For TICKS_HZ=10 it holds almost 2h in the
00064  *  first hash/wheel and ~460h in the first two.
00065  */
00066 
00067 #define H0_ENTRIES (1<<H0_BITS)
00068 #define H1_ENTRIES (1<<H1_BITS)
00069 #define H2_ENTRIES (1<<H2_BITS)
00070 
00071 #define H0_MASK (H0_ENTRIES-1)
00072 #define H1_MASK (H1_ENTRIES-1)
00073 #define H1_H0_MASK ((1<<(H0_BITS+H1_BITS))-1)
00074 
00075 
00076 struct timer_lists{
00077         struct timer_head  h0[H0_ENTRIES];
00078         struct timer_head  h1[H1_ENTRIES];
00079         struct timer_head  h2[H2_ENTRIES];
00080         struct timer_head  expired; /* list of expired entries */
00081 };
00082 
00083 extern struct timer_lists* timer_lst;
00084 
00085 
00086 #define _timer_init_list(head)  clist_init((head), next, prev)
00087 
00088 
00089 #define _timer_add_list(head, tl) \
00090         clist_append((head), (tl), next, prev)
00091 
00092 #define _timer_rm_list(tl) \
00093         clist_rm((tl), next, prev)
00094 
00095 #define timer_foreach(tl, head) clist_foreach((head), (tl), next)
00096 #define timer_foreach_safe(tl, tmp, head)       \
00097         clist_foreach_safe((head), (tl), (tmp), next)
00098 
00099 
00100 
00101 
00102 /* generic add timer entry to the timer lists function (see _timer_add)
00103  * tl->expire must be set previously, delta is the difference in ticks
00104  * from current time to the timer desired expire (should be tl->expire-*tick)
00105  * If you don't know delta, you probably want to call _timer_add instead.
00106  */
00107 static inline int _timer_dist_tl(struct timer_ln* tl, ticks_t delta)
00108 {
00109         if (delta<H0_ENTRIES){
00110                 if (delta==0){
00111                         LOG(L_WARN, "WARNING: timer: add_timeout: 0 expire timer added\n");
00112                         _timer_add_list(&timer_lst->expired, tl);
00113                 }else{
00114                         _timer_add_list( &timer_lst->h0[tl->expire & H0_MASK], tl);
00115                 }
00116         }else if (delta<(H0_ENTRIES*H1_ENTRIES)){
00117                 _timer_add_list(&timer_lst->h1[(tl->expire & H1_H0_MASK)>>H0_BITS],tl);
00118         }else{
00119                 _timer_add_list(&timer_lst->h2[tl->expire>>(H1_BITS+H0_BITS)], tl);
00120         }
00121         return 0;
00122 }
00123 
00124 
00125 
00126 #define _timer_mv_expire(h) \
00127         do{ \
00128                 if ((h)->next!=(struct timer_ln*)(h)){ \
00129                         clist_append_sublist(&timer_lst->expired, (h)->next, \
00130                                                                         (h)->prev, next, prev); \
00131                         _timer_init_list(h); \
00132                 } \
00133         }while(0)
00134 
00135 
00136 #if 1
00137 
00138 static inline void timer_redist(ticks_t t, struct timer_head *h)
00139 {
00140         struct timer_ln* tl;
00141         struct timer_ln* tmp;
00142         
00143         timer_foreach_safe(tl, tmp, h){
00144                 _timer_dist_tl(tl, tl->expire-t);
00145         }
00146         /* clear the current list */
00147         _timer_init_list(h);
00148 }
00149 
00150 static inline void timer_run(ticks_t t)
00151 {
00152         /* trust the compiler for optimizing */
00153         if ((t & H0_MASK)==0){              /*r1*/
00154                 if ((t & H1_H0_MASK)==0){        /*r2*/
00155                         timer_redist(t, &timer_lst->h2[t>>(H0_BITS+H1_BITS)]);
00156                 }
00157                 
00158                 timer_redist(t, &timer_lst->h1[(t & H1_H0_MASK)>>H0_BITS]);/*r2 >> H0*/
00159         }
00160         /*
00161         DBG("timer_run: ticks %u, expire h0[%u]\n",
00162                                                 (unsigned ) t, (unsigned)(t & H0_MASK));*/
00163         _timer_mv_expire(&timer_lst->h0[t & H0_MASK]);  /*r1*/
00164 }
00165 #else
00166 
00167 static inline void timer_lst_mv0(ticks_t t, struct timer_head* h)
00168 {
00169         struct timer_ln* tl;
00170         struct timer_ln* tmp;
00171         
00172         timer_foreach_safe(tl, tmp, h){
00173                         _timer_dist_tl(tl, &timer_lst->h0[tl->expire & H0_MASK]);
00174         }
00175         /* clear the current list */
00176         _timer_init_list(h);
00177 }
00178 
00179 static inline void timer_lst_mv1(ticks_t t, struct timer_head* h)
00180 {
00181         struct timer_ln* tl;
00182         struct timer_ln* tmp;
00183         
00184         timer_foreach_safe(tl, tmp, h){
00185                 if ((tl->expire & H0_MASK)==0) /* directly to h0 */
00186                         _timer_add_list(tl, &timer_lst->h0[tl->expire & H0_MASK]);
00187                 else  /* to h1 */
00188                         _timer_add_list(tl, 
00189                                                 &timer_lst->h1[(tl->expire & H1_H0_MASK)>>H0_BITS]);
00190         }
00191         /* clear the current list */
00192         _timer_init_list(h);
00193 }
00194 
00195 
00196 /* possible faster version */
00197 static inline void timer_run(ticks_t t)
00198 {
00199         /* trust the compiler for optimizing */
00200         if ((t & H0_MASK)==0){              /*r1*/
00201                 if ((t & H1_H0_MASK)==0)        /*r2*/
00202                         /* just move the list "down" to hash1 */
00203                         timer_lst_mv1(&timer_lst->h2[t>>(H0_BITS+H1_BITS)]); 
00204                 /* move "down" to hash0 */
00205                 timer_lst_mv0(&timer_lst->h1[(t & H1_H0_MASK)>>H0_BITS]);
00206         }
00207         _timer_mv_expire(t, &timer_lst->h0[t & H0_MASK]);  /*r1*/
00208 }
00209 #endif
00210 
00211 
00212 
00213 #endif

Generated on Thu Sep 9 04:16:06 2010 for SIPExpressRouter by  doxygen 1.3.9.1