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 }