More log message fixes.
[sip-router] / modules / tm / timer.c
1 /*
2  * $Id$
3  *
4  *
5  * Copyright (C) 2001-2003 Fhg Fokus
6  *
7  * This file is part of ser, a free SIP server.
8  *
9  * ser is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * For a license to use the ser software under conditions
15  * other than those described here, or to purchase support for this
16  * software, please contact iptel.org by e-mail at the following addresses:
17  *    info@iptel.org
18  *
19  * ser is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License 
25  * along with this program; if not, write to the Free Software 
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  */
28
29
30 /* 
31   timer.c is where we implement TM timers. It has been designed
32   for high performance using some techniques of which timer users
33   need to be aware.
34
35         One technique is "fixed-timer-length". We maintain separate 
36         timer lists, all of them include elements of the same time
37         to fire. That allows *appending* new events to the list as
38         opposed to inserting them by time, which is costly due to
39         searching time spent in a mutex. The performance benefit is
40         noticeable. The limitation is you need a new timer list for
41         each new timer length.
42
43         Another technique is the timer process slices off expired elements
44         from the list in a mutex, but executes the timer after the mutex
45         is left. That saves time greatly as whichever process wants to
46         add/remove a timer, it does not have to wait until the current
47         list is processed. However, be aware the timers may hit in a delayed
48         manner; you have no guarantee in your process that after resetting a timer, 
49         it will no more hit. It might have been removed by timer process,
50     and is waiting to be executed.  The following example shows it:
51
52                         PROCESS1                                TIMER PROCESS
53
54         0.                                                              timer hits, it is removed from queue and
55                                                                         about to be executed
56         1.      process1 decides to
57                 reset the timer 
58         2.                                                              timer is executed now
59         3.      if the process1 naively
60                 thinks the timer could not 
61                 have been executed after 
62                 resetting the timer, it is
63                 WRONG -- it was (step 2.)
64
65         So be careful when writing the timer handlers. Currently defined timers 
66         don't hurt if they hit delayed, I hope at least. Retransmission timer 
67         may results in a useless retransmission -- not too bad. FR timer not too
68         bad either as timer processing uses a REPLY mutex making it safe to other
69         processing affecting transaction state. Wait timer not bad either -- processes
70         putting a transaction on wait don't do anything with it anymore.
71
72                 Example when it does not hurt:
73
74                         P1                                              TIMER
75         0.                                                              RETR timer removed from list and
76                                                                         scheduled for execution
77         1. 200/BYE received->
78            reset RETR, put_on_wait
79         2.                                                              RETR timer executed -- too late but it does
80                                                                         not hurt
81         3.                                                              WAIT handler executed
82
83         The rule of thumb is don't touch data you put under a timer. Create data,
84     put them under a timer, and let them live until they are safely destroyed from
85     wait/delete timer.  The only safe place to manipulate the data is 
86     from timer process in which delayed timers cannot hit (all timers are
87     processed sequentially).
88
89         A "bad example" -- rewriting content of retransmission buffer
90         in an unprotected way is bad because a delayed retransmission timer might 
91         hit. Thats why our reply retransmission procedure is enclosed in 
92         a REPLY_LOCK.
93
94 */
95 /*
96  * History:
97  * --------
98  *  2003-06-27  timers are not unlinked if timerlist is 0 (andrei)
99  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced;
100  *              timer_link.payload removed (bogdan)
101  */
102
103 #include "defs.h"
104
105
106
107 #include "config.h"
108 #include "h_table.h"
109 #include "timer.h"
110 #include "../../dprint.h"
111 #include "lock.h"
112 #include "t_stats.h"
113
114 #include "../../hash_func.h"
115 #include "../../dprint.h"
116 #include "../../config.h"
117 #include "../../parser/parser_f.h"
118 #include "../../ut.h"
119 #include "t_funcs.h"
120 #include "t_reply.h"
121 #include "t_cancel.h"
122
123
124 static struct timer_table *timertable=0;
125 static struct timer detached_timer; /* just to have a value to compare with*/
126
127 #define DETACHED_LIST (&detached_timer)
128
129 #define is_in_timer_list2(_tl) ( (_tl)->timer_list &&  \
130                                                                         ((_tl)->timer_list!=DETACHED_LIST) )
131
132 int noisy_ctimer=0;
133
134
135 int timer_group[NR_OF_TIMER_LISTS] = 
136 {
137         TG_FR, TG_FR,
138         TG_WT,
139         TG_DEL,
140         TG_RT, TG_RT, TG_RT, TG_RT
141 };
142
143 /* default values of timeouts for all the timer list
144    (see timer.h for enumeration of timer lists)
145 */
146 unsigned int timer_id2timeout[NR_OF_TIMER_LISTS] = {
147         FR_TIME_OUT,            /* FR_TIMER_LIST */
148         INV_FR_TIME_OUT,        /* FR_INV_TIMER_LIST */
149         WT_TIME_OUT,            /* WT_TIMER_LIST */
150         DEL_TIME_OUT,           /* DELETE_LIST */
151         RETR_T1,                        /* RT_T1_TO_1 */
152         RETR_T1 << 1,           /* RT_T1_TO_2 */
153         RETR_T1 << 2,           /* RT_T1_TO_3 */
154         RETR_T2                         /* RT_T2 */
155                                                 /* NR_OF_TIMER_LISTS */
156 };
157
158 /******************** handlers ***************************/
159
160
161 static void unlink_timers( struct cell *t );
162
163 static void delete_cell( struct cell *p_cell, int unlock )
164 {
165
166 #ifdef EXTRA_DEBUG
167         int i;
168 #endif
169
170         /* there may still be FR/RETR timers, which have been reset
171            (i.e., time_out==TIMER_DELETED) but are stilled linked to
172            timer lists and must be removed from there before the
173            structures are released
174         */
175         unlink_timers( p_cell );
176
177 #ifdef EXTRA_DEBUG
178
179         if (is_in_timer_list2(& p_cell->wait_tl )) {
180                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
181                         " still on WAIT, timeout=%d\n", p_cell, p_cell->wait_tl.time_out);
182                 abort();
183         }
184         if (is_in_timer_list2(& p_cell->uas.response.retr_timer )) {
185                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
186                         " still on RETR (rep), timeout=%d\n",
187                         p_cell, p_cell->uas.response.retr_timer.time_out);
188                 abort();
189         }
190         if (is_in_timer_list2(& p_cell->uas.response.fr_timer )) {
191                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
192                         " still on FR (rep), timeout=%d\n", p_cell,
193                         p_cell->uas.response.fr_timer.time_out);
194                 abort();
195         }
196         for (i=0; i<p_cell->nr_of_outgoings; i++) {
197                 if (is_in_timer_list2(& p_cell->uac[i].request.retr_timer)) {
198                         LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
199                                 " still on RETR (req %d), timeout %d\n", p_cell, i,
200                                 p_cell->uac[i].request.retr_timer.time_out);
201                         abort();
202                 }
203                 if (is_in_timer_list2(& p_cell->uac[i].request.fr_timer)) {
204                         LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
205                                 " still on FR (req %d), timeout %d\n", p_cell, i,
206                                 p_cell->uac[i].request.fr_timer.time_out);
207                         abort();
208                 }
209                 if (is_in_timer_list2(& p_cell->uac[i].local_cancel.retr_timer)) {
210                         LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
211                                 " still on RETR/cancel (req %d), timeout %d\n", p_cell, i,
212                                 p_cell->uac[i].request.retr_timer.time_out);
213                         abort();
214                 }
215                 if (is_in_timer_list2(& p_cell->uac[i].local_cancel.fr_timer)) {
216                         LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
217                                 " still on FR/cancel (req %d), timeout %d\n", p_cell, i,
218                                 p_cell->uac[i].request.fr_timer.time_out);
219                         abort();
220                 }
221         }
222         /* reset_retr_timers( hash__XX_table, p_cell ); */
223 #endif
224         /* still in use ... don't delete */
225         if ( IS_REFFED_UNSAFE(p_cell) ) {
226                 if (unlock) UNLOCK_HASH(p_cell->hash_index);
227                 DBG("DEBUG: delete_cell %p: can't delete -- still reffed\n",
228                         p_cell);
229                 /* it's added to del list for future del */
230                 set_timer( &(p_cell->dele_tl), DELETE_LIST );
231         } else {
232                 if (unlock) UNLOCK_HASH(p_cell->hash_index);
233                 DBG("DEBUG: delete transaction %p\n", p_cell );
234                 free_cell( p_cell );
235         }
236 }
237
238 static void fake_reply(struct cell *t, int branch, int code )
239 {
240         branch_bm_t cancel_bitmap;
241         short do_cancel_branch;
242         enum rps reply_status;
243
244         do_cancel_branch = is_invite(t) && should_cancel_branch(t, branch);
245
246         cancel_bitmap=do_cancel_branch ? 1<<branch : 0;
247         if ( is_local(t) ) {
248                 reply_status=local_reply( t, FAKED_REPLY, branch, 
249                         code, &cancel_bitmap );
250         } else {
251                 reply_status=relay_reply( t, FAKED_REPLY, branch, code,
252                         &cancel_bitmap );
253         }
254         /* now when out-of-lock do the cancel I/O */
255         if (do_cancel_branch) cancel_branch(t, branch );
256         /* it's cleaned up on error; if no error occured and transaction
257            completed regularly, I have to clean-up myself
258         */
259         if (reply_status==RPS_COMPLETED) {
260                 /* don't need to cleanup uac_timers -- they were cleaned
261                    branch by branch and this last branch's timers are
262                    reset now too
263                 */
264                 /* don't need to issue cancels -- local cancels have been
265                    issued branch by branch and this last branch was
266                    cancelled now too
267                 */
268                 /* then the only thing to do now is to put the transaction
269                    on FR/wait state 
270                 */
271                 set_final_timer(  t );
272         }
273 }
274
275
276
277
278 inline static void retransmission_handler( struct timer_link *retr_tl )
279 {
280         struct retr_buf* r_buf ;
281         enum lists id;
282
283         r_buf = get_retr_timer_payload(retr_tl);
284 #ifdef EXTRA_DEBUG
285         if (r_buf->my_T->damocles) {
286                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
287                         " called from RETR timer\n",r_buf->my_T);
288                 abort();
289         }       
290 #endif
291
292         /*the transaction is already removed from RETRANSMISSION_LIST by timer*/
293         /* retransmision */
294         if ( r_buf->activ_type==TYPE_LOCAL_CANCEL 
295                 || r_buf->activ_type==TYPE_REQUEST ) {
296                         DBG("DEBUG: retransmission_handler : "
297                                 "request resending (t=%p, %.9s ... )\n", 
298                                 r_buf->my_T, r_buf->buffer);
299                         if (SEND_BUFFER( r_buf )==-1) {
300                                 reset_timer( &r_buf->fr_timer );
301                                 fake_reply(r_buf->my_T, r_buf->branch, 503 );
302                                 return;
303                         }
304         } else {
305                         DBG("DEBUG: retransmission_handler : "
306                                 "reply resending (t=%p, %.9s ... )\n", 
307                                 r_buf->my_T, r_buf->buffer);
308                         t_retransmit_reply(r_buf->my_T);
309         }
310
311         id = r_buf->retr_list;
312         r_buf->retr_list = id < RT_T2 ? id + 1 : RT_T2;
313         
314         retr_tl->timer_list= NULL; /* set to NULL so that set_timer will work */
315         set_timer( retr_tl, id < RT_T2 ? id + 1 : RT_T2 );
316
317         DBG("DEBUG: retransmission_handler : done\n");
318 }
319
320
321
322
323 inline static void final_response_handler( struct timer_link *fr_tl )
324 {
325         int silent;
326         struct retr_buf* r_buf;
327         struct cell *t;
328
329         if (fr_tl==0){
330                 /* or BUG?, ignoring it for now */
331                 LOG(L_CRIT, "ERROR: final_response_handler(0) called\n");
332                 return;
333         }
334         r_buf = get_fr_timer_payload(fr_tl);
335         t=r_buf->my_T;
336
337 #       ifdef EXTRA_DEBUG
338         if (t->damocles) 
339         {
340                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
341                         " called from FR timer\n",r_buf->my_T);
342                 abort();
343         }
344 #       endif
345
346         reset_timer(  &(r_buf->retr_timer) );
347
348         /* the transaction is already removed from FR_LIST by the timer */
349
350         /* FR for local cancels.... */
351         if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
352         {
353                 DBG("DEBUG: final_response_handler: stop retr for Local Cancel\n");
354                 return;
355         }
356
357         /* FR for replies (negative INVITE replies) */
358         if (r_buf->activ_type>0) {
359 #               ifdef EXTRA_DEBUG
360                 if (t->uas.request->REQ_METHOD!=METHOD_INVITE
361                         || t->uas.status < 200 ) {
362                         LOG(L_ERR, "ERROR: final_response_handler: uknown type reply buffer\n");
363                         abort();
364                 }
365 #               endif
366                 put_on_wait( t );
367                 return;
368         };
369
370         /* lock reply processing to determine how to proceed reliably */
371         LOCK_REPLIES( t );
372         /* now it can be only a request retransmission buffer;
373            try if you can simply discard the local transaction 
374            state without compellingly removing it from the
375            world */
376         silent=
377                 /* not for UACs */
378                 !is_local(t)
379                 /* invites only */
380                 && is_invite(t)
381                 /* parallel forking does not allow silent state discarding */
382                 && t->nr_of_outgoings==1
383                 /* on_negativ reply handler not installed -- serial forking 
384                  * could occur otherwise */
385                 && t->on_negative==0
386                 /* the same for FAILURE callbacks */
387                 && !has_tran_tmcbs( t, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE) 
388                 /* something received -- we will not be silent on error */
389                 && t->uac[r_buf->branch].last_received>0
390                 /* don't go silent if disallowed globally ... */
391                 && noisy_ctimer==0
392                 /* ... or for this particular transaction */
393                 && has_noisy_ctimer(t);
394         if (silent) {
395                 UNLOCK_REPLIES(t);
396                 DBG("DEBUG: final_response_handler: transaction silently dropped (%p)\n",t);
397                 put_on_wait( t );
398                 return;
399         }
400
401         DBG("DEBUG: final_response_handler:stop retr. and send CANCEL (%p)\n", t);
402         fake_reply(t, r_buf->branch, 408 );
403
404         DBG("DEBUG: final_response_handler : done\n");
405 }
406
407
408
409 void cleanup_localcancel_timers( struct cell *t )
410 {
411         int i;
412         for (i=0; i<t->nr_of_outgoings; i++ )  {
413                 reset_timer(  &t->uac[i].local_cancel.retr_timer );
414                 reset_timer(  &t->uac[i].local_cancel.fr_timer );
415         }
416 }
417
418
419 inline static void wait_handler( struct timer_link *wait_tl )
420 {
421         struct cell *p_cell;
422
423         p_cell = get_wait_timer_payload( wait_tl );
424 #ifdef EXTRA_DEBUG
425         if (p_cell->damocles) {
426                 LOG( L_ERR, "ERROR: transaction %p scheduled for deletion and"
427                         " called from WAIT timer\n",p_cell);
428                 abort();
429         }       
430         DBG("DEBUG: WAIT timer hit\n");
431 #endif
432
433         /* stop cancel timers if any running */
434         if ( is_invite(p_cell) ) cleanup_localcancel_timers( p_cell );
435
436         /* the transaction is already removed from WT_LIST by the timer */
437         /* remove the cell from the hash table */
438         DBG("DEBUG: wait_handler : removing %p from table \n", p_cell );
439         LOCK_HASH( p_cell->hash_index );
440         remove_from_hash_table_unsafe(  p_cell );
441         /* jku: no more here -- we do it when we put a transaction on wait */
442 #ifdef EXTRA_DEBUG
443         p_cell->damocles = 1;
444 #endif
445         /* delete (returns with UNLOCK-ed_HASH) */
446         delete_cell( p_cell, 1 /* unlock on return */ );
447         DBG("DEBUG: wait_handler : done\n");
448 }
449
450
451
452 inline static void delete_handler( struct timer_link *dele_tl )
453 {
454         struct cell *p_cell;
455
456         p_cell = get_dele_timer_payload( dele_tl );
457         DBG("DEBUG: delete_handler : removing %p \n", p_cell );
458 #ifdef EXTRA_DEBUG
459         if (p_cell->damocles==0) {
460                 LOG( L_ERR, "ERROR: transaction %p not scheduled for deletion"
461                         " and called from DELETE timer\n",p_cell);
462                 abort();
463         }       
464 #endif
465
466         /* we call delete now without any locking on hash/ref_count;
467            we can do that because delete_handler is only entered after
468            the delete timer was installed from wait_handler, which
469            removed transaction from hash table and did not destroy it
470            because some processes were using it; that means that the
471            processes currently using the transaction can unref and no
472            new processes can ref -- we can wait until ref_count is
473            zero safely without locking
474         */
475         delete_cell( p_cell, 0 /* don't unlock on return */ );
476     DBG("DEBUG: delete_handler : done\n");
477 }
478
479
480 /***********************************************************/
481
482 struct timer_table *get_timertable()
483 {
484         return timertable;
485 }
486
487
488 void unlink_timer_lists()
489 {
490         struct timer_link  *tl, *end, *tmp;
491         enum lists i;
492
493         if (timertable==0) return; /* nothing to do */
494         /* remember the DELETE LIST */
495         tl = timertable->timers[DELETE_LIST].first_tl.next_tl;
496         end = & timertable->timers[DELETE_LIST].last_tl;
497         /* unlink the timer lists */
498         for( i=0; i<NR_OF_TIMER_LISTS ; i++ )
499                 reset_timer_list( i );
500         DBG("DEBUG: unlink_timer_lists : empting DELETE list\n");
501         /* deletes all cells from DELETE_LIST list 
502            (they are no more accessible from enrys) */
503         while (tl!=end) {
504                 tmp=tl->next_tl;
505                 free_cell( get_dele_timer_payload(tl) );
506                 tl=tmp;
507         }
508         
509 }
510
511 struct timer_table *tm_init_timers()
512 {
513         enum lists i;
514
515         timertable=(struct timer_table *) shm_malloc(sizeof(struct timer_table));
516         if (!timertable) {
517                 LOG(L_ERR, "ERROR: tm_init_timers: no shmem for timer_Table\n");
518                 goto error0;
519         }
520         memset(timertable, 0, sizeof (struct timer_table));
521                 
522
523         /* inits the timers*/
524         for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
525         init_timer_list( i );
526     
527     /* init. timer lists */
528         timertable->timers[RT_T1_TO_1].id = RT_T1_TO_1;
529         timertable->timers[RT_T1_TO_2].id = RT_T1_TO_2;
530         timertable->timers[RT_T1_TO_3].id = RT_T1_TO_3;
531         timertable->timers[RT_T2].id      = RT_T2;
532         timertable->timers[FR_TIMER_LIST].id     = FR_TIMER_LIST; 
533         timertable->timers[FR_INV_TIMER_LIST].id = FR_INV_TIMER_LIST;
534         timertable->timers[WT_TIMER_LIST].id     = WT_TIMER_LIST;
535         timertable->timers[DELETE_LIST].id       = DELETE_LIST;
536
537         return timertable;
538
539 error0:
540         return 0;
541 }
542
543 void free_timer_table()
544 {
545         enum lists i;
546
547         if (timertable) {
548                 /* the mutexs for sync the lists are released*/
549                 for ( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
550                         release_timerlist_lock( &timertable->timers[i] );
551                 shm_free(timertable);
552         }
553                 
554 }
555
556 void reset_timer_list( enum lists list_id)
557 {
558         timertable->timers[list_id].first_tl.next_tl =
559                 &(timertable->timers[list_id].last_tl );
560         timertable->timers[list_id].last_tl.prev_tl =
561                 &(timertable->timers[list_id].first_tl );
562         timertable->timers[list_id].first_tl.prev_tl =
563                 timertable->timers[list_id].last_tl.next_tl = NULL;
564         timertable->timers[list_id].last_tl.time_out = -1;
565 }
566
567
568
569
570 void init_timer_list( /* struct s_table* ht, */ enum lists list_id)
571 {
572         reset_timer_list( /* ht, */ list_id );
573         init_timerlist_lock( /* ht, */ list_id );
574 }
575
576
577
578
579 void print_timer_list( enum lists list_id)
580 {
581         struct timer* timer_list=&(timertable->timers[ list_id ]);
582         struct timer_link *tl ;
583
584         tl = timer_list->first_tl.next_tl;
585         while (tl!=& timer_list->last_tl)
586         {
587                 DBG("DEBUG: print_timer_list[%d]: %p, next=%p \n",
588                         list_id, tl, tl->next_tl);
589                 tl = tl->next_tl;
590         }
591 }
592
593
594
595 static void remove_timer_unsafe(  struct timer_link* tl )
596 {
597 #ifdef EXTRA_DEBUG
598         if (tl && is_in_timer_list2(tl) &&
599                 tl->timer_list->last_tl.prev_tl==0) {
600                 LOG( L_CRIT,
601                 "CRITICAL : Oh no, zero link in trailing timer element\n");
602                 abort();
603         };
604 #endif
605         if (is_in_timer_list2( tl )) {
606 #ifdef EXTRA_DEBUG
607                 DBG("DEBUG: unlinking timer: tl=%p, timeout=%d, group=%d\n", 
608                         tl, tl->time_out, tl->tg);
609 #endif
610                 tl->prev_tl->next_tl = tl->next_tl;
611                 tl->next_tl->prev_tl = tl->prev_tl;
612                 tl->next_tl = 0;
613                 tl->prev_tl = 0;
614                 tl->timer_list = NULL;
615         }
616 }
617
618
619
620
621 /* put a new cell into a list nr. list_id */
622 static void add_timer_unsafe( struct timer *timer_list, struct timer_link *tl,
623         unsigned int time_out )
624 {
625 #ifdef EXTRA_DEBUG
626         if (timer_list->last_tl.prev_tl==0) {
627         LOG( L_CRIT,
628                 "CRITICAL : Oh no, zero link in trailing timer element\n");
629                 abort();
630         };
631 #endif
632
633         tl->time_out = time_out;
634         tl->prev_tl = timer_list->last_tl.prev_tl;
635         tl->next_tl = & timer_list->last_tl;
636         timer_list->last_tl.prev_tl = tl;
637         tl->prev_tl->next_tl = tl;
638         tl->timer_list = timer_list;
639 #ifdef EXTRA_DEBUG
640         if ( tl->tg != timer_group[ timer_list->id ] ) {
641                 LOG( L_CRIT, "CRITICAL error: changing timer group\n");
642                 abort();
643         }
644 #endif
645         DBG("DEBUG: add_timer_unsafe[%d]: %p\n",timer_list->id,tl);
646 }
647
648
649
650
651 /* detach items passed by the time from timer list */
652 static struct timer_link  *check_and_split_time_list( struct timer *timer_list,
653         int time )
654 {
655         struct timer_link *tl , *end, *ret;
656
657
658         /* quick check whether it is worth entering the lock */
659         if (timer_list->first_tl.next_tl==&timer_list->last_tl 
660                         || ( /* timer_list->first_tl.next_tl
661                                 && */ timer_list->first_tl.next_tl->time_out > time) )
662                 return NULL;
663
664         /* the entire timer list is locked now -- noone else can manipulate it */
665         lock(timer_list->mutex);
666
667         end = &timer_list->last_tl;
668         tl = timer_list->first_tl.next_tl;
669         while( tl!=end && tl->time_out <= time) {
670                 tl->timer_list = DETACHED_LIST;
671                 tl=tl->next_tl;
672         }
673
674         /* nothing to delete found */
675         if (tl->prev_tl==&(timer_list->first_tl)) {
676                 ret = NULL;
677         } else { /* we did find timers to be fired! */
678                 /* the detached list begins with current beginning */
679                 ret = timer_list->first_tl.next_tl;
680                 /* and we mark the end of the split list */
681                 tl->prev_tl->next_tl = NULL;
682                 /* the shortened list starts from where we suspended */
683                 timer_list->first_tl.next_tl = tl;      
684                 tl->prev_tl = & timer_list->first_tl;
685         }
686 #ifdef EXTRA_DEBUG
687         if (timer_list->last_tl.prev_tl==0) {
688                 LOG( L_CRIT,
689                 "CRITICAL : Oh no, zero link in trailing timer element\n");
690                 abort();
691         };
692 #endif
693         /* give the list lock away */
694         unlock(timer_list->mutex);
695
696         return ret;
697 }
698
699
700
701 /* stop timer
702  * WARNING: a reset'ed timer will be lost forever
703  *  (succesive set_timer won't work unless you're lucky
704  *   an catch the race condition, the ideea here is there is no
705  *   guarantee you can do anything after a timer_reset)*/
706 void reset_timer( struct timer_link* tl )
707 {
708         /* disqualify this timer from execution by setting its time_out
709            to zero; it will stay in timer-list until the timer process
710            starts removing outdated elements; then it will remove it
711            but not execute; there is a race condition, though -- see
712            timer.c for more details
713         */
714         tl->time_out = TIMER_DELETED;
715 #ifdef EXTRA_DEBUG
716         DBG("DEBUG: reset_timer (group %d, tl=%p)\n", tl->tg, tl );
717 #endif
718 }
719
720
721
722
723 /* determine timer length and put on a correct timer list
724  * WARNING: - don't try to use it to "move" a timer from one list
725  *            to another, you'll run into races
726  *          - reset_timer; set_timer might not work, a reset'ed timer
727  *             has no set_timer guarantee, it might be lost;
728  *             same for an expired timer: only it's handler can
729  *             set it again, an external set_timer has no guarantee
730  */
731 void set_timer( struct timer_link *new_tl, enum lists list_id )
732 {
733         unsigned int timeout;
734         struct timer* list;
735
736
737         if (list_id<FR_TIMER_LIST || list_id>=NR_OF_TIMER_LISTS) {
738                 LOG(L_CRIT, "ERROR: set_timer: unkown list: %d\n", list_id);
739 #ifdef EXTRA_DEBUG
740                 abort();
741 #endif
742                 return;
743         }
744         timeout = timer_id2timeout[ list_id ];
745         list= &(timertable->timers[ list_id ]);
746
747         lock(list->mutex);
748         /* check first if we are on the "detached" timer_routine list,
749          * if so do nothing, the timer is not valid anymore
750          * (sideffect: reset_timer ; set_timer is not safe, a reseted timer
751          *  might be lost, depending on this race condition ) */
752         if (new_tl->timer_list==DETACHED_LIST){
753                 LOG(L_CRIT, "WARNING: set_timer called on a \"detached\" timer"
754                                 " -- ignoring: %p\n", new_tl);
755                 goto end;
756         }
757         /* make sure I'm not already on a list */
758         remove_timer_unsafe( new_tl );
759         add_timer_unsafe( list, new_tl, get_ticks()+timeout);
760 end:
761         unlock(list->mutex);
762 }
763
764 /* similar to set_timer, except it allows only one-time
765    timer setting and all later attempts are ignored */
766 void set_1timer( struct timer_link *new_tl, enum lists list_id )
767 {
768         unsigned int timeout;
769         struct timer* list;
770
771
772         if (list_id<FR_TIMER_LIST || list_id>=NR_OF_TIMER_LISTS) {
773                 LOG(L_CRIT, "ERROR: set_timer: unkown list: %d\n", list_id);
774 #ifdef EXTRA_DEBUG
775                 abort();
776 #endif
777                 return;
778         }
779         timeout = timer_id2timeout[ list_id ];
780         list= &(timertable->timers[ list_id ]);
781
782         lock(list->mutex);
783         if (!(new_tl->time_out>TIMER_DELETED)) {
784                 /* make sure I'm not already on a list */
785                 /* remove_timer_unsafe( new_tl ); */
786                 add_timer_unsafe( list, new_tl, get_ticks()+timeout);
787
788                 /* set_1timer is used only by WAIT -- that's why we can
789                    afford updating wait statistics; I admit its not nice
790                    but it greatly utilizes existing lock 
791                 */
792         }
793         unlock(list->mutex);
794         t_stats_wait();
795 }
796
797
798
799 /* should be called only from timer process context,
800  * else it's unsafe */
801 static void unlink_timers( struct cell *t )
802 {
803         int i;
804         int remove_fr, remove_retr;
805
806         remove_fr=0; remove_retr=0;
807
808         /* first look if we need to remove timers and play with
809            costly locks at all
810
811             note that is_in_timer_list2 is unsafe but it does not
812             hurt -- transaction is already dead (wait state) so that
813             noone else will install a FR/RETR timer and it can only
814             be removed from timer process itself -> it is safe to
815             use it without any protection
816         */
817         if (is_in_timer_list2(&t->uas.response.fr_timer)) remove_fr=1; 
818         else for (i=0; i<t->nr_of_outgoings; i++)
819                 if (is_in_timer_list2(&t->uac[i].request.fr_timer)
820                         || is_in_timer_list2(&t->uac[i].local_cancel.fr_timer)) {
821                                 remove_fr=1;
822                                 break;
823                 }
824         if (is_in_timer_list2(&t->uas.response.retr_timer)) remove_retr=1; 
825         else for (i=0; i<t->nr_of_outgoings; i++)
826                 if (is_in_timer_list2(&t->uac[i].request.retr_timer)
827                         || is_in_timer_list2(&t->uac[i].local_cancel.retr_timer)) {
828                                 remove_retr=1;
829                                 break;
830                 }
831
832         /* do what we have to do....*/
833         if (remove_retr) {
834                 /* RT_T1 lock is shared by all other RT timer
835                    lists -- we can safely lock just one
836                 */
837                 lock(timertable->timers[RT_T1_TO_1].mutex);
838                 remove_timer_unsafe(&t->uas.response.retr_timer);
839                 for (i=0; i<t->nr_of_outgoings; i++) {
840                         remove_timer_unsafe(&t->uac[i].request.retr_timer);
841                         remove_timer_unsafe(&t->uac[i].local_cancel.retr_timer);
842                 }
843                 unlock(timertable->timers[RT_T1_TO_1].mutex);
844         }
845         if (remove_fr) {
846                 /* FR lock is shared by all other FR timer
847                    lists -- we can safely lock just one
848                 */
849                 lock(timertable->timers[FR_TIMER_LIST].mutex);
850                 remove_timer_unsafe(&t->uas.response.fr_timer);
851                 for (i=0; i<t->nr_of_outgoings; i++) {
852                         remove_timer_unsafe(&t->uac[i].request.fr_timer);
853                         remove_timer_unsafe(&t->uac[i].local_cancel.fr_timer);
854                 }
855                 unlock(timertable->timers[FR_TIMER_LIST].mutex);
856         }
857 }
858
859
860
861
862 #define run_handler_for_each( _tl , _handler ) \
863         while ((_tl))\
864         {\
865                 /* reset the timer list linkage */\
866                 tmp_tl = (_tl)->next_tl;\
867                 (_tl)->next_tl = (_tl)->prev_tl = 0;\
868                 DBG("DEBUG: timer routine:%d,tl=%p next=%p\n",\
869                         id,(_tl),tmp_tl);\
870                 if ((_tl)->time_out>TIMER_DELETED) \
871                         (_handler)( _tl );\
872                 (_tl) = tmp_tl;\
873         }
874
875
876
877
878 void timer_routine(unsigned int ticks , void * attr)
879 {
880         /* struct timer_table *tt= (struct timer_table*)attr; */
881         struct timer_link *tl, *tmp_tl;
882         int                id;
883
884         for( id=0 ; id<NR_OF_TIMER_LISTS ; id++ )
885         {
886                 /* to waste as little time in lock as possible, detach list
887                    with expired items and process them after leaving the lock */
888                 tl=check_and_split_time_list( &timertable->timers[ id ], ticks);
889                 /* process items now */
890                 switch (id)
891                 {
892                         case FR_TIMER_LIST:
893                         case FR_INV_TIMER_LIST:
894                                 run_handler_for_each(tl,final_response_handler);
895                                 break;
896                         case RT_T1_TO_1:
897                         case RT_T1_TO_2:
898                         case RT_T1_TO_3:
899                         case RT_T2:
900                                 run_handler_for_each(tl,retransmission_handler);
901                                 break;
902                         case WT_TIMER_LIST:
903                                 run_handler_for_each(tl,wait_handler);
904                                 break;
905                         case DELETE_LIST:
906                                 run_handler_for_each(tl,delete_handler);
907                                 break;
908                 }
909         }
910 }
911