Go to the documentation of this file.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
00034 #include "../../mem/shm_mem.h"
00035 #include "../../timer.h"
00036 #include "dlg_timer.h"
00037
00039 struct dlg_timer *d_timer = 0;
00041 dlg_timer_handler timer_hdl = 0;
00042
00043
00051 int init_dlg_timer(dlg_timer_handler hdl)
00052 {
00053 d_timer = (struct dlg_timer*)shm_malloc(sizeof(struct dlg_timer));
00054 if (d_timer==0) {
00055 LM_ERR("no more shm mem\n");
00056 return -1;
00057 }
00058 memset( d_timer, 0, sizeof(struct dlg_timer) );
00059
00060 d_timer->first.next = d_timer->first.prev = &(d_timer->first);
00061
00062 d_timer->lock = lock_alloc();
00063 if (d_timer->lock==0) {
00064 LM_ERR("failed to alloc lock\n");
00065 goto error0;
00066 }
00067
00068 if (lock_init(d_timer->lock)==0) {
00069 LM_ERR("failed to init lock\n");
00070 goto error1;
00071 }
00072
00073 timer_hdl = hdl;
00074 return 0;
00075 error1:
00076 lock_dealloc(d_timer->lock);
00077 error0:
00078 shm_free(d_timer);
00079 d_timer = 0;
00080 return -1;
00081 }
00082
00083
00087 void destroy_dlg_timer(void)
00088 {
00089 if (d_timer==0)
00090 return;
00091
00092 lock_destroy(d_timer->lock);
00093 lock_dealloc(d_timer->lock);
00094
00095 shm_free(d_timer);
00096 d_timer = 0;
00097 }
00098
00099
00105 static inline void insert_dialog_timer_unsafe(struct dlg_tl *tl)
00106 {
00107 struct dlg_tl* ptr;
00108
00109
00110 for(ptr = d_timer->first.prev; ptr != &d_timer->first ; ptr = ptr->prev) {
00111 if ( ptr->timeout <= tl->timeout )
00112 break;
00113 }
00114
00115 LM_DBG("inserting %p for %d\n", tl,tl->timeout);
00116 tl->prev = ptr;
00117 tl->next = ptr->next;
00118 tl->prev->next = tl;
00119 tl->next->prev = tl;
00120 }
00121
00122
00129 int insert_dlg_timer(struct dlg_tl *tl, int interval)
00130 {
00131 lock_get( d_timer->lock);
00132
00133 if (tl->next!=0 || tl->prev!=0) {
00134 LM_CRIT("Trying to insert a bogus dlg tl=%p tl->next=%p tl->prev=%p\n",
00135 tl, tl->next, tl->prev);
00136 lock_release( d_timer->lock);
00137 return -1;
00138 }
00139 tl->timeout = get_ticks()+interval;
00140 insert_dialog_timer_unsafe( tl );
00141
00142 lock_release( d_timer->lock);
00143
00144 return 0;
00145 }
00146
00147
00153 static inline void remove_dialog_timer_unsafe(struct dlg_tl *tl)
00154 {
00155 tl->prev->next = tl->next;
00156 tl->next->prev = tl->prev;
00157 }
00158
00159
00166 int remove_dialog_timer(struct dlg_tl *tl)
00167 {
00168 lock_get( d_timer->lock);
00169
00170 if (tl->prev==NULL && tl->timeout==0) {
00171 lock_release( d_timer->lock);
00172 return 1;
00173 }
00174
00175 if (tl->prev==NULL || tl->next==NULL) {
00176 LM_CRIT("bogus tl=%p tl->prev=%p tl->next=%p\n",
00177 tl, tl->prev, tl->next);
00178 lock_release( d_timer->lock);
00179 return -1;
00180 }
00181
00182 remove_dialog_timer_unsafe(tl);
00183 tl->next = NULL;
00184 tl->prev = NULL;
00185 tl->timeout = 0;
00186
00187 lock_release( d_timer->lock);
00188 return 0;
00189 }
00190
00191
00199 int update_dlg_timer(struct dlg_tl *tl, int timeout)
00200 {
00201 lock_get( d_timer->lock);
00202
00203 if (tl->next==0 || tl->prev==0) {
00204 LM_CRIT("Trying to update a bogus dlg tl=%p tl->next=%p tl->prev=%p\n",
00205 tl, tl->next, tl->prev);
00206 lock_release( d_timer->lock);
00207 return -1;
00208 }
00209 remove_dialog_timer_unsafe( tl );
00210 tl->timeout = get_ticks()+timeout;
00211 insert_dialog_timer_unsafe( tl );
00212
00213 lock_release( d_timer->lock);
00214 return 0;
00215 }
00216
00217
00223 static inline struct dlg_tl* get_expired_dlgs(unsigned int time)
00224 {
00225 struct dlg_tl *tl , *end, *ret;
00226
00227 lock_get( d_timer->lock);
00228
00229 if (d_timer->first.next==&(d_timer->first)
00230 || d_timer->first.next->timeout > time ) {
00231 lock_release( d_timer->lock);
00232 return 0;
00233 }
00234
00235 end = &d_timer->first;
00236 tl = d_timer->first.next;
00237 LM_DBG("start with tl=%p tl->prev=%p tl->next=%p (%d) at %d "
00238 "and end with end=%p end->prev=%p end->next=%p\n",
00239 tl,tl->prev,tl->next,tl->timeout,time,
00240 end,end->prev,end->next);
00241 while( tl!=end && tl->timeout <= time) {
00242 LM_DBG("getting tl=%p tl->prev=%p tl->next=%p with %d\n",
00243 tl,tl->prev,tl->next,tl->timeout);
00244 tl->prev = 0;
00245 tl->timeout = 0;
00246 tl=tl->next;
00247 }
00248 LM_DBG("end with tl=%p tl->prev=%p tl->next=%p and d_timer->first.next->prev=%p\n",
00249 tl,tl->prev,tl->next,d_timer->first.next->prev);
00250
00251 if (tl==end && d_timer->first.next->prev) {
00252 ret = 0;
00253 } else {
00254 ret = d_timer->first.next;
00255 tl->prev->next = 0;
00256 d_timer->first.next = tl;
00257 tl->prev = &d_timer->first;
00258 }
00259
00260 lock_release( d_timer->lock);
00261
00262 return ret;
00263 }
00264
00265
00272 void dlg_timer_routine(unsigned int ticks , void * attr)
00273 {
00274 struct dlg_tl *tl, *ctl;
00275
00276 tl = get_expired_dlgs( ticks );
00277
00278 while (tl) {
00279 ctl = tl;
00280 tl = tl->next;
00281 ctl->next = NULL;
00282 LM_DBG("tl=%p next=%p\n", ctl, tl);
00283 timer_hdl( ctl );
00284 }
00285 }