dn_timer.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * DECnet       An implementation of the DECnet protocol suite for the LINUX
  3.  *              operating system.  DECnet is implemented using the  BSD Socket
  4.  *              interface as the means of communication with the user level.
  5.  *
  6.  *              DECnet Socket Timer Functions
  7.  *
  8.  * Author:      Steve Whitehouse <SteveW@ACM.org>
  9.  *
  10.  *
  11.  * Changes:
  12.  *       Steve Whitehouse      : Made keepalive timer part of the same
  13.  *                               timer idea.
  14.  *       Steve Whitehouse      : Added checks for sk->sock_readers
  15.  *       David S. Miller       : New socket locking
  16.  *       Steve Whitehouse      : Timer grabs socket ref.
  17.  */
  18. #include <linux/net.h>
  19. #include <linux/socket.h>
  20. #include <linux/skbuff.h>
  21. #include <linux/netdevice.h>
  22. #include <linux/timer.h>
  23. #include <linux/spinlock.h>
  24. #include <net/sock.h>
  25. #include <asm/atomic.h>
  26. #include <net/dn.h>
  27. /*
  28.  * Fast timer is for delayed acks (200mS max)
  29.  * Slow timer is for everything else (n * 500mS)
  30.  */
  31. #define FAST_INTERVAL (HZ/5)
  32. #define SLOW_INTERVAL (HZ/2)
  33. static void dn_slow_timer(unsigned long arg);
  34. void dn_start_slow_timer(struct sock *sk)
  35. {
  36. sk->timer.expires = jiffies + SLOW_INTERVAL;
  37. sk->timer.function = dn_slow_timer;
  38. sk->timer.data = (unsigned long)sk;
  39. add_timer(&sk->timer);
  40. }
  41. void dn_stop_slow_timer(struct sock *sk)
  42. {
  43. del_timer(&sk->timer);
  44. }
  45. static void dn_slow_timer(unsigned long arg)
  46. {
  47. struct sock *sk = (struct sock *)arg;
  48. struct dn_scp *scp = DN_SK(sk);
  49. sock_hold(sk);
  50. bh_lock_sock(sk);
  51. if (sk->lock.users != 0) {
  52. sk->timer.expires = jiffies + HZ / 10;
  53. add_timer(&sk->timer);
  54. goto out;
  55. }
  56. /*
  57.  * The persist timer is the standard slow timer used for retransmits
  58.  * in both connection establishment and disconnection as well as
  59.  * in the RUN state. The different states are catered for by changing
  60.  * the function pointer in the socket. Setting the timer to a value
  61.  * of zero turns it off. We allow the persist_fxn to turn the
  62.  * timer off in a permant way by returning non-zero, so that
  63.  * timer based routines may remove sockets. This is why we have a
  64.  * sock_hold()/sock_put() around the timer to prevent the socket
  65.  * going away in the middle.
  66.  */
  67. if (scp->persist && scp->persist_fxn) {
  68. if (scp->persist <= SLOW_INTERVAL) {
  69. scp->persist = 0;
  70. if (scp->persist_fxn(sk))
  71. goto out;
  72. } else {
  73. scp->persist -= SLOW_INTERVAL;
  74. }
  75. }
  76. /*
  77.  * Check for keepalive timeout. After the other timer 'cos if
  78.  * the previous timer caused a retransmit, we don't need to
  79.  * do this. scp->stamp is the last time that we sent a packet.
  80.  * The keepalive function sends a link service packet to the
  81.  * other end. If it remains unacknowledged, the standard
  82.  * socket timers will eventually shut the socket down. Each
  83.  * time we do this, scp->stamp will be updated, thus
  84.  * we won't try and send another until scp->keepalive has passed
  85.  * since the last successful transmission.
  86.  */
  87. if (scp->keepalive && scp->keepalive_fxn && (scp->state == DN_RUN)) {
  88. if ((jiffies - scp->stamp) >= scp->keepalive)
  89. scp->keepalive_fxn(sk);
  90. }
  91. sk->timer.expires = jiffies + SLOW_INTERVAL;
  92. add_timer(&sk->timer);
  93. out:
  94. bh_unlock_sock(sk);
  95. sock_put(sk);
  96. }
  97. static void dn_fast_timer(unsigned long arg)
  98. {
  99. struct sock *sk = (struct sock *)arg;
  100. struct dn_scp *scp = DN_SK(sk);
  101. bh_lock_sock(sk);
  102. if (sk->lock.users != 0) {
  103. scp->delack_timer.expires = jiffies + HZ / 20;
  104. add_timer(&scp->delack_timer);
  105. goto out;
  106. }
  107. scp->delack_pending = 0;
  108. if (scp->delack_fxn)
  109. scp->delack_fxn(sk);
  110. out:
  111. bh_unlock_sock(sk);
  112. }
  113. void dn_start_fast_timer(struct sock *sk)
  114. {
  115. struct dn_scp *scp = DN_SK(sk);
  116. if (!scp->delack_pending) {
  117. scp->delack_pending = 1;
  118. init_timer(&scp->delack_timer);
  119. scp->delack_timer.expires = jiffies + FAST_INTERVAL;
  120. scp->delack_timer.data = (unsigned long)sk;
  121. scp->delack_timer.function = dn_fast_timer;
  122. add_timer(&scp->delack_timer);
  123. }
  124. }
  125. void dn_stop_fast_timer(struct sock *sk)
  126. {
  127. struct dn_scp *scp = DN_SK(sk);
  128. if (scp->delack_pending) {
  129. scp->delack_pending = 0;
  130. del_timer(&scp->delack_timer);
  131. }
  132. }