00001 
00002 
00003 
00004 
00005 #include <stdio.h>
00006 #include <pthread.h>
00007 #include <assert.h>
00008 #include <semaphore.h>
00009 
00010 #include "misc.h"
00011 #include "tcpproxy.h"
00012 #include "tcp.h"
00013 #include "tcptimer.h"
00014 
00015 
00016 typedef struct timerq_event {
00017     long time_left;             
00018     long time_queued;           
00019     void (*func)(void *);       
00020     void *arg;                  
00021     struct timerq_event *next;  
00022 } Ttimerq_event;
00023 
00024 static const struct timespec tick = { TIMER_MTICK/1000, 1000000*TIMER_MTICK };
00025 static pthread_mutex_t timerq_mut = PTHREAD_MUTEX_INITIALIZER;
00026 static Ttimerq_event *timerq_head = NULL;
00027 
00028 
00029 
00030 
00031 
00032 void init_timer()
00033 {
00034     
00035 }
00036 
00037 
00038 
00039 
00040 
00041 void cleanup_timer()
00042 {
00043     Ttimerq_event *event;  
00044     int count = 0;
00045 
00046     
00047 
00048     while(timerq_head != NULL) {
00049         event = timerq_head;
00050         timerq_head = timerq_head->next;
00051         xfree(event);
00052         count++;
00053     }
00054     
00055     if(count > 0)
00056         DPRINT("cleanup_timer: cleared %d events from the queue.\n", count);
00057 }
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 long clear_timer(void (*func)(void *), void *arg)
00066 {
00067     Ttimerq_event *ptr, *prev_ptr;
00068     long dur;
00069     
00070     
00071 
00072     mutex_lock("clear_timer", &timerq_mut);
00073 
00074     prev_ptr = NULL;
00075     for(ptr=timerq_head; ptr; ptr=ptr->next) {
00076         if(ptr->func == func && ptr->arg == arg) {
00077             
00078             
00079             dur = get_mclock() - ptr->time_queued;
00080 
00081             
00082             if(prev_ptr)
00083                 prev_ptr->next = ptr->next;
00084             else
00085                 timerq_head = ptr->next;
00086             if(ptr->next)  
00087               ptr->next->time_left += ptr->time_left;
00088 
00089             mutex_unlock("clear_timer", &timerq_mut);
00090             xfree(ptr);
00091             return dur;
00092         }
00093     }
00094     mutex_unlock("clear_timer", &timerq_mut);
00095     return -1;
00096 }
00097 
00098 
00099 
00100 
00101 
00102 void clear_tcp_timers(void *arg)
00103 {
00104     
00105     clear_timer(tcp_timeout, arg);
00106 }
00107 
00108 
00109 
00110 
00111 
00112 
00113 long left_timer(void (*func)(void *), void *arg)
00114 {
00115     Ttimerq_event *ptr;
00116     long dur = 0;
00117     
00118     DPRINT("left_timer: entered.\n");
00119 
00120     mutex_lock("left_timer", &timerq_mut);
00121     for(ptr=timerq_head; ptr; ptr=ptr->next) {
00122         dur += ptr->time_left;
00123         if(ptr->func == func && ptr->arg == arg) {
00124             mutex_unlock("left_timer", &timerq_mut);
00125             return dur;
00126         }
00127     }
00128     mutex_unlock("left_timer", &timerq_mut);
00129     return -1;
00130 }
00131 
00132 
00133 
00134 
00135 
00136 
00137 int add_timer(long mdelay, void (*func)(void *), void *arg)
00138 {
00139     Ttimerq_event *event;
00140     Ttimerq_event *ptr, *prev_ptr;
00141     
00142     
00143 
00144     assert(mdelay >= 0);
00145 
00146     
00147     event = (Ttimerq_event *) xmalloc(sizeof(Ttimerq_event));
00148     event->time_left = mdelay;
00149     event->time_queued = get_mclock();
00150     event->func = func;
00151     event->arg = arg;
00152     event->next = NULL;
00153 
00154     clear_timer(func, arg);  
00155 
00156     mutex_lock("add_timer", &timerq_mut);
00157 
00158     if(timerq_head == NULL) {      
00159         
00160         timerq_head = event;
00161         mutex_unlock("add_timer", &timerq_mut);
00162         return 0;
00163     }
00164 
00165     
00166     prev_ptr = NULL;
00167     for(ptr=timerq_head; ptr; ptr=ptr->next) {
00168         if(event->time_left < ptr->time_left)  
00169             break;
00170         
00171         event->time_left -= ptr->time_left;
00172         prev_ptr = ptr;
00173     }
00174 
00175     if(prev_ptr)
00176         prev_ptr->next = event;
00177     else
00178         timerq_head = event;
00179     event->next = ptr;
00180     if(ptr)
00181         ptr->time_left -= event->time_left;    
00182 
00183     mutex_unlock("add_timer", &timerq_mut);    
00184     return 0;
00185 }
00186 
00187 
00188 
00189 
00190 
00191 void tcp_timer(void *sig_mask)
00192 {
00193     long now, last_run, delta;    
00194     struct timespec time_rem;     
00195     Ttimerq_event *event;         
00196     Ttimerq_event *expired_head;  
00197     Ttimerq_event *expired_tail;  
00198 
00199     
00200 
00201     if(pthread_sigmask(SIG_BLOCK, sig_mask, NULL)) {
00202         EPRINT("tcp_timer: error blocking signals.\n");
00203     }
00204 
00205     last_run = get_mclock();
00206     
00207     while(!request_exit) {      
00208         while(nanosleep(&time_rem, &time_rem) == -1)
00209             DPRINT("tcp_timer: nanosleep returned -1, sleeping again.\n");
00210 
00211         mutex_lock("tcp_timer", &timerq_mut);
00212 
00213         now = get_mclock();
00214         delta = now - last_run;
00215 
00216         last_run = now;
00217         expired_head = timerq_head;
00218 
00219         
00220 
00221         while(timerq_head != NULL && timerq_head->time_left <= delta) {
00222             delta -= timerq_head->time_left;
00223             timerq_head = timerq_head->next;
00224         }
00225         if(timerq_head != NULL)
00226             timerq_head->time_left -= delta;
00227 
00228         
00229         expired_tail = timerq_head;
00230 
00231         mutex_unlock("tcp_timer", &timerq_mut);
00232 
00233         
00234         while(expired_head != timerq_head) {
00235             event = expired_head;
00236             expired_head = expired_head->next;
00237             event->func(event->arg);  
00238             xfree(event);           
00239         }
00240     }
00241 }