rngLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:13k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* rngLib.c - ring buffer subroutine library */
  2. /* Copyright 1984-1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01x,13feb95,jdi  doc tweaks.
  8. 01w,20jan93,jdi  documentation cleanup for 5.1.
  9. 01v,26may92,rrr  the tree shuffle
  10. 01u,11jan92,wmd  fix bug spr #1210, race condition based on updates of buf
  11.  pointers in more than 1 place in rngBufPut() and rngBufGet().
  12. 01t,13dec91,gae  ANSI cleanup.
  13. 01s,04oct91,rrr  passed through the ansification filter
  14.                   -changed functions to ansi style
  15.   -changed VOID to void
  16.   -changed copyright notice
  17. 01r,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  18.  doc review by dnw.
  19. 01q,11mar91,jaa  documentation cleanup.
  20. 01p,11may90,yao  added missing modification history (01o) for the last checkin.
  21. 01o,09may90,yao  typecasted malloc to (char *).
  22. 01n,22mar89,dab  changed shorts to ints in rngBufGet, rngBufPut.
  23. 01m,03feb89,dab  added rngDelete to delete a ring buffer.
  24. 01l,20aug88,gae  documentation.
  25. 01k,07jul88,jcf  fixed malloc to match new declaration.
  26. 01j,30may88,dnw  changed to v4 names.
  27. 01i,03nov87,ecs  documentation.
  28. 01h,20oct87,gae  documentation.
  29. 01g,23mar87,jlf  documentation.
  30. 01f,21dec86,dnw  changed to not get include files from default directories.
  31. 01e,14apr86,rdc  changed memAllocates to mallocs.
  32. 01d,20jul85,jlf  documentation.
  33. 01c,09sep84,jlf  added comments and copyright.
  34. 01b,15aug84,dnw  changed rngBufCreate to allocate ring buffer one byte larger
  35.    than requested, because ring buffer algorithm always leaves
  36.    at least one empty byte in buffer.
  37.  added rngEmpty, rngFull, rngFreeBytes, rngNBytes, rngFlush,
  38.    rngPutAhead, rngMoveAhead, some of which used to be
  39.    macros in rngLib.h.
  40.  changed rngBufGet,rngBufPut to rngGetBuf,rngPutBuf.
  41.  changed rngBufCreate to rngCreate.
  42. 01a,06jun84,dnw  culled from old drvLib.c
  43. */
  44. /*
  45. This library provides routines for creating and using ring buffers, which
  46. are first-in-first-out circular buffers.  The routines simply manipulate
  47. the ring buffer data structure; no kernel functions are invoked.  In
  48. particular, ring buffers by themselves provide no task synchronization or
  49. mutual exclusion.
  50. However, the ring buffer pointers are manipulated in such a way that a
  51. reader task (invoking rngBufGet()) and a writer task (invoking
  52. rngBufPut()) can access a ring simultaneously without requiring mutual
  53. exclusion.  This is because readers only affect a f2readf1 pointer and
  54. writers only affect a f2writef1 pointer in a ring buffer data structure.
  55. However, access by multiple readers or writers f2mustfP be interlocked
  56. through a mutual exclusion mechanism (i.e., a mutual-exclusion semaphore
  57. guarding a ring buffer).
  58. This library also supplies two macros, RNG_ELEM_PUT and RNG_ELEM_GET,
  59. for putting and getting single bytes from a ring buffer.  They are defined
  60. in rngLib.h.
  61. .CS
  62.     int RNG_ELEM_GET (ringId, pch, fromP)
  63.     int RNG_ELEM_PUT (ringId, ch, toP)
  64. .CE
  65. Both macros require a temporary variable <fromP> or <toP>, which
  66. should be declared as `register int' for maximum efficiency.  RNG_ELEM_GET
  67. returns 1 if there was a character available in the buffer; it returns 0
  68. otherwise.  RNG_ELEM_PUT returns 1 if there was room in the buffer; it returns
  69. 0 otherwise.  These are somewhat faster than rngBufPut() and rngBufGet(),
  70. which can put and get multi-byte buffers.
  71. INCLUDE FILES: rngLib.h
  72. */
  73. /* LINTLIBRARY */
  74. #include "vxWorks.h"
  75. #include "memLib.h"
  76. #include "rngLib.h"
  77. #include "stdlib.h"
  78. #include "string.h"
  79. /*******************************************************************************
  80. *
  81. * rngCreate - create an empty ring buffer
  82. *
  83. * This routine creates a ring buffer of size <nbytes>, and initializes
  84. * it.  Memory for the buffer is allocated from the system memory partition.
  85. *
  86. * RETURNS
  87. * The ID of the ring buffer, or NULL if memory cannot be allocated.
  88. */
  89. RING_ID rngCreate
  90.     (
  91.     int nbytes          /* number of bytes in ring buffer */
  92.     )
  93.     {
  94.     char *buffer;
  95.     RING_ID ringId = (RING_ID) malloc (sizeof (RING));
  96.     if (ringId == NULL)
  97. return (NULL);
  98.     /* bump number of bytes requested because ring buffer algorithm
  99.      * always leaves at least one empty byte in buffer */
  100.     buffer = (char *) malloc ((unsigned) ++nbytes);
  101.     if (buffer == NULL)
  102. {
  103. free ((char *)ringId);
  104. return (NULL);
  105. }
  106.     ringId->bufSize = nbytes;
  107.     ringId->buf     = buffer;
  108.     rngFlush (ringId);
  109.     return (ringId);
  110.     }
  111. /*******************************************************************************
  112. *
  113. * rngDelete - delete a ring buffer
  114. *
  115. * This routine deletes a specified ring buffer.
  116. * Any data currently in the buffer will be lost.
  117. *
  118. * RETURNS: N/A
  119. */
  120. void rngDelete
  121.     (
  122.     FAST RING_ID ringId         /* ring buffer to delete */
  123.     )
  124.     {
  125.     free (ringId->buf);
  126.     free ((char *)ringId);
  127.     }
  128. /*******************************************************************************
  129. *
  130. * rngFlush - make a ring buffer empty
  131. *
  132. * This routine initializes a specified ring buffer to be empty.
  133. * Any data currently in the buffer will be lost.
  134. *
  135. * RETURNS: N/A
  136. */
  137. void rngFlush
  138.     (
  139.     FAST RING_ID ringId         /* ring buffer to initialize */
  140.     )
  141.     {
  142.     ringId->pToBuf   = 0;
  143.     ringId->pFromBuf = 0;
  144.     }
  145. /*******************************************************************************
  146. *
  147. * rngBufGet - get characters from a ring buffer
  148. *
  149. * This routine copies bytes from the ring buffer <rngId> into <buffer>.
  150. * It copies as many bytes as are available in the ring, up to <maxbytes>.
  151. * The bytes copied will be removed from the ring.
  152. *
  153. * RETURNS:
  154. * The number of bytes actually received from the ring buffer;
  155. * it may be zero if the ring buffer is empty at the time of the call.
  156. */
  157. int rngBufGet
  158.     (
  159.     FAST RING_ID rngId,         /* ring buffer to get data from      */
  160.     char *buffer,               /* pointer to buffer to receive data */
  161.     int maxbytes                /* maximum number of bytes to get    */
  162.     )
  163.     {
  164.     FAST int bytesgot = 0;
  165.     int pToBuf = rngId->pToBuf;
  166.     int bytes2;
  167.     int pRngTmp = 0;
  168.     if (pToBuf >= rngId->pFromBuf)
  169. {
  170. /* pToBuf has not wrapped around */
  171. bytesgot = min (maxbytes, pToBuf - rngId->pFromBuf);
  172. bcopy (&rngId->buf [rngId->pFromBuf], buffer, bytesgot);
  173. rngId->pFromBuf += bytesgot;
  174. }
  175.     else
  176. {
  177. /* pToBuf has wrapped around.  Grab chars up to the end of the
  178.  * buffer, then wrap around if we need to. */
  179. bytesgot = min (maxbytes, rngId->bufSize - rngId->pFromBuf);
  180. bcopy (&rngId->buf [rngId->pFromBuf], buffer, bytesgot);
  181. pRngTmp = rngId->pFromBuf + bytesgot;
  182. /* If pFromBuf is equal to bufSize, we've read the entire buffer,
  183.  * and need to wrap now.  If bytesgot < maxbytes, copy some more chars
  184.  * in now. */
  185. if (pRngTmp == rngId->bufSize)
  186.     {
  187.     bytes2 = min (maxbytes - bytesgot, pToBuf);
  188.     bcopy (rngId->buf, buffer + bytesgot, bytes2);
  189.     rngId->pFromBuf = bytes2;
  190.     bytesgot += bytes2;
  191.     }
  192. else
  193.     rngId->pFromBuf = pRngTmp;
  194. }
  195.     return (bytesgot);
  196.     }
  197. /*******************************************************************************
  198. *
  199. * rngBufPut - put bytes into a ring buffer
  200. *
  201. * This routine puts bytes from <buffer> into ring buffer <ringId>.  The
  202. * specified number of bytes will be put into the ring, up to the number of
  203. * bytes available in the ring.
  204. *
  205. * INTERNAL
  206. * Always leaves at least one byte empty between pToBuf and pFromBuf, to
  207. * eliminate ambiguities which could otherwise occur when the two pointers
  208. * are equal.
  209. *
  210. * RETURNS:
  211. * The number of bytes actually put into the ring buffer;
  212. * it may be less than number requested, even zero,
  213. * if there is insufficient room in the ring buffer at the time of the call.
  214. */
  215. int rngBufPut
  216.     (
  217.     FAST RING_ID rngId,         /* ring buffer to put data into  */
  218.     char *buffer,               /* buffer to get data from       */
  219.     int nbytes                  /* number of bytes to try to put */
  220.     )
  221.     {
  222.     FAST int bytesput = 0;
  223.     int pFromBuf = rngId->pFromBuf;
  224.     int bytes2;
  225.     int pRngTmp = 0;
  226.     if (pFromBuf > rngId->pToBuf)
  227. {
  228. /* pFromBuf is ahead of pToBuf.  We can fill up to two bytes
  229.  * before it */
  230. bytesput = min (nbytes, pFromBuf - rngId->pToBuf - 1);
  231. bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  232. rngId->pToBuf += bytesput;
  233. }
  234.     else if (pFromBuf == 0)
  235. {
  236. /* pFromBuf is at the beginning of the buffer.  We can fill till
  237.  * the next-to-last element */
  238. bytesput = min (nbytes, rngId->bufSize - rngId->pToBuf - 1);
  239. bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  240. rngId->pToBuf += bytesput;
  241. }
  242.     else
  243. {
  244. /* pFromBuf has wrapped around, and its not 0, so we can fill
  245.  * at least to the end of the ring buffer.  Do so, then see if
  246.  * we need to wrap and put more at the beginning of the buffer. */
  247. bytesput = min (nbytes, rngId->bufSize - rngId->pToBuf);
  248. bcopy (buffer, &rngId->buf [rngId->pToBuf], bytesput);
  249. pRngTmp = rngId->pToBuf + bytesput;
  250. if (pRngTmp == rngId->bufSize)
  251.     {
  252.     /* We need to wrap, and perhaps put some more chars */
  253.     bytes2 = min (nbytes - bytesput, pFromBuf - 1);
  254.     bcopy (buffer + bytesput, rngId->buf, bytes2);
  255.     rngId->pToBuf = bytes2;
  256.     bytesput += bytes2;
  257.     }
  258. else
  259.     rngId->pToBuf = pRngTmp;
  260. }
  261.     return (bytesput);
  262.     }
  263. /*******************************************************************************
  264. *
  265. * rngIsEmpty - test if a ring buffer is empty
  266. *
  267. * This routine determines if a specified ring buffer is empty.
  268. *
  269. * RETURNS:
  270. * TRUE if empty, FALSE if not.
  271. */
  272. BOOL rngIsEmpty
  273.     (
  274.     RING_ID ringId      /* ring buffer to test */
  275.     )
  276.     {
  277.     return (ringId->pToBuf == ringId->pFromBuf);
  278.     }
  279. /*******************************************************************************
  280. *
  281. * rngIsFull - test if a ring buffer is full (no more room)
  282. *
  283. * This routine determines if a specified ring buffer is completely full.
  284. *
  285. * RETURNS:
  286. * TRUE if full, FALSE if not.
  287. */
  288. BOOL rngIsFull
  289.     (
  290.     FAST RING_ID ringId         /* ring buffer to test */
  291.     )
  292.     {
  293.     int n = ringId->pToBuf - ringId->pFromBuf + 1;
  294.     return ((n == 0) || (n == ringId->bufSize));
  295.     }
  296. /*******************************************************************************
  297. *
  298. * rngFreeBytes - determine the number of free bytes in a ring buffer
  299. *
  300. * This routine determines the number of bytes currently unused in a specified
  301. * ring buffer.
  302. *
  303. * RETURNS: The number of unused bytes in the ring buffer.
  304. */
  305. int rngFreeBytes
  306.     (
  307.     FAST RING_ID ringId         /* ring buffer to examine */
  308.     )
  309.     {
  310.     FAST int n = ringId->pFromBuf - ringId->pToBuf - 1;
  311.     if (n < 0)
  312. n += ringId->bufSize;
  313.     return (n);
  314.     }
  315. /*******************************************************************************
  316. *
  317. * rngNBytes - determine the number of bytes in a ring buffer
  318. *
  319. * This routine determines the number of bytes currently in a specified
  320. * ring buffer.
  321. *
  322. * RETURNS: The number of bytes filled in the ring buffer.
  323. */
  324. int rngNBytes
  325.     (
  326.     FAST RING_ID ringId         /* ring buffer to be enumerated */
  327.     )
  328.     {
  329.     FAST int n = ringId->pToBuf - ringId->pFromBuf;
  330.     if (n < 0)
  331. n += ringId->bufSize;
  332.     return (n);
  333.     }
  334. /*******************************************************************************
  335. *
  336. * rngPutAhead - put a byte ahead in a ring buffer without moving ring pointers
  337. *
  338. * This routine writes a byte into the ring, but does not move the ring buffer
  339. * pointers.  Thus the byte will not yet be available to rngBufGet() calls.
  340. * The byte is written <offset> bytes ahead of the next input location in the
  341. * ring.  Thus, an offset of 0 puts the byte in the same position as would
  342. * RNG_ELEM_PUT would put a byte, except that the input pointer is not updated.
  343. *
  344. * Bytes written ahead in the ring buffer with this routine can be made available
  345. * all at once by subsequently moving the ring buffer pointers with the routine
  346. * rngMoveAhead().
  347. *
  348. * Before calling rngPutAhead(), the caller must verify that at least
  349. * <offset> + 1 bytes are available in the ring buffer.
  350. *
  351. * RETURNS: N/A
  352. */
  353. void rngPutAhead
  354.     (
  355.     FAST RING_ID ringId,   /* ring buffer to put byte in    */
  356.     char byte,             /* byte to be put in ring        */
  357.     int offset             /* offset beyond next input byte where to put byte */
  358.     )
  359.     {
  360.     FAST int n = ringId->pToBuf + offset;
  361.     if (n >= ringId->bufSize)
  362. n -= ringId->bufSize;
  363.     *(ringId->buf + n) = byte;
  364.     }
  365. /*******************************************************************************
  366. *
  367. * rngMoveAhead - advance a ring pointer by <n> bytes
  368. *
  369. * This routine advances the ring buffer input pointer by <n> bytes.  This makes
  370. * <n> bytes available in the ring buffer, after having been written ahead in
  371. * the ring buffer with rngPutAhead().
  372. *
  373. * RETURNS: N/A
  374. */
  375. void rngMoveAhead
  376.     (
  377.     FAST RING_ID ringId,  /* ring buffer to be advanced                  */
  378.     FAST int n            /* number of bytes ahead to move input pointer */
  379.     )
  380.     {
  381.     n += ringId->pToBuf;
  382.     if (n >= ringId->bufSize)
  383. n -= ringId->bufSize;
  384.     ringId->pToBuf = n;
  385.     }