modules/tm/timer.c

Go to the documentation of this file.
00001 /*
00002  * $Id: timer.c 5490 2009-01-20 16:11:14Z henningw $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  * Copyright (C) 2007 Voice Sistem SRL
00006  *
00007  * This file is part of Kamailio, a free SIP server.
00008  *
00009  * Kamailio is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * Kamailio is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * --------
00025  *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
00026  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
00027  *              timer_link.payload removed (bogdan)
00028  *  2007-02-02  retransmission timers have milliseconds resolution;
00029  *              adde faster timers (shortcuts based on timeout) (bogdan)
00030  */
00031 
00032 
00033 
00034 /*! \file
00035  * \brief TM :: Transaction timers
00036  *
00037  * \ingroup tm
00038  * - Module: \ref tm
00039  * - \ref TmTimers
00040 
00041  * \page TmTimers TM :: Implementation of timers
00042   timer.c is where we implement TM timers. It has been designed
00043   for high performance using some techniques of which timer users
00044   need to be aware.
00045 
00046    One technique is "fixed-timer-length". We maintain separate 
00047    timer lists, all of them include elements of the same time
00048    to fire. That allows *appending* new events to the list as
00049    opposed to inserting them by time, which is costly due to
00050    searching time spent in a mutex. The performance benefit is
00051    noticeable. The limitation is you need a new timer list for
00052    each new timer length.
00053 
00054    Another technique is the timer process slices off expired elements
00055    from the list in a mutex, but executes the timer after the mutex
00056    is left. That saves time greatly as whichever process wants to
00057    add/remove a timer, it does not have to wait until the current
00058    list is processed. However, be aware the timers may hit in a delayed
00059    manner; you have no guarantee in your process that after resetting a timer, 
00060    it will no more hit. It might have been removed by timer process,
00061     and is waiting to be executed.  The following example shows it:
00062 \code
00063 
00064          PROCESS1          TIMER PROCESS
00065 
00066    0.                      timer hits, it is removed from queue and
00067                            about to be executed
00068    1. process1 decides to
00069       reset the timer 
00070    2.                      timer is executed now
00071    3. if the process1 naively
00072       thinks the timer could not 
00073       have been executed after 
00074       resetting the timer, it is
00075       WRONG -- it was (step 2.)
00076 
00077 \endcode
00078    So be careful when writing the timer handlers. Currently defined timers 
00079    don't hurt if they hit delayed, I hope at least. Retransmission timer 
00080    may results in a useless retransmission -- not too bad. FR timer not too
00081    bad either as timer processing uses a REPLY mutex making it safe to other
00082    processing affecting transaction state. Wait timer not bad either -- processes
00083    putting a transaction on wait don't do anything with it anymore.
00084 
00085       Example when it does not hurt:
00086 \code
00087 
00088          P1                TIMER
00089    0.                      RETR timer removed from list and
00090                            scheduled for execution
00091    1. 200/BYE received->
00092       reset RETR, put_on_wait
00093    2.                      RETR timer executed -- too late but it does
00094                            not hurt
00095    3.                      WAIT handler executed
00096 \endcode
00097 
00098    The rule of thumb is don't touch data you put under a timer. Create data,
00099     put them under a timer, and let them live until they are safely destroyed from
00100     wait/delete timer.  The only safe place to manipulate the data is 
00101     from timer process in which delayed timers cannot hit (all timers are
00102     processed sequentially).
00103 
00104    A "bad example" -- rewriting content of retransmission buffer
00105    in an unprotected way is bad because a delayed retransmission timer might 
00106    hit. Thats why our reply retransmission procedure is enclosed in 
00107    a REPLY_LOCK.
00108 
00109 */
00110 
00111 
00112 #include "config.h"
00113 #include "h_table.h"
00114 #include "timer.h"
00115 #include "../../dprint.h"
00116 #include "lock.h"
00117 
00118 #include "../../hash_func.h"
00119 #include "../../dprint.h"
00120 #include "../../config.h"
00121 #include "../../parser/parser_f.h"
00122 #include "../../ut.h"
00123 #include "t_funcs.h"
00124 #include "t_reply.h"
00125 #include "t_cancel.h"
00126 
00127 
00128 static struct timer_table *timertable=0;
00129 static struct timer detached_timer; /* just to have a value to compare with*/
00130 
00131 #define DETACHED_LIST (&detached_timer)
00132 
00133 #define is_in_timer_list2(_tl) ( (_tl)->timer_list &&  \
00134                            ((_tl)->timer_list!=DETACHED_LIST) )
00135 
00136 
00137 
00138 int timer_group[NR_OF_TIMER_LISTS] =
00139 {
00140    TG_FR, TG_FR,
00141    TG_WT,
00142    TG_DEL,
00143    TG_RT, TG_RT, TG_RT, TG_RT
00144 };
00145 
00146 /* default values of timeouts for all the timer list
00147    (see timer.h for enumeration of timer lists)
00148 */
00149 unsigned int timer_id2timeout[NR_OF_TIMER_LISTS] = {
00150    FR_TIME_OUT,      /* FR_TIMER_LIST */
00151    INV_FR_TIME_OUT,  /* FR_INV_TIMER_LIST */
00152    WT_TIME_OUT,      /* WT_TIMER_LIST */
00153    DEL_TIME_OUT,     /* DELETE_LIST */
00154    RETR_T1,          /* RT_T1_TO_1 */
00155    0,                /* RT_T1_TO_2 */
00156    0,                /* RT_T1_TO_3 */
00157    RETR_T2        /* RT_T2 */
00158                   /* NR_OF_TIMER_LISTS */
00159 };
00160 
00161 #define UTIME_TYPE 1
00162 
00163 static unsigned int timer_id2type[NR_OF_TIMER_LISTS] = {
00164    0,             /* FR_TIMER_LIST */
00165    0,             /* FR_INV_TIMER_LIST */
00166    0,             /* WT_TIMER_LIST */
00167    0,             /* DELETE_LIST */
00168    UTIME_TYPE,    /* RT_T1_TO_1 */
00169    UTIME_TYPE,    /* RT_T1_TO_2 */
00170    UTIME_TYPE,    /* RT_T1_TO_3 */
00171    UTIME_TYPE     /* RT_T2 */
00172                /* NR_OF_TIMER_LISTS */
00173 };
00174 
00175 
00176 /******************** handlers ***************************/
00177 
00178 
00179 static void unlink_timers( struct cell *t );
00180 
00181 static void delete_cell( struct cell *p_cell, int unlock )
00182 {
00183 #ifdef EXTRA_DEBUG
00184    int i;
00185 #endif
00186 
00187    /* there may still be FR/RETR timers, which have been reset
00188       (i.e., time_out==TIMER_DELETED) but are stilled linked to
00189       timer lists and must be removed from there before the
00190       structures are released
00191    */
00192    unlink_timers( p_cell );
00193 
00194 #ifdef EXTRA_DEBUG
00195    if (is_in_timer_list2(& p_cell->wait_tl )) {
00196       LM_ERR("transaction %p scheduled for deletion and still on WAIT,"
00197             " timeout=%lld\n",p_cell, p_cell->wait_tl.time_out);
00198       abort();
00199    }
00200    if (is_in_timer_list2(& p_cell->uas.response.retr_timer )) {
00201       LM_ERR("transaction %p scheduled for deletion and still on RETR (rep),"
00202          "timeout=%lld\n",p_cell, p_cell->uas.response.retr_timer.time_out);
00203       abort();
00204    }
00205    if (is_in_timer_list2(& p_cell->uas.response.fr_timer )) {
00206       LM_ERR("transaction %p scheduled for deletion and still on FR (rep),"
00207          " timeout=%lld\n", p_cell,p_cell->uas.response.fr_timer.time_out);
00208       abort();
00209    }
00210    for (i=0; i<p_cell->nr_of_outgoings; i++) {
00211       if (is_in_timer_list2(& p_cell->uac[i].request.retr_timer)) {
00212          LM_ERR("transaction %p scheduled for deletion and still on RETR "
00213             "(req %d), timeout %lld\n", p_cell, i,
00214             p_cell->uac[i].request.retr_timer.time_out);
00215          abort();
00216       }
00217       if (is_in_timer_list2(& p_cell->uac[i].request.fr_timer)) {
00218          LM_ERR("transaction %p scheduled for deletion and"
00219             " still on FR (req %d), timeout %lld\n", p_cell, i,
00220             p_cell->uac[i].request.fr_timer.time_out);
00221          abort();
00222       }
00223       if (is_in_timer_list2(& p_cell->uac[i].local_cancel.retr_timer)) {
00224          LM_ERR("transaction %p scheduled for deletion and"
00225             " still on RETR/cancel (req %d), timeout %lld\n", p_cell, i,
00226             p_cell->uac[i].request.retr_timer.time_out);
00227          abort();
00228       }
00229       if (is_in_timer_list2(& p_cell->uac[i].local_cancel.fr_timer)) {
00230          LM_ERR("transaction %p scheduled for deletion and"
00231             " still on FR/cancel (req %d), timeout %lld\n", p_cell, i,
00232             p_cell->uac[i].request.fr_timer.time_out);
00233          abort();
00234       }
00235    }
00236    /* reset_retr_timers( hash__XX_table, p_cell ); */
00237 #endif
00238    /* still in use ... don't delete */
00239    if ( IS_REFFED_UNSAFE(p_cell) ) {
00240       LM_DBG("delete_cell %p: can't delete -- still reffed (%d)\n",
00241          p_cell, p_cell->ref_count);
00242       if (unlock) UNLOCK_HASH(p_cell->hash_index);
00243       /* set to NULL so that set_timer will work */
00244       p_cell->dele_tl.timer_list= NULL;
00245       /* it's added to del list for future del */
00246       set_timer( &(p_cell->dele_tl), DELETE_LIST, 0 );
00247    } else {
00248       if (unlock) UNLOCK_HASH(p_cell->hash_index);
00249       LM_DBG("delete transaction %p\n", p_cell );
00250       free_cell( p_cell );
00251    }
00252 }
00253 
00254 static void fake_reply(struct cell *t, int branch, int code )
00255 {
00256    branch_bm_t cancel_bitmap;
00257    short do_cancel_branch;
00258    enum rps reply_status;
00259 
00260    do_cancel_branch = is_invite(t) && should_cancel_branch(t, branch);
00261 
00262    cancel_bitmap=do_cancel_branch ? 1<<branch : 0;
00263    if ( is_local(t) ) {
00264       reply_status=local_reply( t, FAKED_REPLY, branch, 
00265                  code, &cancel_bitmap );
00266       if (reply_status==RPS_COMPLETED) {
00267          put_on_wait(t);
00268       }
00269    } else {
00270       reply_status=relay_reply( t, FAKED_REPLY, branch, code,
00271          &cancel_bitmap );
00272    }
00273    /* now when out-of-lock do the cancel I/O */
00274    if (do_cancel_branch) cancel_branch(t, branch );
00275    /* it's cleaned up on error; if no error occurred and transaction
00276       completed regularly, I have to clean-up myself
00277    */
00278 }
00279 
00280 
00281 
00282 
00283 
00284 inline static void retransmission_handler( struct timer_link *retr_tl )
00285 {
00286    struct retr_buf* r_buf ;
00287    enum lists id;
00288 
00289    r_buf = get_retr_timer_payload(retr_tl);
00290 #ifdef EXTRA_DEBUG
00291    if (r_buf->my_T->damocles) {
00292       LM_ERR("transaction %p scheduled for deletion and"
00293          " called from RETR timer\n",r_buf->my_T);
00294       abort();
00295    }  
00296 #endif
00297 
00298    /* the transaction is already removed from RETRANSMISSION_LIST by timer*/
00299    /* retransmission */
00300    if ( r_buf->activ_type==TYPE_LOCAL_CANCEL 
00301       || r_buf->activ_type==TYPE_REQUEST ) {
00302          LM_DBG("retransmission_handler : request resending"
00303             " (t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer.s);
00304          if (SEND_BUFFER( r_buf )==-1) {
00305             reset_timer( &r_buf->fr_timer );
00306             fake_reply(r_buf->my_T, r_buf->branch, 503 );
00307             return;
00308          }
00309    } else {
00310          LM_DBG("retransmission_handler : reply resending "
00311             "(t=%p, %.9s ... )\n", r_buf->my_T, r_buf->buffer.s);
00312          t_retransmit_reply(r_buf->my_T);
00313    }
00314 
00315    id = r_buf->retr_list;
00316    r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
00317    
00318    retr_tl->timer_list= NULL; /* set to NULL so that set_timer will work */
00319    set_timer( retr_tl, id < RT_T2 ? id + 1 : RT_T2, 0 );
00320 
00321    LM_DBG("retransmission_handler : done\n");
00322 }
00323 
00324 
00325 
00326 
00327 inline static void final_response_handler( struct timer_link *fr_tl )
00328 {
00329    struct retr_buf* r_buf;
00330    struct cell *t;
00331 
00332    if (fr_tl==0){
00333       /* or BUG?, ignoring it for now */
00334       LM_CRIT("final_response_handler(0) called\n");
00335       return;
00336    }
00337    r_buf = get_fr_timer_payload(fr_tl);
00338    t=r_buf->my_T;
00339 
00340 #  ifdef EXTRA_DEBUG
00341    if (t->damocles) 
00342    {
00343       LM_ERR("transaction %p scheduled for deletion and"
00344          " called from FR timer\n",r_buf->my_T);
00345       abort();
00346    }
00347 #  endif
00348 
00349    reset_timer(  &(r_buf->retr_timer) );
00350 
00351    /* the transaction is already removed from FR_LIST by the timer */
00352 
00353    /* FR for local cancels.... */
00354    if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
00355    {
00356       LM_DBG("stop retr for Local Cancel\n");
00357       return;
00358    }
00359 
00360    /* FR for replies (negative INVITE replies) */
00361    if (r_buf->activ_type>0) {
00362 #     ifdef EXTRA_DEBUG
00363       if (t->uas.request->REQ_METHOD!=METHOD_INVITE
00364          || t->uas.status < 200 ) {
00365          LM_ERR("unknown type reply buffer\n");
00366          abort();
00367       }
00368 #     endif
00369       put_on_wait( t );
00370       return;
00371    };
00372 
00373    /* lock reply processing to determine how to proceed reliably */
00374    LOCK_REPLIES( t );
00375    LM_DBG("stop retr. and send CANCEL (%p)\n", t);
00376    fake_reply(t, r_buf->branch, 408 );
00377 
00378    LM_DBG("done\n");
00379 }
00380 
00381 
00382 
00383 void cleanup_localcancel_timers( struct cell *t )
00384 {
00385    int i;
00386    for (i=0; i<t->nr_of_outgoings; i++ )  {
00387       reset_timer(  &t->uac[i].local_cancel.retr_timer );
00388       reset_timer(  &t->uac[i].local_cancel.fr_timer );
00389    }
00390 }
00391 
00392 
00393 inline static void wait_handler( struct timer_link *wait_tl )
00394 {
00395    struct cell *p_cell;
00396 
00397    p_cell = get_wait_timer_payload( wait_tl );
00398 #ifdef EXTRA_DEBUG
00399    if (p_cell->damocles) {
00400       LM_ERR("transaction %p scheduled for deletion and"
00401          " called from WAIT timer\n",p_cell);
00402       abort();
00403    }  
00404    LM_DBG("WAIT timer hit\n");
00405 #endif
00406 
00407    /* stop cancel timers if any running */
00408    if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
00409 
00410    /* the transaction is already removed from WT_LIST by the timer */
00411    /* remove the cell from the hash table */
00412    LM_DBG("removing %p from table \n", p_cell );
00413    LOCK_HASH( p_cell->hash_index );
00414    remove_from_hash_table_unsafe(  p_cell );
00415    /* jku: no more here -- we do it when we put a transaction on wait */
00416 #ifdef EXTRA_DEBUG
00417    p_cell->damocles = 1;
00418 #endif
00419    /* delete (returns with UNLOCK-ed_HASH) */
00420    delete_cell( p_cell, 1 /* unlock on return */ );
00421    LM_DBG("done\n");
00422 }
00423 
00424 
00425 
00426 inline static void delete_handler( struct timer_link *dele_tl )
00427 {
00428    struct cell *p_cell;
00429 
00430    p_cell = get_dele_timer_payload( dele_tl );
00431    LM_DBG("removing %p \n", p_cell );
00432 #ifdef EXTRA_DEBUG
00433    if (p_cell->damocles==0) {
00434       LM_ERR("transaction %p not scheduled for deletion"
00435          " and called from DELETE timer\n",p_cell);
00436       abort();
00437    }  
00438 #endif
00439 
00440    /* we call delete now without any locking on hash/ref_count;
00441       we can do that because delete_handler is only entered after
00442       the delete timer was installed from wait_handler, which
00443       removed transaction from hash table and did not destroy it
00444       because some processes were using it; that means that the
00445       processes currently using the transaction can unref and no
00446       new processes can ref -- we can wait until ref_count is
00447       zero safely without locking
00448    */
00449    delete_cell( p_cell, 0 /* don't unlock on return */ );
00450    LM_DBG("done\n");
00451 }
00452 
00453 
00454 /***********************************************************/
00455 
00456 struct timer_table *get_timertable(void)
00457 {
00458    return timertable;
00459 }
00460 
00461 
00462 void unlink_timer_lists(void)
00463 {
00464    struct timer_link  *tl, *end, *tmp;
00465    enum lists i;
00466 
00467    if (timertable==0) return; /* nothing to do */
00468    /* remember the DELETE LIST */
00469    tl = timertable->timers[DELETE_LIST].first_tl.next_tl;
00470    end = & timertable->timers[DELETE_LIST].last_tl;
00471    /* unlink the timer lists */
00472    for( i=0; i<NR_OF_TIMER_LISTS ; i++ )
00473       reset_timer_list( i );
00474    LM_DBG("emptying DELETE list\n");
00475    /* deletes all cells from DELETE_LIST list 
00476       (they are no more accessible from entrys) */
00477    while (tl!=end) {
00478       tmp=tl->next_tl;
00479       free_cell( get_dele_timer_payload(tl) );
00480       tl=tmp;
00481    }
00482    
00483 }
00484 
00485 
00486 
00487 struct timer_table *tm_init_timers(void)
00488 {
00489    enum lists i;
00490 
00491    timertable=(struct timer_table *) shm_malloc(sizeof(struct timer_table));
00492    if (!timertable) {
00493       LM_ERR("no more share memory\n");
00494       goto error0;
00495    }
00496    memset(timertable, 0, sizeof (struct timer_table));
00497 
00498    /* check the timeout values */
00499    if ( timer_id2timeout[FR_TIMER_LIST]<MIN_TIMER_VALUE ) {
00500       LM_ERR("FR_TIMER must be at least %d\n",
00501          MIN_TIMER_VALUE);
00502       goto error0;
00503    }
00504 
00505    if ( timer_id2timeout[FR_INV_TIMER_LIST]<MIN_TIMER_VALUE ) {
00506       LM_ERR("FR_INV_TIMER must be at least %d\n",
00507          MIN_TIMER_VALUE);
00508       goto error0;
00509    }
00510 
00511    if ( timer_id2timeout[WT_TIMER_LIST]<MIN_TIMER_VALUE ) {
00512       LM_ERR("WT_TIMER must be at least %d\n",
00513          MIN_TIMER_VALUE);
00514       goto error0;
00515    }
00516 
00517    if ( timer_id2timeout[DELETE_LIST]<MIN_TIMER_VALUE ) {
00518       LM_ERR("DELETE_TIMER must be at least %d\n",
00519          MIN_TIMER_VALUE);
00520       goto error0;
00521    }
00522 
00523    if ( timer_id2timeout[RT_T2]<=timer_id2timeout[RT_T1_TO_1] ) {
00524       LM_ERR("T2 must be greater than T1\n");
00525       goto error0;
00526    }
00527 
00528    /* generate timeouts for retransmissions */
00529    timer_id2timeout[RT_T1_TO_1] *=1000;
00530    timer_id2timeout[RT_T2] *=1000;
00531 
00532    if ( (timer_id2timeout[RT_T1_TO_1]<<1) < timer_id2timeout[RT_T2] )
00533       timer_id2timeout[RT_T1_TO_2] = timer_id2timeout[RT_T1_TO_1]<<1;
00534    else
00535       timer_id2timeout[RT_T1_TO_2] = timer_id2timeout[RT_T2];
00536 
00537    if ( (timer_id2timeout[RT_T1_TO_1]<<2) < timer_id2timeout[RT_T2] )
00538       timer_id2timeout[RT_T1_TO_3] = timer_id2timeout[RT_T1_TO_1]<<2;
00539    else
00540       timer_id2timeout[RT_T1_TO_3] = timer_id2timeout[RT_T2];
00541 
00542 
00543    /* inits the timers*/
00544    for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
00545       init_timer_list( i );
00546 
00547    /* init. timer lists */
00548    timertable->timers[RT_T1_TO_1].id = RT_T1_TO_1;
00549    timertable->timers[RT_T1_TO_2].id = RT_T1_TO_2;
00550    timertable->timers[RT_T1_TO_3].id = RT_T1_TO_3;
00551    timertable->timers[RT_T2].id      = RT_T2;
00552    timertable->timers[FR_TIMER_LIST].id     = FR_TIMER_LIST; 
00553    timertable->timers[FR_INV_TIMER_LIST].id = FR_INV_TIMER_LIST;
00554    timertable->timers[WT_TIMER_LIST].id     = WT_TIMER_LIST;
00555    timertable->timers[DELETE_LIST].id       = DELETE_LIST;
00556 
00557    return timertable;
00558 
00559 error0:
00560    return 0;
00561 }
00562 
00563 void free_timer_table(void)
00564 {
00565    if (timertable)
00566       shm_free(timertable);
00567 }
00568 
00569 void reset_timer_list( enum lists list_id)
00570 {
00571    timertable->timers[list_id].first_tl.next_tl =
00572       &(timertable->timers[list_id].last_tl );
00573    timertable->timers[list_id].last_tl.prev_tl =
00574       &(timertable->timers[list_id].first_tl );
00575    timertable->timers[list_id].first_tl.prev_tl =
00576       timertable->timers[list_id].last_tl.next_tl = NULL;
00577    timertable->timers[list_id].last_tl.time_out = -1;
00578 }
00579 
00580 
00581 
00582 
00583 void init_timer_list( enum lists list_id)
00584 {
00585    reset_timer_list( list_id );
00586    init_timerlist_lock( list_id );
00587 }
00588 
00589 
00590 
00591 
00592 void print_timer_list( enum lists list_id)
00593 {
00594    struct timer* timer_list=&(timertable->timers[ list_id ]);
00595    struct timer_link *tl ;
00596 
00597    tl = timer_list->first_tl.next_tl;
00598    while (tl!=& timer_list->last_tl)
00599    {
00600       LM_DBG("[%d]: %p, next=%p \n",
00601          list_id, tl, tl->next_tl);
00602       tl = tl->next_tl;
00603    }
00604 }
00605 
00606 
00607 
00608 #ifdef TM_TIMER_DEBUG
00609 static void check_timer_list(enum lists list_id, char *txt )
00610 {
00611    struct timer* timer_list=&(timertable->timers[ list_id ]);
00612    struct timer_link *tl ;
00613    struct timer_link *tl1 ;
00614 
00615    if (list_id<0 || list_id>=NR_OF_TIMER_LISTS) {
00616          LM_CRIT("------- list [%d] bug [%s]\n",list_id, txt);
00617          abort();
00618    }
00619 
00620    tl = timer_list->last_tl.prev_tl;
00621    while (tl!=&timer_list->first_tl) {
00622       if (tl->prev_tl==0) {
00623          LM_CRIT("------- list [%d] prev_tl==0 [%s]\n",list_id, txt);
00624          abort();
00625       }
00626       tl = tl->prev_tl;
00627    }
00628 
00629    tl = timer_list->first_tl.next_tl;
00630    while (tl!=&timer_list->last_tl) {
00631       if (tl->next_tl==0) {
00632          LM_CRIT("------- list [%d] next_tl==0 [%s]\n",list_id, txt);
00633          abort();
00634       }
00635       tl = tl->next_tl;
00636    }
00637 
00638    tl = timer_list->first_tl.next_tl;
00639    while (tl!=&timer_list->last_tl) {
00640       if (tl->ld_tl==0) {
00641          LM_CRIT("------- list [%d] currupted - ld=0 [%s]\n",list_id, txt);
00642          abort();
00643       }
00644       if (tl->ld_tl->ld_tl!=tl) {
00645          LM_CRIT("------- list [%d] currupted - ld cycle broken [%s]\n",
00646             list_id, txt);
00647          abort();
00648       }
00649 
00650       if (tl->ld_tl!=tl) {
00651          tl1 = tl->next_tl;
00652          while(tl1!=tl->ld_tl) {
00653             if (tl1->ld_tl) {
00654                LM_CRIT("------- list [%d] currupted - ld!=0 inside "
00655                   "cycle [%s]\n", list_id, txt);
00656                abort();
00657             }
00658             tl1 = tl1->next_tl;
00659          }
00660       }
00661 
00662       tl = tl->ld_tl->next_tl;
00663    }
00664 }
00665 #endif
00666 
00667 
00668 static void remove_timer_unsafe(  struct timer_link* tl )
00669 {
00670 #ifdef EXTRA_DEBUG
00671    if (tl && is_in_timer_list2(tl) &&
00672       tl->timer_list->last_tl.prev_tl==0) {
00673       LM_CRIT("Oh no, zero link in trailing timer element\n");
00674       abort();
00675    };
00676 #endif
00677    if (is_in_timer_list2( tl )) {
00678 #ifdef EXTRA_DEBUG
00679       LM_DBG("unlinking timer: tl=%p, timeout=%lld, group=%d\n", 
00680          tl, tl->time_out, tl->tg);
00681 #endif
00682 #ifdef TM_TIMER_DEBUG
00683       check_timer_list( tl->timer_list->id, "before remove" );
00684 #endif
00685       if (tl->ld_tl && tl->ld_tl!=tl) {
00686          if (tl->time_out==tl->prev_tl->time_out) {
00687             tl->prev_tl->ld_tl = tl->ld_tl;
00688             tl->ld_tl->ld_tl = tl->prev_tl;
00689          } else {
00690             tl->next_tl->ld_tl = tl->ld_tl;
00691             tl->ld_tl->ld_tl = tl->next_tl;
00692          }
00693       }
00694       tl->prev_tl->next_tl = tl->next_tl;
00695       tl->next_tl->prev_tl = tl->prev_tl;
00696 #ifdef TM_TIMER_DEBUG
00697       check_timer_list( tl->timer_list->id, "after remove" );
00698 #endif
00699       tl->next_tl = 0;
00700       tl->prev_tl = 0;
00701       tl->ld_tl = 0;
00702       tl->timer_list = NULL;
00703    }
00704 }
00705 
00706 
00707 /* put a new cell into a list nr. list_id */
00708 static void insert_timer_unsafe( struct timer *timer_list,
00709                            struct timer_link *tl, utime_t time_out )
00710 {
00711    struct timer_link* ptr;
00712 
00713    tl->time_out = time_out;
00714    tl->timer_list = timer_list;
00715    tl->deleted = 0;
00716 
00717 #ifdef TM_TIMER_DEBUG
00718    check_timer_list( timer_list->id, "before insert" );
00719 #endif
00720    ptr = timer_list->last_tl.prev_tl;
00721    for( ; ptr != &timer_list->first_tl ; ptr = ptr->ld_tl->prev_tl) {
00722       if ( ptr->time_out<=time_out )
00723          break;
00724    }
00725 
00726    /* insert "tl" after "ptr" */
00727    tl->prev_tl = ptr;
00728    tl->next_tl = ptr->next_tl;
00729    tl->prev_tl->next_tl = tl;
00730    tl->next_tl->prev_tl = tl;
00731 
00732    if (tl->time_out==ptr->time_out) {
00733       tl->ld_tl = ptr->ld_tl;
00734       ptr->ld_tl = 0;
00735       tl->ld_tl->ld_tl = tl;
00736    } else {
00737       tl->ld_tl = tl;
00738    }
00739 #ifdef TM_TIMER_DEBUG
00740    check_timer_list( timer_list->id, "after insert" );
00741 #endif
00742 
00743    LM_DBG("[%d]: %p (%lld)\n",timer_list->id,
00744       tl,tl->time_out);
00745 }
00746 
00747 
00748 
00749 /* detach items passed by the time from timer list */
00750 static struct timer_link  *check_and_split_time_list( struct timer *timer_list,
00751       utime_t time )
00752 {
00753    struct timer_link *tl , *end, *ret;
00754 
00755 
00756    /* quick check whether it is worth entering the lock */
00757    if (timer_list->first_tl.next_tl==&timer_list->last_tl 
00758          || ( /* timer_list->first_tl.next_tl
00759             && */ timer_list->first_tl.next_tl->time_out > time) )
00760       return NULL;
00761 
00762    /* the entire timer list is locked now -- noone else can manipulate it */
00763    lock(timer_list->mutex);
00764 
00765 #ifdef TM_TIMER_DEBUG
00766    check_timer_list( timer_list->id, "before split" );
00767 #endif
00768    end = &timer_list->last_tl;
00769    tl = timer_list->first_tl.next_tl;
00770    while( tl!=end && tl->time_out <= time)
00771       tl=tl->ld_tl->next_tl;
00772 
00773    /* nothing to delete found */
00774    if (tl->prev_tl==&(timer_list->first_tl)) {
00775       ret = NULL;
00776    } else { /* we did find timers to be fired! */
00777       /* the detached list begins with current beginning */
00778       ret = timer_list->first_tl.next_tl;
00779       /* and we mark the end of the split list */
00780       tl->prev_tl->next_tl = NULL;
00781       /* the shortened list starts from where we suspended */
00782       timer_list->first_tl.next_tl = tl;
00783       tl->prev_tl = & timer_list->first_tl;
00784 
00785       for( tl=ret ; tl ; tl=tl->next_tl )
00786          tl->timer_list = DETACHED_LIST;
00787    }
00788 #ifdef TM_TIMER_DEBUG
00789    check_timer_list( timer_list->id, "after split" );
00790 #endif
00791 
00792 #ifdef EXTRA_DEBUG
00793    if (timer_list->last_tl.prev_tl==0) {
00794       LM_CRIT("Oh no, zero link in trailing timer element\n");
00795       abort();
00796    };
00797 #endif
00798 
00799    /* give the list lock away */
00800    unlock(timer_list->mutex);
00801 
00802    return ret;
00803 }
00804 
00805 
00806 
00807 /* stop timer
00808  * WARNING: a reset'ed timer will be lost forever
00809  *  (successive set_timer won't work unless you're lucky
00810  *   an catch the race condition, the idea here is there is no
00811  *   guarantee you can do anything after a timer_reset)*/
00812 void reset_timer( struct timer_link* tl )
00813 {
00814    /* disqualify this timer from execution by setting its time_out
00815       to zero; it will stay in timer-list until the timer process
00816       starts removing outdated elements; then it will remove it
00817       but not execute; there is a race condition, though -- see
00818       timer.c for more details
00819    */
00820    tl->deleted = 1;
00821 #ifdef EXTRA_DEBUG
00822    LM_DBG("(group %d, tl=%p)\n", tl->tg, tl );
00823 #endif
00824 }
00825 
00826 
00827 
00828 
00829 /* determine timer length and put on a correct timer list
00830  * WARNING: - don't try to use it to "move" a timer from one list
00831  *            to another, you'll run into races
00832  *          - reset_timer; set_timer might not work, a reset'ed timer
00833  *             has no set_timer guarantee, it might be lost;
00834  *             same for an expired timer: only it's handler can
00835  *             set it again, an external set_timer has no guarantee
00836  */
00837 void set_timer( struct timer_link *new_tl, enum lists list_id,
00838                                     utime_t* ext_timeout )
00839 {
00840    utime_t timeout;
00841    struct timer* list;
00842 
00843    if (list_id>=NR_OF_TIMER_LISTS) {
00844       LM_CRIT("unknown list: %d\n", list_id);
00845 #ifdef EXTRA_DEBUG
00846       abort();
00847 #endif
00848       return;
00849    }
00850 
00851    if (!ext_timeout) {
00852       timeout = timer_id2timeout[ list_id ];
00853    } else {
00854       timeout = *ext_timeout;
00855    }
00856    LM_DBG("relative timeout is %lld\n",timeout);
00857 
00858    list= &(timertable->timers[ list_id ]);
00859 
00860    lock(list->mutex);
00861    /* check first if we are on the "detached" timer_routine list,
00862     * if so do nothing, the timer is not valid anymore
00863     * (sideffect: reset_timer ; set_timer is not safe, a reseted timer
00864     *  might be lost, depending on this race condition ) */
00865    if (new_tl->timer_list==DETACHED_LIST){
00866       LM_CRIT("set_timer for %d list called on a \"detached\" "
00867          "timer -- ignoring: %p\n", list_id, new_tl);
00868       goto end;
00869    }
00870    /* make sure I'm not already on a list */
00871    remove_timer_unsafe( new_tl );
00872 
00873    insert_timer_unsafe( list, new_tl, timeout +
00874          ((timer_id2type[list_id]==UTIME_TYPE)?get_uticks():get_ticks()));
00875 end:
00876    unlock(list->mutex);
00877 }
00878 
00879 
00880 
00881 /* similar to set_timer, except it allows only one-time
00882    timer setting and all later attempts are ignored */
00883 void set_1timer( struct timer_link *new_tl, enum lists list_id,
00884                                     utime_t* ext_timeout )
00885 {
00886    utime_t timeout;
00887    struct timer* list;
00888 
00889 
00890    if (list_id>=NR_OF_TIMER_LISTS) {
00891       LM_CRIT("unknown list: %d\n", list_id);
00892 #ifdef EXTRA_DEBUG
00893       abort();
00894 #endif
00895       return;
00896    }
00897 
00898    if (!ext_timeout) {
00899       timeout = timer_id2timeout[ list_id ];
00900    } else {
00901       timeout = *ext_timeout;
00902    }
00903 
00904    list= &(timertable->timers[ list_id ]);
00905 
00906    lock(list->mutex);
00907    if (!new_tl->time_out) {
00908       insert_timer_unsafe( list, new_tl, timeout +
00909          ((timer_id2type[list_id]==UTIME_TYPE)?get_uticks():get_ticks()));
00910    }
00911    unlock(list->mutex);
00912 }
00913 
00914 
00915 
00916 /* should be called only from timer process context,
00917  * else it's unsafe */
00918 static void unlink_timers( struct cell *t )
00919 {
00920    int i;
00921    int remove_fr, remove_retr;
00922 
00923    remove_fr=0; remove_retr=0;
00924 
00925    /* first look if we need to remove timers and play with
00926       costly locks at all
00927 
00928        note that is_in_timer_list2 is unsafe but it does not
00929        hurt -- transaction is already dead (wait state) so that
00930        noone else will install a FR/RETR timer and it can only
00931        be removed from timer process itself -> it is safe to
00932        use it without any protection
00933    */
00934    if (is_in_timer_list2(&t->uas.response.fr_timer)) remove_fr=1; 
00935    else for (i=0; i<t->nr_of_outgoings; i++)
00936       if (is_in_timer_list2(&t->uac[i].request.fr_timer)
00937          || is_in_timer_list2(&t->uac[i].local_cancel.fr_timer)) {
00938             remove_fr=1;
00939             break;
00940       }
00941    if (is_in_timer_list2(&t->uas.response.retr_timer)) remove_retr=1; 
00942    else for (i=0; i<t->nr_of_outgoings; i++)
00943       if (is_in_timer_list2(&t->uac[i].request.retr_timer)
00944          || is_in_timer_list2(&t->uac[i].local_cancel.retr_timer)) {
00945             remove_retr=1;
00946             break;
00947       }
00948 
00949    /* do what we have to do....*/
00950    if (remove_retr) {
00951       /* RT_T1 lock is shared by all other RT timer
00952          lists -- we can safely lock just one
00953       */
00954       lock(timertable->timers[RT_T1_TO_1].mutex);
00955       remove_timer_unsafe(&t->uas.response.retr_timer);
00956       for (i=0; i<t->nr_of_outgoings; i++) {
00957          remove_timer_unsafe(&t->uac[i].request.retr_timer);
00958          remove_timer_unsafe(&t->uac[i].local_cancel.retr_timer);
00959       }
00960       unlock(timertable->timers[RT_T1_TO_1].mutex);
00961    }
00962    if (remove_fr) {
00963       /* FR lock is shared by all other FR timer
00964          lists -- we can safely lock just one
00965       */
00966       lock(timertable->timers[FR_TIMER_LIST].mutex);
00967       remove_timer_unsafe(&t->uas.response.fr_timer);
00968       for (i=0; i<t->nr_of_outgoings; i++) {
00969          remove_timer_unsafe(&t->uac[i].request.fr_timer);
00970          remove_timer_unsafe(&t->uac[i].local_cancel.fr_timer);
00971       }
00972       unlock(timertable->timers[FR_TIMER_LIST].mutex);
00973    }
00974 }
00975 
00976 
00977 
00978 
00979 #define run_handler_for_each( _tl , _handler ) \
00980    while ((_tl))\
00981    {\
00982       /* reset the timer list linkage */\
00983       tmp_tl = (_tl)->next_tl;\
00984       (_tl)->next_tl = (_tl)->prev_tl = 0;\
00985       LM_DBG("timer routine:%d,tl=%p next=%p, timeout=%lld\n",\
00986          id,(_tl),tmp_tl,(_tl)->time_out);\
00987       if ( !(_tl)->deleted ) \
00988          (_handler)( _tl );\
00989       (_tl) = tmp_tl;\
00990    }
00991 
00992 
00993 
00994 
00995 void timer_routine(unsigned int ticks , void * attr)
00996 {
00997    struct timer_link *tl, *tmp_tl;
00998    int                id;
00999 
01000    for( id=0 ; id<RT_T1_TO_1 ; id++ )
01001    {
01002       /* to waste as little time in lock as possible, detach list
01003          with expired items and process them after leaving the lock */
01004       tl=check_and_split_time_list( &timertable->timers[ id ], ticks);
01005       /* process items now */
01006       switch (id)
01007       {
01008          case FR_TIMER_LIST:
01009          case FR_INV_TIMER_LIST:
01010             run_handler_for_each(tl,final_response_handler);
01011             break;
01012          case WT_TIMER_LIST:
01013             run_handler_for_each(tl,wait_handler);
01014             break;
01015          case DELETE_LIST:
01016             run_handler_for_each(tl,delete_handler);
01017             break;
01018       }
01019    }
01020 }
01021 
01022 
01023 
01024 void utimer_routine(utime_t uticks , void * attr)
01025 {
01026    struct timer_link *tl, *tmp_tl;
01027    int                id;
01028 
01029    for( id=RT_T1_TO_1 ; id<NR_OF_TIMER_LISTS ; id++ )
01030    {
01031       /* to waste as little time in lock as possible, detach list
01032          with expired items and process them after leaving the lock */
01033       tl=check_and_split_time_list( &timertable->timers[ id ], uticks);
01034       /* process items now */
01035       switch (id)
01036       {
01037          case RT_T1_TO_1:
01038          case RT_T1_TO_2:
01039          case RT_T1_TO_3:
01040          case RT_T2:
01041             run_handler_for_each(tl,retransmission_handler);
01042             break;
01043       }
01044    }
01045 }
01046 

Generated on Wed May 23 20:00:32 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6