root/net/inet/timer.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. delete_timer
  2. reset_timer
  3. net_timer

   1 /*
   2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3  *              operating system.  INET is implemented using the  BSD Socket
   4  *              interface as the means of communication with the user level.
   5  *
   6  *              TIMER - implementation of software timers.
   7  *
   8  * Version:     @(#)timer.c     1.0.7   05/25/93
   9  *
  10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12  *              Corey Minyard <wf-rch!minyard@relay.EU.net>
  13  *              Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
  14  *
  15  *              This program is free software; you can redistribute it and/or
  16  *              modify it under the terms of the GNU General Public License
  17  *              as published by the Free Software Foundation; either version
  18  *              2 of the License, or (at your option) any later version.
  19  */
  20 #include <linux/types.h>
  21 #include <linux/errno.h>
  22 #include <linux/socket.h>
  23 #include <linux/in.h>
  24 #include <linux/kernel.h>
  25 #include <linux/sched.h>
  26 #include <linux/timer.h>
  27 #include <asm/system.h>
  28 #include <linux/interrupt.h>
  29 #include "inet.h"
  30 #include "timer.h"
  31 #include "dev.h"
  32 #include "ip.h"
  33 #include "protocol.h"
  34 #include "tcp.h"
  35 #include "skbuff.h"
  36 #include "sock.h"
  37 #include "arp.h"
  38 
  39 
  40 struct timer *timer_base = NULL;
  41 unsigned long seq_offset;
  42 
  43 
  44 void
  45 delete_timer(struct timer *t)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47   struct timer *tm;
  48 
  49   DPRINTF((DBG_TMR, "delete_timer(t=%X)\n", t));
  50   cli();
  51   if (timer_base == NULL || t == NULL) {
  52         t->running = 9;
  53         sti();
  54         return;
  55   }
  56   if (t == timer_base) {
  57         timer_base = t->next;
  58         if (timer_base != NULL) {
  59                 timer_table[NET_TIMER].expires = timer_base->when;
  60                 timer_active |= (1 << NET_TIMER);
  61         } else {
  62                 timer_active &= ~(1 << NET_TIMER);
  63         }
  64         t->running = 0;
  65         sti();
  66         return;
  67   }
  68   tm = timer_base;
  69   while (tm != NULL) {
  70         if (tm->next == t) {
  71                 tm->next = t->next;
  72                 t->running = 0;
  73                 sti();
  74                 return;
  75         }
  76         tm = tm->next;
  77   }
  78   sti();
  79   t->running = 9;
  80 }
  81 
  82 
  83 void
  84 reset_timer(struct timer *t)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86   struct timer *tm;
  87 
  88   DPRINTF((DBG_TMR, "reset_timer(t=%X) when = %d jiffies = %d\n",
  89                                                 t, t->when, jiffies));
  90   if (t == NULL) {
  91         printk("*** reset timer NULL timer\n");
  92         __asm__ ("\t int $3\n");
  93   }
  94   if (t->running) {
  95         DPRINTF((DBG_TMR, "t->running has value of %d, len %d\n",
  96                                                 t->running, t->len));
  97   }
  98   t->running = 1;
  99   delete_timer(t);              /* here is another race condition ! */
 100   cli();                        /* what about a new reset_timer while being\ */
 101   if (!((t->running == 0) || (t->running == 9))) {    /* about to install on old one ? -FB */
 102         printk("reset_timer(): t->running after delete_timer: %d !\n",
 103                                                                 t->running);
 104         sti();
 105         return;
 106   }
 107   t->running = 2;
 108   if ((int) t->len < 0)         /* prevent close to infinite timers. THEY _DO_ */
 109         t->len = 3;             /* happen (negative values ?) - don't ask me why ! -FB */
 110   
 111   delete_timer(t);
 112   cli();
 113   t->when = timer_seq + t->len;
 114 
 115   /* First see if it goes at the beginning. */
 116 
 117   if (timer_base == NULL) {
 118         t->next = NULL;
 119         timer_base = t;
 120         timer_table[NET_TIMER].expires = timer_base->when;
 121         timer_active |= (1 << NET_TIMER);
 122         t->running = 3;
 123         sti();
 124         return;
 125   }
 126   if (before(t->when, timer_base->when)) {
 127         t->next = timer_base;
 128         timer_base = t;
 129         timer_table[NET_TIMER].expires = timer_base->when;
 130         timer_active |= (1 << NET_TIMER);
 131         t->running = 4;
 132 
 133         sti();
 134         return;
 135   }
 136   tm = timer_base;
 137   while (tm != NULL) {
 138         if (tm->next == NULL || t->when < tm->next->when) {
 139                 t->next = tm->next;
 140                 tm->next = t;
 141                 timer_table[NET_TIMER].expires = timer_base->when;
 142                 timer_active |= (1 << NET_TIMER);
 143                 t->running = 5;
 144                 sti();
 145                 return;
 146         }
 147         tm = tm->next;
 148   }
 149   sti();
 150 }
 151 
 152 
 153 /*
 154  * Now we will only be called whenever we need to do
 155  * something, but we must be sure to process all of the
 156  * sockets that need it.
 157  */
 158 void
 159 net_timer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   struct sock *sk;
 162   struct timer *tm;
 163 
 164   cli();                        /* a timer might expire and a new one with */
 165                                 /* earlier expiration could be inserted before -FB */
 166   tm = timer_base;
 167   while ((tm != NULL) && (jiffies >= tm->when)) {
 168         int why;
 169 
 170         sk = tm->sk;
 171         if (sk->inuse) {
 172                 break;
 173         }
 174         sk->inuse = 1;
 175         sti();
 176         why = sk->timeout;
 177 
 178         DPRINTF((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why));
 179         if (sk->keepopen) {
 180                 sk->time_wait.len = TCP_TIMEOUT_LEN;
 181                 sk->timeout = TIME_KEEPOPEN;
 182                 reset_timer(tm);
 183         } else {
 184                 sk->timeout = 0;
 185                 delete_timer(tm);
 186         }
 187         
 188         /* Always see if we need to send an ack. */
 189         if (sk->ack_backlog) {
 190                 sk->prot->read_wakeup(sk);
 191                 if (!sk->dead) wake_up(sk->sleep);
 192         }
 193         
 194         /* Now we need to figure out why the socket was on the timer. */
 195         switch (why) {
 196                 case TIME_DONE:
 197                         if (!sk->dead || sk->state != TCP_CLOSE) {
 198                                 printk("non dead socket in time_done\n");
 199                                 release_sock(sk);
 200                                 break;
 201                         }
 202                         destroy_sock(sk);
 203                         break;
 204                 case TIME_DESTROY:
 205                         /*
 206                          * We've waited for a while for all the memory
 207                          * assosiated with the socket to be freed.  We
 208                          * need to print an error message.
 209                          */
 210                         DPRINTF((DBG_TMR, "possible memory leak.  sk = %X\n", sk));
 211                         destroy_sock(sk);
 212                         sk->inuse = 0;
 213                         break;
 214                 case TIME_CLOSE:
 215                         /* We've waited long enough, close the socket. */
 216                         sk->state = TCP_CLOSE;
 217                         delete_timer(&sk->time_wait);
 218 
 219                         /*
 220                          * Kill the ARP entry in case the hardware
 221                          * has changed.
 222                          */
 223                         arp_destroy(sk->daddr);
 224                         if (!sk->dead) wake_up(sk->sleep);
 225                         sk->shutdown = SHUTDOWN_MASK;
 226                         sk->time_wait.len = TCP_DONE_TIME;
 227                         sk->timeout = TIME_DESTROY;
 228                         reset_timer (&sk->time_wait);
 229                         release_sock(sk);
 230                         break;
 231                 case TIME_WRITE: /* try to retransmit. */
 232                         /*
 233                          * It could be we got here because we
 234                          * needed to send an ack.  So we need
 235                          * to check for that.
 236                          */
 237                         if (sk->send_head != NULL) {
 238                                 if (jiffies < (sk->send_head->when +
 239                                                backoff(sk->backoff) *
 240                                                (2 * sk->mdev + sk->rtt))) {
 241 /* printk("timer: not yet\n"); */
 242                                         sk->time_wait.len = 
 243                                           (sk->send_head->when +
 244                                            backoff(sk->backoff) *
 245                                            (2 * sk->mdev + sk->rtt)) - jiffies;
 246                                         sk->timeout = TIME_WRITE;
 247                                         reset_timer(&sk->time_wait);
 248                                         release_sock(sk);
 249                                         break;
 250                                 }
 251 /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
 252        sk->retransmits, sk->packets_out, sk->cong_window); */
 253                                 DPRINTF((DBG_TMR, "retransmitting.\n"));
 254                                 sk->prot->retransmit(sk, 0);
 255                                 if ((sk->state == TCP_ESTABLISHED &&
 256                                      sk->retransmits != 0 &&
 257                                      (sk->retransmits & 7) == 0) ||
 258                                     (sk->state != TCP_ESTABLISHED &&
 259                                      sk->retransmits > TCP_RETR1)) {
 260                                         DPRINTF((DBG_TMR, "timer.c TIME_WRITE time-out 1\n"));
 261                                         arp_destroy(sk->daddr);
 262                                         ip_route_check(sk->daddr);
 263                                 }
 264                                 if (sk->state != TCP_ESTABLISHED &&
 265                                     sk->retransmits > TCP_RETR2) {
 266                                         DPRINTF((DBG_TMR, "timer.c TIME_WRITE time-out 2\n"));
 267                                         sk->err = ETIMEDOUT;
 268                                         if (sk->state == TCP_FIN_WAIT1 ||
 269                                             sk->state == TCP_FIN_WAIT2 ||
 270                                             sk->state == TCP_LAST_ACK) {
 271                                                 sk->state = TCP_TIME_WAIT;
 272                                                 sk->timeout = TIME_CLOSE;
 273                                                 sk->time_wait.len =
 274                                                         TCP_TIMEWAIT_LEN;
 275                                                 reset_timer(&sk->time_wait);
 276                                         } else {
 277                                                 sk->prot->close(sk,1);
 278                                                 break;
 279                                         }
 280                                 }
 281                         }
 282                         release_sock(sk);
 283                         break;
 284                 case TIME_KEEPOPEN:
 285                         /* Send something to keep the connection open. */
 286                         if (sk->prot->write_wakeup != NULL)
 287                                         sk->prot->write_wakeup(sk);
 288                         sk->retransmits ++;
 289                         if (sk->shutdown == SHUTDOWN_MASK) {
 290                                 sk->prot->close(sk,1);
 291                                 sk->state = TCP_CLOSE;
 292                         }
 293 
 294                         if ((sk->state == TCP_ESTABLISHED &&
 295                              sk->retransmits != 0 &&
 296                              (sk->retransmits & 7) == 0) ||
 297                             (sk->state != TCP_ESTABLISHED &&
 298                              sk->retransmits > TCP_RETR1)) {
 299                                 DPRINTF((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 1\n"));
 300                                 arp_destroy(sk->daddr);
 301                                 ip_route_check(sk->daddr);
 302                                 release_sock(sk);
 303                                 break;
 304                         }
 305                         if (sk->state != TCP_ESTABLISHED &&
 306                             sk->retransmits > TCP_RETR2) {
 307                                 DPRINTF((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 2\n"));
 308                                 arp_destroy (sk->daddr);
 309                                 sk->err = ETIMEDOUT;
 310                                 if (sk->state == TCP_FIN_WAIT1 ||
 311                                     sk->state == TCP_FIN_WAIT2) {
 312                                         sk->state = TCP_TIME_WAIT;
 313                                         if (!sk->dead) wake_up(sk->sleep);
 314                                         release_sock(sk);
 315                                 } else {
 316                                         sk->prot->close (sk, 1);
 317                                 }
 318                                 break;
 319                         }
 320                         release_sock(sk);
 321                         break;
 322                 default:
 323                         printk("net timer expired - reason unknown, sk=%08X\n",
 324                                                                 (int) sk);
 325                         release_sock(sk);
 326                         break;
 327         }
 328         cli();
 329         tm = timer_base;
 330   }
 331 
 332   /* Now we need to reset the timer. */
 333 
 334   if (timer_base != NULL) {
 335         timer_table[NET_TIMER].expires = timer_base->when;
 336         timer_active |= 1 << NET_TIMER;
 337   }
 338   sti();
 339 }

/* [previous][next][first][last][top][bottom][index][help] */