/contrib/ntp/libntp/recvbuff.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 246 lines · 181 code · 30 blank · 35 comment · 18 complexity · f060775f40566e6816b1263af5518118 MD5 · raw file

  1. #ifdef HAVE_CONFIG_H
  2. # include <config.h>
  3. #endif
  4. #include <stdio.h>
  5. #include "ntp_machine.h"
  6. #include "ntp_fp.h"
  7. #include "ntp_syslog.h"
  8. #include "ntp_stdlib.h"
  9. #include "ntp_io.h"
  10. #include "recvbuff.h"
  11. #include "iosignal.h"
  12. #include <isc/list.h>
  13. /*
  14. * Memory allocation
  15. */
  16. static u_long volatile full_recvbufs; /* number of recvbufs on fulllist */
  17. static u_long volatile free_recvbufs; /* number of recvbufs on freelist */
  18. static u_long volatile total_recvbufs; /* total recvbufs currently in use */
  19. static u_long volatile lowater_adds; /* number of times we have added memory */
  20. static u_long volatile buffer_shortfall;/* number of missed free receive buffers
  21. between replenishments */
  22. static ISC_LIST(recvbuf_t) full_recv_list; /* Currently used recv buffers */
  23. static ISC_LIST(recvbuf_t) free_recv_list; /* Currently unused buffers */
  24. #if defined(SYS_WINNT)
  25. /*
  26. * For Windows we need to set up a lock to manipulate the
  27. * recv buffers to prevent corruption. We keep it lock for as
  28. * short a time as possible
  29. */
  30. static CRITICAL_SECTION RecvLock;
  31. # define LOCK() EnterCriticalSection(&RecvLock)
  32. # define UNLOCK() LeaveCriticalSection(&RecvLock)
  33. #else
  34. # define LOCK()
  35. # define UNLOCK()
  36. #endif
  37. u_long
  38. free_recvbuffs (void)
  39. {
  40. return free_recvbufs;
  41. }
  42. u_long
  43. full_recvbuffs (void)
  44. {
  45. return full_recvbufs;
  46. }
  47. u_long
  48. total_recvbuffs (void)
  49. {
  50. return total_recvbufs;
  51. }
  52. u_long
  53. lowater_additions(void)
  54. {
  55. return lowater_adds;
  56. }
  57. static void
  58. initialise_buffer(recvbuf_t *buff)
  59. {
  60. memset((char *) buff, 0, sizeof(recvbuf_t));
  61. #if defined SYS_WINNT
  62. buff->wsabuff.len = RX_BUFF_SIZE;
  63. buff->wsabuff.buf = (char *) buff->recv_buffer;
  64. #endif
  65. }
  66. static void
  67. create_buffers(int nbufs)
  68. {
  69. register recvbuf_t *bufp;
  70. int i, abuf;
  71. abuf = nbufs + buffer_shortfall;
  72. buffer_shortfall = 0;
  73. bufp = (recvbuf_t *) emalloc(abuf*sizeof(recvbuf_t));
  74. for (i = 0; i < abuf; i++)
  75. {
  76. memset((char *) bufp, 0, sizeof(recvbuf_t));
  77. ISC_LIST_APPEND(free_recv_list, bufp, link);
  78. bufp++;
  79. free_recvbufs++;
  80. total_recvbufs++;
  81. }
  82. lowater_adds++;
  83. }
  84. void
  85. init_recvbuff(int nbufs)
  86. {
  87. /*
  88. * Init buffer free list and stat counters
  89. */
  90. ISC_LIST_INIT(full_recv_list);
  91. ISC_LIST_INIT(free_recv_list);
  92. free_recvbufs = total_recvbufs = 0;
  93. full_recvbufs = lowater_adds = 0;
  94. create_buffers(nbufs);
  95. #if defined(SYS_WINNT)
  96. InitializeCriticalSection(&RecvLock);
  97. #endif
  98. }
  99. /*
  100. * freerecvbuf - make a single recvbuf available for reuse
  101. */
  102. void
  103. freerecvbuf(recvbuf_t *rb)
  104. {
  105. if (rb == NULL) {
  106. msyslog(LOG_ERR, "freerecvbuff received NULL buffer");
  107. return;
  108. }
  109. LOCK();
  110. (rb->used)--;
  111. if (rb->used != 0)
  112. msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
  113. ISC_LIST_APPEND(free_recv_list, rb, link);
  114. #if defined SYS_WINNT
  115. rb->wsabuff.len = RX_BUFF_SIZE;
  116. rb->wsabuff.buf = (char *) rb->recv_buffer;
  117. #endif
  118. free_recvbufs++;
  119. UNLOCK();
  120. }
  121. void
  122. add_full_recv_buffer(recvbuf_t *rb)
  123. {
  124. if (rb == NULL) {
  125. msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
  126. return;
  127. }
  128. LOCK();
  129. ISC_LIST_APPEND(full_recv_list, rb, link);
  130. full_recvbufs++;
  131. UNLOCK();
  132. }
  133. recvbuf_t *
  134. get_free_recv_buffer(void)
  135. {
  136. recvbuf_t * buffer = NULL;
  137. LOCK();
  138. buffer = ISC_LIST_HEAD(free_recv_list);
  139. if (buffer != NULL)
  140. {
  141. ISC_LIST_DEQUEUE(free_recv_list, buffer, link);
  142. free_recvbufs--;
  143. initialise_buffer(buffer);
  144. (buffer->used)++;
  145. }
  146. else
  147. {
  148. buffer_shortfall++;
  149. }
  150. UNLOCK();
  151. return (buffer);
  152. }
  153. #ifdef HAVE_IO_COMPLETION_PORT
  154. recvbuf_t *
  155. get_free_recv_buffer_alloc(void)
  156. {
  157. recvbuf_t * buffer = get_free_recv_buffer();
  158. if (buffer == NULL)
  159. {
  160. create_buffers(RECV_INC);
  161. buffer = get_free_recv_buffer();
  162. }
  163. return (buffer);
  164. }
  165. #endif
  166. recvbuf_t *
  167. get_full_recv_buffer(void)
  168. {
  169. recvbuf_t *rbuf;
  170. LOCK();
  171. #ifdef HAVE_SIGNALED_IO
  172. /*
  173. * make sure there are free buffers when we
  174. * wander off to do lengthy paket processing with
  175. * any buffer we grab from the full list.
  176. *
  177. * fixes malloc() interrupted by SIGIO risk
  178. * (Bug 889)
  179. */
  180. rbuf = ISC_LIST_HEAD(free_recv_list);
  181. if (rbuf == NULL || buffer_shortfall > 0) {
  182. /*
  183. * try to get us some more buffers
  184. */
  185. create_buffers(RECV_INC);
  186. }
  187. #endif
  188. /*
  189. * try to grab a full buffer
  190. */
  191. rbuf = ISC_LIST_HEAD(full_recv_list);
  192. if (rbuf != NULL)
  193. {
  194. ISC_LIST_DEQUEUE(full_recv_list, rbuf, link);
  195. --full_recvbufs;
  196. }
  197. else
  198. {
  199. /*
  200. * Make sure we reset the full count to 0
  201. */
  202. full_recvbufs = 0;
  203. }
  204. UNLOCK();
  205. return (rbuf);
  206. }
  207. /*
  208. * Checks to see if there are buffers to process
  209. */
  210. isc_boolean_t has_full_recv_buffer(void)
  211. {
  212. if (ISC_LIST_HEAD(full_recv_list) != NULL)
  213. return (ISC_TRUE);
  214. else
  215. return (ISC_FALSE);
  216. }