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

VxWorks

开发平台:

C/C++

  1. /* rBuffLib.c - dynamic ring buffer (rBuff) library */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01z,20apr00,max  Change tid == NULL to tid == 0 (like in es.coretools)
  8. 01y,28aug98,dgp  FCS man page edit
  9. 01x,27aug98,dgp  add lib description, edit wvRBuffMgrPrioritySet() for manpgs
  10. 01w,18aug98,cjtc event buffer full handled more gracefully (SPR 22133)
  11. 01v,22jul98,cjtc optimise ring buffer scheme for windview (SPR 21752)
  12.  Avoids multiple rBuffMgr tasks (SPR 21805)
  13. 01u,30jun98,cjtc make priority of rBuffMgr task variable (SPR 21543)
  14. 01t,06may98,pr   fix wrong spell of portWorkQAdd1 for x86.
  15. 01t,01may98,nps  reworked msg passing for rBuff maintenance.
  16. 01s,26mar98,nps  fix 2 buffer / continuous upload problem.
  17. 01r,25mar98,pr   used portable portWorkQAdd1 only for the I80X86.
  18.                  moved portWorkQAdd1 into trgLib.c
  19. 01q,20mar98,pr   replaced workQAdd1 with portable version (for x86).
  20. 01p,19mar98,nps  only give upload threshold semaphore when necessary.
  21. 01o,13mar98,nps  added rBuffVerify.
  22. 01n,03mar98,nps  Source control structures from specfied source partition.
  23. 01m,21feb98,nps  Don't use msgQ fn to pass msgs - it causes problems when
  24.                  used with WV instrumentation.
  25. 01l,04feb98,nps  remove diagnostic messages.
  26. 01k,03feb98,nps  Changed msgQSend option from WAIT_FOREVER to NO_WAIT.
  27. 01j,12jan98,nps  Don't initialise rBuff multiple times.
  28. 01i,18dec97,cth  updated include files, added flushRtn init to rBuffCreate
  29. 01h,25nov97,nps  Tom's fix incorporated.
  30.                  Maintain statistic of peak buffer utilisation.
  31.                  Fix count of empty buffers.
  32. 01g,16nov97,cth  changed every public routine to accept generic buffer id,
  33.  described in buffer.h, rather than rBuffId.
  34.  added initialization for generic buffer id in rBuffCreate
  35. 01f,15Sep97,nps  rBuffShow moved out to its own file.
  36.                  SEMAPHOREs now init'd rather than created.
  37.                  added support for 'infinite' extension.
  38.                  added support for RBUFF_WRAPAROUND.
  39.                  buffers for ring are now added and freed by dedicated task.
  40. 01e,18Aug97,nps  fixed counting of emptyBuffs.
  41. 01d,18Aug97,nps  use semBGiveDefer to signal event upload.
  42. 01c,11Aug97,nps  rBuffReset now resets *all* buffers.
  43. 01b,28jul97,nps  further implementation/testing.
  44.                  rBuffReset returns STATUS type.
  45.                  added rBuffSetFd.
  46. 01a,14jul97,nps  written.
  47. */
  48. /*
  49. DESCRIPTION
  50. This library contains a routine for changing the default priority of the rBuff
  51. manager task.
  52. INTERNAL
  53. This library also contains the non-public routines creating and managing the
  54. dynamic ring buffer.  It provides both a WindView-specific version and a
  55. generic version.
  56. SEE ALSO: memLib, rngLib,
  57. .pG "Basic OS"
  58. */
  59. #undef RBUFF_DEBUG
  60. #ifndef  GENERIC_RBUFF
  61. /*
  62.  * Below this point the WindView specific version of the ring buffer
  63.  * library. In order to compile with the old (generic version of the
  64.  * ring buffer, you should use EXTRA_DEFINE='-DGENERIC_RBUFF' in the
  65.  * make command line, or #define GENERIC_RBUFF at the head of this
  66.  * file.
  67.  */
  68. #include "vxWorks.h"
  69. #include "semLib.h"
  70. #include "classLib.h"
  71. #include "errno.h"
  72. #include "intLib.h"
  73. #include "logLib.h"
  74. #include "taskLib.h"
  75. #include "fioLib.h"
  76. #include "rBuffLib.h"
  77. #include "private/wvBufferP.h"
  78. #include "private/classLibP.h"
  79. #include "private/objLibP.h"
  80. #include "private/workQLibP.h"
  81. #include "stdio.h"
  82. #include "string.h"
  83. #include "unistd.h"
  84. extern int wvRBuffMgr();
  85. #if (CPU_FAMILY == I80X86)
  86. extern void portWorkQAdd1();
  87. #endif
  88. /* locals */
  89. #if defined(__STDC__) || defined(__cplusplus)
  90. LOCAL STATUS rBuffAdd
  91.     (
  92.     RBUFF_ID  rBuff,
  93.     RBUFF_PTR buffToAdd
  94.     );
  95. LOCAL STATUS  rBuffFree
  96.     (
  97.     RBUFF_ID  rBuff,
  98.     RBUFF_PTR buffToFree
  99.     );
  100. LOCAL STATUS rBuffHandleEmpty
  101.     (
  102.     RBUFF_ID rBuff
  103.     );
  104. #else /* __STDC__ */
  105. LOCAL STATUS rBuffAdd();
  106. LOCAL STATUS rBuffFree();
  107. LOCAL STATUS rBuffHandleEmpty();
  108. #endif /* __STDC__ */
  109. extern  BOOL kernelState;
  110. #if (CPU_FAMILY == I80X86)
  111. #   define WQADD1 portWorkQAdd1
  112. #else /* CPU_FAMILY == I80X86 */
  113. #   define WQADD1 workQAdd1
  114. #endif
  115. #define RBUFF_SEND_MSG(RMSG_TYPE,RMSG_PRI,RB_ID,RMSG_PARAM)     
  116.     {     
  117.     if ((RB_ID)->nestLevel++ == 0)     
  118.      {     
  119.      BOOL doIt = TRUE ;     
  120.      if (RMSG_TYPE == RBUFF_MSG_ADD)      
  121.             {     
  122.     if ((RB_ID)->msgOutstanding)     
  123. {     
  124.      doIt = FALSE;     
  125.      }     
  126.     (RB_ID)->msgOutstanding = TRUE;     
  127.     }     
  128.      if (doIt)     
  129.          {     
  130.     WV_RBUFF_MGR_ID pMgr;     
  131.     pMgr = (WV_RBUFF_MGR_ID)(RB_ID)->rBuffMgrId;     
  132.     pMgr->msg[pMgr->msgWriteIndex].ringId = (RB_ID);     
  133.     pMgr->msg[pMgr->msgWriteIndex].msgType = RMSG_TYPE;       
  134.          pMgr->msg[pMgr->msgWriteIndex].arg = (UINT32) RMSG_PARAM;       
  135.                                                                    
  136.          if(++pMgr->msgWriteIndex > (WV_RBUFF_MGR_MSGQ_MAX - 1))         
  137.           {                                                           
  138.              pMgr->msgWriteIndex = 0;                              
  139.           }                                                           
  140.     
  141.          if(kernelState)     
  142.      {     
  143.              WQADD1 ((FUNCPTR)semCGiveDefer, (int)&pMgr->msgSem);        
  144.           }                                                           
  145.          else     
  146.           {     
  147.              semCGiveDefer (&pMgr->msgSem);          
  148.           }     
  149.     }     
  150.      }                                                                   
  151.     (RB_ID)->nestLevel--;     
  152.     }
  153. LOCAL BOOL   rBuffLibInstalled = FALSE;   /* protect from multiple inits */
  154. /* global variables */
  155. IMPORT BOOL  wvEvtBufferFullNotify; /* event buffer full notification */
  156. OBJ_CLASS rBuffClass;                   /* rBuff object Class */
  157. CLASS_ID  rBuffClassId = &rBuffClass;   /* rBuff class ID */
  158. WV_RBUFF_MGR_ID  wvRBuffMgrId = NULL;   /* WV rbuff mgr structure id */
  159. /*******************************************************************************
  160. *
  161. * rBuffLibInit - initialise the ring of buffers library
  162. *
  163. * This routine initialises the ring of buffers library. If INCLUDE_RBUFF is
  164. * defined in configAll.h, it is called by the root task, usrRoot(), in
  165. * usrConfig.c.
  166. *
  167. * NOMANUAL
  168. *
  169. * RETURNS: OK, or ERROR if the library could not be initialized.
  170. */
  171. STATUS rBuffLibInit (void)
  172.     {   
  173.     if (rBuffLibInstalled) 
  174.         {
  175.         return(TRUE);
  176.         }
  177.     /* Initialise the WindView rBuff Manager */
  178.     if ((wvRBuffMgrId = malloc (sizeof (WV_RBUFF_MGR_TYPE))) == NULL)
  179. return (ERROR);
  180.     wvRBuffMgrId->tid = 0;
  181.     wvRBuffMgrId->priorityDefault = WV_RBUFF_MGR_PRIORITY;
  182.     if (semCInit (&wvRBuffMgrId->msgSem, SEM_Q_PRIORITY, 0) == ERROR)
  183.         {
  184.         free (wvRBuffMgrId);
  185. wvRBuffMgrId = NULL;
  186.         return (ERROR);
  187.         }
  188.     wvRBuffMgrId->msgWriteIndex = 0;
  189.     wvRBuffMgrId->msgReadIndex = 0;
  190.     rBuffLibInstalled = TRUE;
  191.     /* initialize the rBuff class structure */
  192.     return (classInit (rBuffClassId,
  193.                 sizeof (RBUFF_TYPE),
  194.                 OFFSET (RBUFF_TYPE, buffDesc),
  195.                 (FUNCPTR) rBuffCreate,
  196.                 (FUNCPTR) NULL,
  197.                 (FUNCPTR) rBuffDestroy));
  198.     }
  199.  
  200. /*******************************************************************************
  201. *
  202. * rBuffCreate - create an extendable ring of buffers
  203. *
  204. * This routine creates an extendable ring of buffers from
  205. * the specified partition.
  206. *
  207. * NOMANUAL
  208. */
  209. BUFFER_ID rBuffCreate
  210.     (
  211.     void *Params
  212.     )
  213.     {
  214.     RBUFF_ID               rBuff;
  215.     UINT32                 count;
  216.     RBUFF_PTR              newBuff;
  217.     rBuffCreateParamsType *  rBuffCreateParams = Params;
  218.     if ((!rBuffLibInstalled) && (rBuffLibInit() == OK))
  219. {
  220. rBuffLibInstalled = TRUE;
  221. }
  222.     if (!rBuffLibInstalled)
  223.         {
  224. #ifdef RBUFF_DEBUG
  225.         logMsg ("rBuff: rBuffLib not installedn",0,0,0,0,0,0);
  226. #endif
  227.         return (NULL);
  228.         }
  229.     /* validate params */
  230.     if (rBuffCreateParams->minimum < 2 ||
  231.             ((rBuffCreateParams->minimum > rBuffCreateParams->maximum) ||
  232.                (rBuffCreateParams->maximum < 2 &&
  233.                 rBuffCreateParams->maximum != RBUFF_MAX_AVAILABLE)) ||
  234.             rBuffCreateParams->buffSize == 0)
  235.         {
  236. #ifdef RBUFF_DEBUG
  237.         logMsg ("rBuff: invalid paramsn",0,0,0,0,0,0);
  238. #endif
  239.         return (NULL);
  240.         }
  241.     /*
  242.      *  Set source partition for object class memory allocation
  243.      *  - note this only works overall if all rBuffs share a source
  244.      *    partition.
  245.      */
  246.     classMemPartIdSet(rBuffClassId,
  247.         rBuffCreateParams->sourcePartition);
  248.     /* allocate control structure */
  249.     rBuff = (RBUFF_ID) objAlloc (rBuffClassId);
  250.     if (rBuff == NULL)
  251.         {
  252. #ifdef RBUFF_DEBUG
  253.         logMsg ("rBuff: objAlloc failedn",0,0,0,0,0,0);
  254. #endif
  255.         return (NULL);
  256.         }
  257.     objCoreInit (&rBuff->buffDesc.objCore, rBuffClassId);
  258.     /* record parameters */
  259.     rBuff->info.srcPart   = rBuffCreateParams->sourcePartition;
  260.     rBuff->info.options   = rBuffCreateParams->options;
  261.     rBuff->info.buffSize  = rBuffCreateParams->buffSize;
  262.     rBuff->info.threshold = rBuffCreateParams->threshold;
  263.     rBuff->info.minBuffs  = rBuffCreateParams->minimum;
  264.     rBuff->info.maxBuffs  = (unsigned int) rBuffCreateParams->maximum;
  265.     rBuff->errorHandler   = rBuffCreateParams->errorHandler;
  266.     if (semBInit (&rBuff->buffDesc.threshXSem, SEM_Q_PRIORITY, 
  267.   SEM_EMPTY) == ERROR)
  268.         {
  269.         objFree (rBuffClassId, (UINT8 *) rBuff);
  270.         return (NULL);
  271.         }
  272.     if (semBInit (&rBuff->readBlk, SEM_Q_PRIORITY, SEM_FULL) == ERROR)
  273.         {
  274.         semTerminate (&rBuff->buffDesc.threshXSem);
  275.         objFree (rBuffClassId, (UINT8 *) rBuff);
  276.         return (NULL);
  277.         }
  278.     if (semBInit (&rBuff->bufferFull, SEM_Q_PRIORITY, SEM_EMPTY) == ERROR)
  279.         {
  280.         semTerminate (&rBuff->buffDesc.threshXSem);
  281.         semTerminate (&rBuff->readBlk);
  282.         objFree (rBuffClassId, (UINT8 *)rBuff);
  283.         return (NULL);
  284.         }
  285.     if (semCInit (&rBuff->msgSem, SEM_Q_PRIORITY, 0) == ERROR)
  286.         {
  287.         semTerminate (&rBuff->bufferFull);
  288.         semTerminate (&rBuff->buffDesc.threshXSem);
  289.         semTerminate (&rBuff->readBlk);
  290.         objFree (rBuffClassId, (UINT8 *)rBuff);
  291.         return (NULL);
  292.         }
  293.     rBuff->rBuffMgrId = 0; /* ...so we can use rBuffDestroy safely */
  294.     /*
  295.      *  If things go wrong from here, use rBuffDestroy to throw back what
  296.      *  we've caught.
  297.      */
  298.     /* allocate 'rBuffCreateParams->minimum' buffers */
  299.     rBuff->info.currBuffs  =
  300.     rBuff->info.emptyBuffs = 0;
  301.     rBuff->buffWrite = NULL;
  302.     for (count=0; count < rBuffCreateParams->minimum; count++)
  303.         {
  304.         /* First we need a buffer */
  305.         newBuff =
  306.             (RBUFF_PTR)
  307.                 memPartAlloc (rBuffCreateParams->sourcePartition,
  308.                 sizeof(RBUFF_BUFF_TYPE) + rBuffCreateParams->buffSize);
  309. #ifdef RBUFF_DEBUG
  310.         logMsg ("rBuff: adding buffer %p to ringn",newBuff,0,0,0,0,0);
  311. #endif
  312.         /* newBuff will be returned as NULL if source partition is exhausted */
  313.         /*  Don't need to lock ints around rBuffAdd as no-one knows about
  314.          *  this rBuff.
  315.          */
  316.         if ((newBuff == NULL) || (rBuffAdd (rBuff, newBuff) == ERROR))
  317.             {
  318. #ifdef RBUFF_DEBUG
  319.             logMsg ("rBuff: abandoned creationn",0,0,0,0,0,0);
  320. #endif
  321.             rBuffDestroy ((BUFFER_ID) rBuff);
  322.             return (NULL);
  323.             }
  324.         }
  325.     /*
  326.      * The first time around, spawn the rBuffMgr task. Once it exists,
  327.      * don't create another one. It should never be deleted. This bit is
  328.      * specific to WindView and will need attention for generic buffers
  329.      */
  330.     if (wvRBuffMgrId->tid == 0)
  331. {
  332.      wvRBuffMgrId->tid = taskSpawn (
  333.          "tWvRBuffMgr",
  334.          wvRBuffMgrId->priorityDefault,
  335.             WV_RBUFF_MGR_OPTIONS,
  336.             2048,
  337.             wvRBuffMgr,
  338.     (int)wvRBuffMgrId,
  339.             0,0,0,0,0,0,0,0,0);
  340. }
  341.     rBuff->rBuffMgrId = (int)wvRBuffMgrId;
  342.     if (wvRBuffMgrId->tid == 0)
  343.         {
  344. #ifdef RBUFF_DEBUG
  345.         logMsg ("rBuff: error creating wvRBuffMgrn",0,0,0,0,0,0);
  346. #endif
  347.         rBuffDestroy ((BUFFER_ID) rBuff);
  348.         return (NULL);
  349.         }
  350.     /* set control pointers */
  351.     rBuff->nestLevel = 0;
  352.     /* rBuff->buffWrite initialised by rBuffAdd */
  353.     rBuff->buffRead  = rBuff->buffWrite;
  354.     rBuff->dataWrite =
  355.     rBuff->dataRead  = rBuff->buffWrite->dataStart;
  356.     /* reset info */
  357.     rBuff->info.maxBuffsActual   = rBuffCreateParams->minimum;
  358.     rBuff->info.dataContent      =
  359.     rBuff->info.writesSinceReset =
  360.     rBuff->info.readsSinceReset  =
  361.     rBuff->info.timesExtended    =
  362.     rBuff->info.timesXThreshold  =
  363.     rBuff->info.bytesWritten     =
  364.     rBuff->info.bytesRead        =
  365.     rBuff->info.bytesPeak        = 0;
  366.     /* Reset msg passing mechanism */
  367.     rBuff->msgOutstanding        = FALSE;
  368.     rBuff->msgWriteIndex         =
  369.     rBuff->msgReadIndex          = 0;
  370.     /* now set up func ptrs allowing it to be called */
  371.     rBuff->buffDesc.readReserveRtn = (FUNCPTR) rBuffReadReserve;
  372.     rBuff->buffDesc.readCommitRtn  = (FUNCPTR) rBuffReadCommit;
  373.     rBuff->buffDesc.writeRtn       = rBuffWrite;
  374.     rBuff->buffDesc.flushRtn       = rBuffFlush;
  375.     rBuff->buffDesc.threshold      = rBuffCreateParams->threshold;
  376.     rBuff->buffDesc.nBytesRtn      = rBuffNBytes;
  377.     /* made it! */
  378. #ifdef RBUFF_DEBUG
  379.     logMsg("Created rBuff with ID %pn",rBuff,0,0,0,0,0);
  380. #endif
  381.     return ((BUFFER_ID) rBuff);
  382.     }
  383. int rBuffVerify 
  384.     (
  385.     BUFFER_ID rBuff
  386.     )
  387.     {
  388.     if (OBJ_VERIFY (rBuff, rBuffClassId) == OK) /* validate rBuff ID */
  389.         {
  390. return (OK);
  391.         }
  392.     else
  393. {
  394. return (ERROR);
  395. }
  396.     }
  397. /*******************************************************************************
  398. *
  399. * rBuffWrite - Write data to a ring of buffers
  400. *
  401. * This routine writes data to an extendable ring of buffers. If the existing
  402. * structure is full, and the existing number of buffers is less than the
  403. * specified minimum, then this function will attempt to add another buffer to
  404. * the ring.
  405. *
  406. * This function may be called from interrupt level.
  407. *
  408. * Mutually exclusive access must be guaranteed by the caller.
  409. *
  410. * NOMANUAL
  411. */
  412. UINT8* rBuffWrite
  413.     (
  414.     BUFFER_ID buffId, /* ring buffer id */
  415.     UINT8 *   pDummy, /* not used for WV ring buffer */
  416.     UINT32    numOfBytes /* number of bytes to reserve */
  417.     )
  418.     {
  419.     BOOL startUploading;
  420.     RBUFF_ID rBuff; /* access this particular rBuff */
  421.     UINT8 *returnPtr = (UINT8 *) ~0; /* Return a non-zero value if OK */
  422.     /* Get access to the private members of this buffer's descriptor. */
  423.     rBuff = (RBUFF_ID) buffId;
  424.     /* Get out early if this request makes no sense. */
  425.     if (numOfBytes > rBuff->info.buffSize)
  426.         {
  427.         return (NULL);
  428.         }
  429.     /* Critical Region Start */
  430.     if (rBuff->info.dataContent >= rBuff->info.threshold)
  431.         {
  432.         startUploading = TRUE;
  433.         }
  434.     else
  435.         {
  436.         startUploading = FALSE;
  437.         }
  438.     if (rBuff->buffWrite->spaceAvail >= numOfBytes)
  439.         {
  440.         /* Record the start of the reserved area */
  441.         returnPtr = rBuff->dataWrite;
  442.         /*
  443.          *  If we are consuming one of our precious empty buffs,
  444.          *  check we have enough in reserve.
  445.          */
  446.         if (rBuff->buffWrite->dataLen == 0) 
  447.             {
  448.             --rBuff->info.emptyBuffs;
  449.     }
  450. if (rBuff->info.emptyBuffs < RBUFF_EMPTY_KEEP &&
  451.             rBuff->info.currBuffs != rBuff->info.maxBuffs)
  452.             {
  453.             /* Schedule the rBuff Mgr to extend the buffer */
  454.             RBUFF_SEND_MSG (RBUFF_MSG_ADD, MSG_PRI_URGENT, rBuff, 0);
  455.     }
  456.         rBuff->buffWrite->dataLen    += numOfBytes;
  457.         rBuff->dataWrite             += numOfBytes;
  458.         rBuff->buffWrite->spaceAvail -= numOfBytes;
  459.         /*
  460.          *  It may be that the current buffer is full at this point,
  461.          *  but don't do anything about it yet as the situation will
  462.          *  be handled next time through. Also, it's possible that
  463.          *  the current buffer may even have been emptied by then.
  464.          */
  465.         }
  466.     else
  467.         {
  468.         /*
  469.          *  Data won't fit in this buffer (at least not entirely),
  470.          *  is the next buffer available?
  471.          */
  472.         if (rBuff->buffWrite->next == rBuff->buffRead)
  473.             {
  474.             /*  We've caught the reader. This will only happen when
  475.              *  we have actually filled the maximum allocation of
  476.              *  buffers *or* the reserved buffer has been filled
  477.              *  before the buffer has had the opportunity to
  478.              *  be extended. We cannot extend the buffer at this point
  479.              *  as we may be in a critical region, the design is such
  480.              *  that if the buffer could be extended it should have
  481.              *  been done by now (for that matter, the wrap-around
  482.              *  should have also occurred).
  483.              *
  484.              *  If we have filled the reserved buffer without having
  485.              *  the opportunity to extend the buffer then the buffer
  486.              *  is configured badly and must be retuned.
  487.              *
  488.              *  Meanwhile, at this moment, options are:
  489.              *
  490.              *  1) If we have filled the entire buffer and cannot wrap-
  491.              *     around then return ERROR.
  492.              *  2) If we have filled the entire buffer but can wrap-
  493.              *     around then do that.
  494.              */           
  495.             if (rBuff->info.options & RBUFF_WRAPAROUND)
  496.                 {
  497.                 /*
  498.                  *  OK, perform an inline ring extension supplying NULL
  499.                  *  as the new buffer forcing the ring to wrap-around.
  500.                  *  This is a deterministic action.
  501.                  */
  502.                 /* Interrupts already locked out */
  503.                 rBuffAdd(rBuff, NULL);
  504.                 }
  505.             else
  506.                 {
  507.                 /* Oh dear, can't wrap-round */
  508.              RBUFF_SEND_MSG (RBUFF_MSG_FULL, MSG_PRI_NORMAL, rBuff, 0);
  509. wvEvtBufferFullNotify = TRUE;
  510.                 return (NULL);
  511.                 }
  512.             }
  513.         /*
  514.          *  OK.
  515.          *  In the case that this function is writing the data, it
  516.          *  can be shared between this and next buffer.
  517.          *  In the case that we are only reserving the space, we must
  518.          *  return a pointer to contiguous space and therefore skip the
  519.          *  remainder of the previous buffer.
  520.          */
  521.         /* skip the remainder of the current buffer */
  522.         rBuff->buffWrite->spaceAvail = 0;
  523.         /* Move on to the next buffer */
  524.         rBuff->buffWrite = rBuff->buffWrite->next;
  525.         /* Record the start of the reserved area */
  526.         returnPtr = rBuff->buffWrite->dataStart;
  527.         /* Point dataWrite past the reserved area */
  528.         rBuff->dataWrite = rBuff->buffWrite->dataStart;
  529.         rBuff->buffWrite->dataLen    = numOfBytes;
  530.         rBuff->dataWrite            += numOfBytes;
  531.         rBuff->buffWrite->spaceAvail =
  532.             rBuff->info.buffSize - numOfBytes;
  533.         if (--rBuff->info.emptyBuffs < RBUFF_EMPTY_KEEP &&
  534.             rBuff->info.currBuffs != rBuff->info.maxBuffs)
  535.             {
  536.             /* Schedule the rBuff Mgr to extend the buffer */
  537.             RBUFF_SEND_MSG (RBUFF_MSG_ADD, MSG_PRI_URGENT, rBuff, 0);
  538.             }
  539.         }
  540.     rBuff->info.dataContent  += numOfBytes;
  541.     /* update info */
  542.     if(rBuff->info.dataContent > rBuff->info.bytesPeak)
  543.         {
  544.         rBuff->info.bytesPeak = rBuff->info.dataContent;
  545.         }
  546.     rBuff->info.bytesWritten += numOfBytes;
  547.     rBuff->info.writesSinceReset++;
  548.     if (!startUploading && rBuff->info.dataContent >= rBuff->info.threshold)
  549.         {
  550.         rBuff->info.timesXThreshold++;
  551.         if (!(rBuff->info.options & RBUFF_UP_DEFERRED))
  552.             {
  553.             /*
  554.              *  Signal for uploading to begin. Note that if we have just
  555.              *  reserved space it is imperative that uploading does not
  556.              *  actually begin until the data is in the buffer.
  557.              */
  558. #if (CPU_FAMILY == I80X86)
  559.             portWorkQAdd1 ((FUNCPTR)semBGiveDefer,
  560.                 (int) &rBuff->buffDesc.threshXSem);
  561. #else
  562.             workQAdd1 ((FUNCPTR)semBGiveDefer,
  563.                 (int) &rBuff->buffDesc.threshXSem);
  564. #endif
  565.             }
  566.         }
  567.     /* Critical Region End */
  568.     return (returnPtr);
  569.     }
  570. /*******************************************************************************
  571. *
  572. * rBuffRead - Read data from a ring of buffers
  573. *
  574. * This routine reads data from an extendable ring of buffers.
  575. *
  576. * This function assumes mutually exclusive access is guaranteed by the caller.
  577. *
  578. * NOMANUAL
  579. */
  580. INT32 rBuffRead
  581.     (
  582.     BUFFER_ID  buffId, /* generic buffer descriptor */
  583.     UINT8 *    dataDest,
  584.     UINT32   numOfBytes
  585.     )
  586.     {
  587.     UINT32  bytesToCopy;
  588.     UINT32 remaining = numOfBytes;
  589.     RBUFF_ID  rBuff; /* access private members of this rBuff desc */
  590.     /* Get access to the private members of this particular rBuff. */
  591.     rBuff = (RBUFF_ID) buffId;
  592.     /* Critical Region Start */
  593.     while (remaining > 0)
  594.         {
  595.         bytesToCopy = (rBuff->buffRead->dataLen < remaining ?
  596.                         rBuff->buffRead->dataLen : remaining);
  597.         if (bytesToCopy > 0)
  598.             {
  599.             memcpy (dataDest,rBuff->dataRead,bytesToCopy);
  600.             remaining                -= bytesToCopy;
  601.             dataDest                 += bytesToCopy;
  602.             /* Update buffer */
  603.             rBuff->buffRead->dataLen -= bytesToCopy;
  604.             rBuff->dataRead          += bytesToCopy;
  605.             rBuff->info.dataContent  -= bytesToCopy;
  606.             }
  607.         if (rBuff->buffRead->dataLen != 0)
  608.             {
  609.             /* This buffer is now empty */
  610.             rBuffHandleEmpty (rBuff);
  611.             }
  612.         else
  613.             {
  614.             /* this buffer is not yet emptied */
  615.             rBuff->dataRead += bytesToCopy;
  616.             }
  617.         }
  618.     /* update info */
  619.     rBuff->info.bytesRead += (numOfBytes - remaining);
  620.     rBuff->info.readsSinceReset++;
  621.     /* Critical Region End */
  622.     return (numOfBytes - remaining);
  623.     }
  624. /*******************************************************************************
  625. *
  626. * rBuffReadReserve - Return the number of contiguous bytes available for
  627. *                    reading.
  628. *
  629. * NOMANUAL
  630. */
  631. UINT32 rBuffReadReserve
  632.     (
  633.     BUFFER_ID buffId, /* generic identifier for this buffer */
  634.     UINT8 **src
  635.     )
  636.     {
  637.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  638.     INT32 bytesAvailable; 
  639.     /* Get access to the private members of this particular rBuff. */
  640.     rBuff = (RBUFF_ID) buffId;
  641.     /* Generate and return the available contiguous bytes. */
  642.     if ((bytesAvailable = rBuff->buffRead->dataLen))
  643.         {
  644.         *src = rBuff->dataRead;
  645.         }
  646.     else
  647.         {
  648.         *src = NULL;
  649.         }
  650.     return (bytesAvailable);
  651.     }
  652. /*******************************************************************************
  653. *
  654. * rBuffReadCommit - Move the read data ptr along a ring of buffers
  655. *
  656. * This routine moves the data ptr along a ring of buffers.
  657. *
  658. * It is equivalent to reading data from the buffers and should be used
  659. * when the data has been copied elsewhere.
  660. *
  661. * This function assumes mutually exclusive access is guaranteed by the caller.
  662. *
  663. * NOMANUAL
  664. */
  665. STATUS rBuffReadCommit
  666.     (
  667.     BUFFER_ID buffId, /* generic identifier for this buffer */
  668.     UINT32  numOfBytes
  669.     )
  670.     {
  671.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  672.     /* Get access to the private members of this particular rBuff. */
  673.     if (!numOfBytes)
  674.     {
  675.         return (OK);
  676.     }
  677.     rBuff = (RBUFF_ID) buffId;
  678.     /* Critical Region Start */
  679.     if (numOfBytes == rBuff->buffRead->dataLen)
  680.         {
  681.         rBuffHandleEmpty (rBuff);
  682.         }
  683.     else if (numOfBytes < rBuff->buffRead->dataLen)
  684.         {
  685.         rBuff->buffRead->dataLen -= numOfBytes;
  686.         rBuff->dataRead += numOfBytes;
  687.         }
  688.     else
  689.         {
  690.         /* Moving ahead through multiple buffers */
  691.         /* Not yet supported */
  692.         return(ERROR);
  693.         }
  694.     rBuff->info.dataContent -= numOfBytes;
  695.     /* update info */
  696.     rBuff->info.bytesRead += numOfBytes;
  697.     rBuff->info.readsSinceReset++;
  698.     /* Critical Region End */
  699.     return (OK);
  700.     }
  701. /*******************************************************************************
  702. *
  703. * rBuffFlush - Flush data from a ring of buffers
  704. *
  705. * This routine causes any data held in a buffer to be uploaded and is
  706. * used to clear data that falls below the specified threshold.
  707. *
  708. * NOMANUAL
  709. */
  710. STATUS rBuffFlush
  711.     (
  712.     BUFFER_ID buffId /* generic identifier for this buffer */
  713.     )
  714.     {
  715.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  716.     int result, originalThreshold;
  717.     /* Get access to the private members of this particular rBuff. */
  718.     rBuff = (RBUFF_ID) buffId;
  719.     result = OK;
  720.     if (!rBuff->info.dataContent)
  721.         {
  722.         return(OK);
  723.         }
  724.     /* Store the original threshold */
  725.     originalThreshold = rBuff->info.threshold;
  726.     rBuff->info.threshold = 0;
  727.     while (rBuff->info.dataContent > 0 && result != ERROR)
  728.         {
  729.         if (semGive (&rBuff->buffDesc.threshXSem) == OK)
  730.             {
  731.             /* Cause a reschedule to allow uploader in */
  732.             taskDelay(0);
  733.             }
  734.         else
  735.             {
  736.             result = ERROR;
  737.             }
  738.         }
  739.     rBuff->info.threshold = originalThreshold;
  740.     return(result);
  741. }
  742. /*******************************************************************************
  743. *
  744. * rBuffReset - reset an extendable ring of buffers
  745. *
  746. * This routine resets an already created extendable ring of buffers to its
  747. * initial state. This loses any data held in the buffer. Any buffers held
  748. * above the specified minimum number are deallocated.
  749. *
  750. * NOMANUAL
  751. */
  752. STATUS rBuffReset
  753.     (
  754.     BUFFER_ID buffId /* generic identifier for this buffer */
  755.     )
  756.     {
  757.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  758.     RBUFF_LOCK (rBuff);
  759.     /* Get access to the private members of this particular rBuff. */
  760.     rBuff = (RBUFF_ID) buffId;
  761.     /* Now reset the ring of buffers. */
  762.     if (rBuff->info.currBuffs > rBuff->info.minBuffs)
  763.         {
  764.         UINT32 excessBuffs, count;
  765.         /* drop the excess buffers */
  766.         excessBuffs = rBuff->info.currBuffs - rBuff->info.minBuffs;
  767.         for (count=0;count < excessBuffs;count++)
  768.             {
  769.             RBUFF_PTR tempPtr;
  770.             tempPtr = rBuff->buffWrite->next; /* should not be NULL! */
  771.             rBuffFree (rBuff,rBuff->buffWrite);
  772.             rBuff->buffWrite = tempPtr;
  773.             }
  774.         }
  775.     /* Make sure the 'read' buffer pointer points somewhere sensible */
  776.     rBuff->buffRead = rBuff->buffWrite;
  777.     /* and reset the byte ptrs */
  778.     rBuff->dataRead         =
  779.     rBuff->dataWrite        = rBuff->buffWrite->dataStart;
  780.     rBuff->info.currBuffs        =
  781.     rBuff->info.maxBuffsActual   = rBuff->info.minBuffs;
  782.     /* now traverse the ring resetting the individual buffers */
  783.     {
  784.     RBUFF_PTR backHome = rBuff->buffWrite;
  785.     RBUFF_PTR currBuff = rBuff->buffWrite;
  786.     do
  787.       {
  788.         currBuff->dataLen    = 0;
  789.         currBuff->spaceAvail = rBuff->info.buffSize;
  790.         currBuff = currBuff->next;
  791.         }
  792.     while (currBuff != backHome);
  793.     }
  794.     /* Reset msg passing mechanism */
  795.     rBuff->msgOutstanding        = FALSE;
  796.     rBuff->msgWriteIndex         =
  797.     rBuff->msgReadIndex          = 0;
  798.     rBuff->nestLevel = 0;
  799.     /* reset info */
  800.     rBuff->info.emptyBuffs       = rBuff->info.minBuffs;
  801.     rBuff->info.dataContent      =
  802.     rBuff->info.writesSinceReset =
  803.     rBuff->info.readsSinceReset  =
  804.     rBuff->info.timesExtended    =
  805.     rBuff->info.timesXThreshold  =
  806.     rBuff->info.bytesWritten     =
  807.     rBuff->info.bytesRead        = 0;
  808.     semGive (&rBuff->bufferFull);
  809.     RBUFF_UNLOCK (rBuff);
  810.     return (OK);
  811. }
  812. /*******************************************************************************
  813. *
  814. * rBuffNBytes - Returns the total number of bytes held in a ring of buffers
  815. *
  816. * NOMANUAL
  817. */
  818. INT32 rBuffNBytes
  819.     (
  820.     BUFFER_ID buffId /* generic identifier for this buffer */
  821.     )
  822.     {
  823.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  824.     /* Get access to the private members of this particular rBuff. */
  825.     rBuff = (RBUFF_ID) buffId;
  826.     return (rBuff->info.dataContent);
  827.     }
  828. /*******************************************************************************
  829. *
  830. * rBuffAdd - Add a new buffer to an extendable ring of buffers
  831. *
  832. * This routine adds a further buffer to an already created or partially created
  833. * extendable ring of buffers unless the maximum number is already allocated.
  834. *
  835. * This function assumes mutually exclusive access is guaranteed by the caller.
  836. *
  837. * NOMANUAL
  838. */
  839. STATUS rBuffAdd
  840.     (
  841.     RBUFF_ID  rBuff,
  842.     RBUFF_PTR  newBuff
  843.     )
  844.     {
  845.     if (rBuff->info.emptyBuffs >= RBUFF_EMPTY_KEEP &&
  846.         rBuff->info.currBuffs  >= rBuff->info.minBuffs)
  847.         {
  848.         /*
  849.          *  OK, the uploader got in so now we don't need to extend the
  850.          *  buffer.
  851.          */
  852. #ifdef RBUFF_DEBUG
  853.         logMsg ("rBuff: abandoned addn",0,0,0,0,0,0);
  854. #endif
  855.         if (newBuff)
  856.             {
  857.             memPartFree (rBuff->info.srcPart, (UINT8 *) newBuff);
  858.             }
  859.         return (OK);
  860.         }
  861.     if (rBuff->info.currBuffs == rBuff->info.maxBuffs || newBuff == NULL)
  862.         {
  863.         /*
  864.          *  We are at the maximum ring size already or the source
  865.          *  partition is exhausted, there's still hope...
  866.          *
  867.          *  ...can we wrap-around?
  868.          */
  869.         if (!(rBuff->info.options & RBUFF_WRAPAROUND))
  870.             {
  871.             /* We aren't allowed to wrap around */
  872.             return (ERROR);
  873.             }
  874.         else
  875.             {
  876.             RBUFF_PTR reclaim;
  877.             /*  We can wrap around by comandeering the 'oldest'
  878.              *  buffer in the ring.
  879.              *
  880.              *  It is possible (probable?) that this buffer is the
  881.              *  one to be read from next so handle this.
  882.              */
  883.             reclaim = rBuff->buffWrite->next;
  884.             if (rBuff->buffRead == reclaim)
  885.                 {
  886.                 /* Move the reader along */
  887.                 rBuff->buffRead = rBuff->buffRead->next;
  888.                 rBuff->dataRead = rBuff->buffRead->dataStart;
  889.                 }
  890.             rBuff->info.dataContent  -= reclaim->dataLen;
  891.             /* Reset the buffer */
  892.             reclaim->dataLen    = 0;
  893.             reclaim->spaceAvail = rBuff->info.buffSize;
  894.             rBuff->info.emptyBuffs++;
  895.             return (OK);
  896.             }
  897.         }
  898.     newBuff->dataStart  = (UINT8 *) newBuff + sizeof(RBUFF_BUFF_TYPE);
  899.     newBuff->dataEnd    = newBuff->dataStart + rBuff->info.buffSize;
  900.     newBuff->spaceAvail = rBuff->info.buffSize;
  901.     newBuff->dataLen    = 0;
  902.     /* Now link the buffer into the ring */
  903.     if (rBuff->buffWrite != NULL)
  904.         {
  905.         RBUFF_PTR tempPtr;
  906.         tempPtr = rBuff->buffWrite->next;
  907.         rBuff->buffWrite->next = newBuff;
  908.         /* close the ring */
  909.         newBuff->next = tempPtr;
  910.         }
  911.     else
  912.         {
  913.         /* ring is empty, must be creation time */
  914.         rBuff->buffWrite =
  915.         rBuff->buffRead  =
  916.         newBuff->next    = newBuff;
  917.         }
  918.     /* Maintain statistics */
  919.     if (++(rBuff->info.currBuffs) > rBuff->info.maxBuffsActual)
  920.         {
  921.         rBuff->info.maxBuffsActual++;
  922.         }
  923.     rBuff->info.timesExtended++;
  924.     rBuff->info.emptyBuffs++;
  925.     return (OK);
  926. }
  927. /*******************************************************************************
  928. *
  929. * rBuffFree - Free a specified buffer
  930. *
  931. * This function must only be called from task level.
  932. * Semaphores are used to protect access at task-level. However, protection
  933. * from access at interrupt level must be guaranteed by the caller.
  934. *
  935. * NOMANUAL
  936. */
  937. STATUS rBuffFree
  938.     (
  939.     RBUFF_ID  rBuff,
  940.     RBUFF_PTR  buffToFree
  941.     )
  942.     {
  943.     RBUFF_PTR  ptrToBuff, backHome, ptrToPreviousBuff;
  944.     if (buffToFree == NULL)
  945.         {
  946.         return(ERROR);
  947.         }
  948.     /* find the pointer to the buffer to be freed */
  949.     ptrToBuff         = rBuff->buffWrite->next;
  950.     backHome          = rBuff->buffWrite;
  951.     ptrToPreviousBuff = rBuff->buffWrite;
  952.     while ((ptrToBuff != buffToFree) && (ptrToBuff != backHome))
  953.         {
  954.         ptrToPreviousBuff = ptrToBuff;
  955.         ptrToBuff         = buffToFree;
  956.         }
  957.     if (ptrToBuff == backHome)
  958.         {
  959.         /* an error has occured, possibly invalid buff ptr passed */
  960.         return (ERROR);
  961.         }
  962.     /* OK, de-link the buffer to be freed */
  963.     ptrToPreviousBuff->next = buffToFree->next;
  964.     /* Schedule the rBuff Mgr to actually free the buffer */
  965.     RBUFF_SEND_MSG (RBUFF_MSG_FREE, MSG_PRI_NORMAL, rBuff, buffToFree);
  966.     /* Maintain statistics */
  967.     rBuff->info.emptyBuffs--;
  968.     rBuff->info.currBuffs--;
  969.     return (OK);
  970.     }
  971. /*******************************************************************************
  972. *
  973. * rBuffDestroy - Destroy an extendable ring of buffers
  974. *
  975. * This routine destroys an already created or partially created extendable ring
  976. * of buffers. This loses any data held in the buffer. All resources held are
  977. * returned to the system.
  978. *
  979. * NOMANUAL
  980. */
  981. STATUS rBuffDestroy
  982.     (
  983.     BUFFER_ID  buffId /* generic identifier for this buffer */
  984.     )
  985.     {
  986.     RBUFF_ID  rBuff; /* specific identifier for this rBuff */
  987.     RBUFF_PTR  tempPtr;
  988.     /* Get access to the private members of this particular rBuff. */
  989.     rBuff = (RBUFF_ID) buffId;
  990.     RBUFF_LOCK (rBuff);
  991. #if 0
  992.     if (OBJ_VERIFY (rBuff, rBuffClassId) != OK) /* validate rBuff ID */
  993. {
  994. ((OBJ_ID)rBuff)->pObjClass, rBuffClassId);
  995. RBUFF_UNLOCK (rBuff);
  996. return (ERROR);
  997. }
  998. #endif
  999.     objCoreTerminate (&rBuff->buffDesc.objCore);   /* invalidate this object */
  1000.     /* Break the ring and traverse the list, freeing off   */
  1001.     /* the buffers. buffWrite is used as the start point   */
  1002.     /* this works if the ring creation is abandoned early. */
  1003.     if (rBuff->buffWrite != NULL)
  1004.         {
  1005.         /* Break the ring */
  1006.         tempPtr = rBuff->buffWrite->next;
  1007.         rBuff->buffWrite->next = NULL;
  1008.         rBuff->buffWrite = tempPtr;
  1009.         /* traverse and free */
  1010.         while(rBuff->buffWrite != NULL)
  1011.             {
  1012.             tempPtr = rBuff->buffWrite->next;
  1013.             memPartFree (rBuff->info.srcPart,(UINT8 *)rBuff->buffWrite);
  1014.             rBuff->buffWrite = tempPtr;
  1015.             }
  1016.         }
  1017.     else
  1018.         {
  1019.         /* ring hasn't been created so don't worry about it */
  1020.         }
  1021.     /* now free off the control structure */
  1022.     semTerminate (&rBuff->buffDesc.threshXSem);
  1023.     semTerminate (&rBuff->readBlk);
  1024.     semTerminate (&rBuff->bufferFull);
  1025.     objFree (rBuffClassId, (UINT8 *) rBuff);
  1026.     /* we're done */
  1027.     return (OK);
  1028.     }
  1029. /*******************************************************************************
  1030. *
  1031. * rBuffSetFd - Set a new fd as the data upload destination
  1032. *
  1033. *
  1034. * NOMANUAL
  1035. */
  1036. STATUS rBuffSetFd
  1037.     (
  1038.     BUFFER_ID  buffId, /* generic identifier for this buffer */
  1039.     int  fd
  1040.     )
  1041.     {
  1042.     RBUFF_ID  rBuff; /* specific identifier for this rBuff */
  1043.     RBUFF_LOCK (rBuff);
  1044.     /* Get access to the private members of this particular rBuff. */
  1045.     rBuff = (RBUFF_ID) buffId;
  1046.     rBuff->fd = fd;
  1047.     RBUFF_UNLOCK (rBuff);
  1048.     return (OK);
  1049.     }
  1050. /*******************************************************************************
  1051. *
  1052. * rBuffHandleEmpty - Handles a newly empty buffer by deciding whether to free
  1053. *                    it off.
  1054. *
  1055. * This function assumes mutually exclusive access is guaranteed by the caller.
  1056. *
  1057. * NOMANUAL
  1058. */
  1059. LOCAL STATUS rBuffHandleEmpty
  1060.     (
  1061.     RBUFF_ID rBuff
  1062.     )
  1063.     {
  1064.     BOOL      moveAlong = TRUE;
  1065.     RBUFF_PTR buffToFree;
  1066.     /*
  1067.      *  Determine if we are to move around the ring and if the
  1068.      *  newly empty buffer is to be freed, and then do the actions.
  1069.      *  This avoids having to fumble with ptrs as we move around
  1070.      *  from a buffer that has been freed.
  1071.      */
  1072.     if (rBuff->buffRead == rBuff->buffWrite)
  1073.         {
  1074.         /*
  1075.          *  We've caught the writer so might as well reset this
  1076.          *  buffer and make efficient use of it.
  1077.          */
  1078.         rBuff->dataRead  =
  1079.             rBuff->dataWrite = rBuff->buffWrite->dataStart;
  1080.         rBuff->buffRead->spaceAvail = rBuff->info.buffSize;
  1081.         rBuff->buffRead->dataLen     = 0;
  1082.         /* In this case, we don't move along to the next buffer */
  1083.         moveAlong = FALSE;
  1084.         }
  1085.     if (++(rBuff->info.emptyBuffs) > RBUFF_EMPTY_KEEP &&
  1086.            rBuff->info.currBuffs > rBuff->info.minBuffs)
  1087.         {
  1088.         /* We already have enough empty buffs, so free one off */
  1089.         if (rBuff->buffRead != rBuff->buffWrite)
  1090.             {
  1091.             buffToFree = rBuff->buffRead;
  1092.             }
  1093.         else
  1094.             {
  1095.             /*
  1096.              *  As the reader and writer are in the same buffer
  1097.              *  we know it's safe to free off the next buffer.
  1098.              */
  1099.             buffToFree = rBuff->buffRead->next;
  1100.             }
  1101.         }
  1102.     else
  1103.         {
  1104.         /* we've just emptied one of the 'core' buffers */
  1105.         rBuff->buffRead->spaceAvail = rBuff->info.buffSize;
  1106.         rBuff->buffRead->dataLen    = 0;
  1107.         /* Don't free */
  1108.         buffToFree = NULL;
  1109.         }
  1110.     if (moveAlong)
  1111.         {
  1112.         /* Move round the ring */
  1113.         rBuff->buffRead = rBuff->buffRead->next;
  1114.         rBuff->dataRead = rBuff->buffRead->dataStart;
  1115.         }
  1116.     else
  1117.         {
  1118.         /* reset flag for next time */
  1119.         moveAlong = TRUE;
  1120.         }
  1121.     if (/* there's a */ buffToFree)
  1122.         {
  1123. #ifdef RBUFF_DEBUG
  1124.         logMsg ("rBuff: Freeing buffer %pn",
  1125.             buffToFree,0,0,0,0,0);
  1126. #endif
  1127.         rBuffFree (rBuff, buffToFree);
  1128.         }
  1129.     return (OK);
  1130.     }
  1131. /*******************************************************************************
  1132. *
  1133. * wvRBuffMgr - The function is spawned as a task to manage WV rBuff extension.
  1134. *
  1135. * It waits for a msg which carries the ID of a buffer which has had a change
  1136. * of the number of empty buffers held. If there are less the requested to be
  1137. * reserved than an attempt will be made to make more available. If there are
  1138. * more empty buffers than required than some will be freed.
  1139. *
  1140. * For each msg received, the task will achieve the required number of free
  1141. * buffers. This may result in redundant msgs being received.
  1142. *
  1143. * This manager is specific to WindView
  1144. *
  1145. * NOMANUAL
  1146. */
  1147. int wvRBuffMgr
  1148.     (
  1149.     WV_RBUFF_MGR_TYPE * rBuffMgrId  /* id of the WindView rBuffMgr structure */
  1150.     )
  1151.     {
  1152.     UINT32      busy;
  1153.     int                key;
  1154.     RBUFF_PTR          newBuff;
  1155.     WV_RBUFF_MGR_MSG_TYPE*  pMsg;
  1156. #ifdef RBUFF_DEBUG
  1157.         logMsg ("rBuffMgr %p createdn",rBuffMgrId,0,0,0,0,0);
  1158. #endif
  1159.     for(;;)
  1160.         {
  1161. semTake (&(rBuffMgrId->msgSem), WAIT_FOREVER);
  1162. pMsg = &(rBuffMgrId->msg[rBuffMgrId->msgReadIndex]);
  1163. #ifdef RBUFF_DEBUG
  1164.         logMsg ("rBuffMgr: (%d) rBuff %p type 0x%x arg 0x%xn",
  1165. rBuffMgrId->msgReadIndex,
  1166.                 pMsg->ringId, 
  1167.                 pMsg->msgType, 
  1168.                 pMsg->arg, 
  1169.                 0, 0);
  1170. #endif
  1171.         busy = TRUE;
  1172.         /* Determine what needs to be done */
  1173.         switch (pMsg->msgType)
  1174.             {
  1175.             case RBUFF_MSG_ADD :
  1176.                 {
  1177.                 /*
  1178.                  *  This message may be generated one or more times by
  1179.                  *  event logging, and the condition that caused the msg
  1180.                  *  may no longer be TRUE, so just take this as a prompt
  1181.                  *  to see if the ring needs extending.
  1182.                  */
  1183.                 /* Make sure that we don't request extension recursively */
  1184.                 pMsg->ringId->nestLevel++;
  1185.                 while
  1186.                     (pMsg->ringId->info.emptyBuffs < RBUFF_EMPTY_KEEP &&
  1187.                     (pMsg->ringId->info.currBuffs  < pMsg->ringId->info.maxBuffs ||
  1188.                         pMsg->ringId->info.options & RBUFF_WRAPAROUND) &&
  1189.                     busy)
  1190.                     {
  1191.                     /* Looks like we are going to need a buffer */
  1192.                     newBuff = (RBUFF_PTR)
  1193.                         memPartAlloc (pMsg->ringId->info.srcPart,
  1194.                             sizeof(RBUFF_BUFF_TYPE) + pMsg->ringId->info.buffSize);
  1195.                     /* of course, newBuff may be NULL... */
  1196.                     key = intLock();
  1197. #ifdef RBUFF_DEBUG
  1198.                     logMsg ("rBuffMgr: adding buffer %pn",newBuff,0,0,0,0,0);
  1199. #endif
  1200.     if (rBuffAdd (pMsg->ringId, newBuff) == ERROR)
  1201.                         {
  1202.                         /* ring cannot be extended so give up trying */
  1203.                         busy = FALSE;
  1204.                         }
  1205.                     intUnlock (key);
  1206.                     }
  1207.                 }
  1208.                 pMsg->ringId->nestLevel--;
  1209.             break;
  1210.             case RBUFF_MSG_FREE :
  1211.                 {
  1212.                 /* This message carries a ptr to the buffer to be freed */
  1213. #ifdef RBUFF_DEBUG
  1214.                 logMsg ("rBuffMgr: freeing buffer %pn", pMsg->arg, 0,0,0,0,0);
  1215. #endif
  1216.                 memPartFree (pMsg->ringId->info.srcPart, (UINT8 *) pMsg->arg);
  1217.                 }
  1218.             break;
  1219.             case RBUFF_MSG_FULL :
  1220.      logMsg ("Ring Buffer %p full. Stopped event logging.n",
  1221.              (unsigned int)pMsg->ringId,0,0,0,0,0);
  1222.     break;
  1223.     default :
  1224.                 logMsg ("Unknown message type %dn", pMsg->msgType, 0,0,0,0,0);
  1225.     break;
  1226.             }
  1227.          if (++rBuffMgrId->msgReadIndex > (WV_RBUFF_MGR_MSGQ_MAX - 1))
  1228.              {
  1229.              rBuffMgrId->msgReadIndex = 0;
  1230.              }
  1231.          pMsg->ringId->msgOutstanding = FALSE;
  1232.          }
  1233.     }
  1234. /*******************************************************************************
  1235. *
  1236. * wvRBuffMgrPrioritySet - set the priority of the WindView rBuff manager (WindView)
  1237. *
  1238. * This routine changes the priority of the `tWvRBuffMgr' task to the value of 
  1239. * <priority>.  Priorities range from 0, the highest priority, to 255, the
  1240. * lowest priority.  If the task is not yet running, this priority is
  1241. * used when it is spawned.
  1242. * RETURNS: OK, or ERROR if the priority can not be set.
  1243. *
  1244. * SEE ALSO: taskPrioritySet(),
  1245. * .pG "Basic OS"
  1246. */
  1247. STATUS wvRBuffMgrPrioritySet
  1248.     (
  1249.     int      priority           /* new priority */
  1250.     )
  1251.     {
  1252.     if (!rBuffLibInstalled)
  1253.         {
  1254.      if (rBuffLibInit() == OK)
  1255.     rBuffLibInstalled = TRUE;
  1256.      else
  1257.             return (ERROR);
  1258. }
  1259.     if (wvRBuffMgrId->tid != 0)
  1260.   if (taskPrioritySet (wvRBuffMgrId->tid, priority) != OK)
  1261.     return (ERROR);
  1262.     wvRBuffMgrId->priorityDefault = priority;
  1263.     return (OK);
  1264.     }
  1265. /*******************************************************************************
  1266. *
  1267. * rBuffUpload - Copy data that is added to the buffer to the specified 'fd'
  1268. *
  1269. * NOMANUAL
  1270. */
  1271. STATUS rBuffUpload
  1272.     (
  1273.     BUFFER_ID  buffId, /* generic identifier for this buffer */
  1274.     int  fd
  1275.     )
  1276.     {
  1277.     RBUFF_ID  rBuff; /* specific identifier for this rBuff */
  1278.     UINT8 * src;
  1279.     int  lockKey;
  1280.     STATUS  result = OK;
  1281.     /* Get access to the private members of this particular rBuff. */
  1282.     rBuff = (RBUFF_ID) buffId;
  1283.     rBuff->fd = fd;
  1284.     while (result == OK)
  1285.         {
  1286.         /* Wait for the dinner gong */
  1287.         logMsg ("Waiting for datan",0,0,0,0,0,0);
  1288.         semTake (&rBuff->buffDesc.threshXSem,WAIT_FOREVER);
  1289.         logMsg("Uploading...n",0,0,0,0,0,0);
  1290.         /* tuck in... */
  1291.         while (result == OK && rBuff->info.dataContent >
  1292.               (rBuff->info.threshold / 4))
  1293.             {
  1294.             UINT32 bytesToWrite = rBuffReadReserve(buffId, &src);
  1295.             UINT32 bytesWritten;
  1296.             if (bytesToWrite > 4096)
  1297.                 {
  1298.                     bytesToWrite = 4096;
  1299.                 }
  1300. #ifdef RBUFF_DEBUG
  1301.             logMsg ("%#x bytes from %p (dataContent=%#x)n",
  1302.                 bytesToWrite,
  1303.                 (int) src,
  1304.                 rBuff->info.dataContent,0,0,0);
  1305. #endif
  1306.             /* move the data */
  1307. #if 0
  1308. {
  1309. UINT8 buffer[100];
  1310. bcopy(src,buffer,bytesToWrite);
  1311. buffer[bytesToWrite] = '';
  1312. printf("%sn",buffer);
  1313. }
  1314. #endif
  1315.             if ((bytesWritten =
  1316.                 write (fd, src, bytesToWrite)) == -1)
  1317.                 {
  1318.                 logMsg ("Upload error!n",0,0,0,0,0,0);
  1319.                 if (rBuff->errorHandler)
  1320.                     {
  1321.                     /* Dial 999 / 911 */
  1322.                     (*rBuff->errorHandler)();
  1323.                     }
  1324.                 result = ERROR;
  1325.                 }
  1326.             else
  1327.                 {
  1328.                 /* move the buffer pointers along */
  1329.                 lockKey = intLock();
  1330.                 result = rBuffReadCommit (buffId,bytesWritten);
  1331.                 intUnlock (lockKey);
  1332.                 taskDelay (0);
  1333.                 }
  1334.             }
  1335.         }
  1336.     return (result);
  1337.     }
  1338. #else  /* GENERIC_RBUFF */
  1339. /*
  1340.  * The code below constitutes the generic ring buffer scheme on which
  1341.  * WindView 2.0 was originally based. If there is a need to go back to
  1342.  * it, #define GENERIC_RBUFF at the top of this file or build with
  1343.  * EXTRA_DEFINE="-DGENERIC_RBUFF" in the make command line
  1344.  */
  1345. #include "vxWorks.h"
  1346. #include "semLib.h"
  1347. #include "classLib.h"
  1348. #include "errno.h"
  1349. #include "intLib.h"
  1350. #include "logLib.h"
  1351. #include "taskLib.h"
  1352. #include "fioLib.h"
  1353. #include "rBuffLib.h"
  1354. #include "private/wvBufferP.h"
  1355. #include "private/classLibP.h"
  1356. #include "private/objLibP.h"
  1357. #include "private/workQLibP.h"
  1358. #include "stdio.h"
  1359. #include "string.h"
  1360. #include "unistd.h"
  1361. extern int rBuffMgr();
  1362. #if (CPU_FAMILY == I80X86)
  1363. extern void portWorkQAdd1();
  1364. #endif
  1365. /* locals */
  1366. #if defined(__STDC__) || defined(__cplusplus)
  1367. LOCAL STATUS rBuffAdd
  1368.     (
  1369.     RBUFF_ID  rBuff,
  1370.     RBUFF_PTR buffToAdd
  1371.     );
  1372. LOCAL STATUS  rBuffFree
  1373.     (
  1374.     RBUFF_ID  rBuff,
  1375.     RBUFF_PTR buffToFree
  1376.     );
  1377. LOCAL STATUS rBuffHandleEmpty
  1378.     (
  1379.     RBUFF_ID rBuff
  1380.     );
  1381. #else /* __STDC__ */
  1382. LOCAL STATUS rBuffAdd();
  1383. LOCAL STATUS rBuffFree();
  1384. LOCAL STATUS rBuffHandleEmpty();
  1385. #endif /* __STDC__ */
  1386. extern  BOOL kernelState;
  1387. #if (CPU_FAMILY == I80X86)
  1388. #define RBUFF_SEND_MSG(RMSG_TYPE,RMSG_PRI,RMSG_ID,RMSG_PARAM) 
  1389. if((!(RMSG_ID)->nestLevel++) && !(RMSG_ID)->msgOutstanding)   
  1390. {                                                             
  1391.     (RMSG_ID)->msgOutstanding = TRUE;                         
  1392.     (RMSG_ID)->msg[(RMSG_ID)->msgWriteIndex][0] = RMSG_TYPE;  
  1393.     (RMSG_ID)->msg[(RMSG_ID)->msgWriteIndex][1] = (UINT32) RMSG_PARAM; 
  1394.                                                               
  1395.     if(++(RMSG_ID)->msgWriteIndex > RBUFF_MAX_MSGS)           
  1396.     {                                                         
  1397.         (RMSG_ID)->msgWriteIndex = 0;                         
  1398.     }                                                         
  1399.                                                               
  1400.     if(kernelState)                                           
  1401.     {                                                         
  1402.         portWorkQAdd1((FUNCPTR)semCGiveDefer, (int)&(RMSG_ID)->msgSem); 
  1403.     }                                                         
  1404.     else                                                      
  1405.     {                                                         
  1406.         semCGiveDefer(&(RMSG_ID)->msgSem);                    
  1407.     }                                                         
  1408. }                                                             
  1409.                                                               
  1410. (RMSG_ID)->nestLevel--;
  1411. #else /* CPU_FAMILY == I80X86 */
  1412. #define RBUFF_SEND_MSG(RMSG_TYPE,RMSG_PRI,RMSG_ID,RMSG_PARAM) 
  1413. if((!(RMSG_ID)->nestLevel++) && !(RMSG_ID)->msgOutstanding)   
  1414. {                                                             
  1415.     (RMSG_ID)->msgOutstanding = TRUE;                         
  1416.     (RMSG_ID)->msg[(RMSG_ID)->msgWriteIndex][0] = RMSG_TYPE;  
  1417.     (RMSG_ID)->msg[(RMSG_ID)->msgWriteIndex][1] = (UINT32) RMSG_PARAM; 
  1418.                                                               
  1419.     if(++(RMSG_ID)->msgWriteIndex > RBUFF_MAX_MSGS)           
  1420.     {                                                         
  1421.         (RMSG_ID)->msgWriteIndex = 0;                         
  1422.     }                                                         
  1423.                                                               
  1424.     if(kernelState)                                           
  1425.     {                                                         
  1426.         workQAdd1((FUNCPTR)semCGiveDefer, (int)&(RMSG_ID)->msgSem); 
  1427.     }                                                         
  1428.     else                                                      
  1429.     {                                                         
  1430.         semCGiveDefer(&(RMSG_ID)->msgSem);                    
  1431.     }                                                         
  1432. }                                                             
  1433.                                                               
  1434. (RMSG_ID)->nestLevel--;
  1435. #endif /* CPU_FAMILY == I80X86 */
  1436. LOCAL BOOL   rBuffLibInstalled = FALSE;   /* protect from multiple inits */
  1437. /* global variables */
  1438. OBJ_CLASS rBuffClass;                   /* rBuff object Class */
  1439. CLASS_ID  rBuffClassId = &rBuffClass;   /* rBuff class ID */
  1440. int       rBuffMgrPriorityDefault = RBUFF_MGR_PRIORITY; /* default ring buff */
  1441.                                         /* manager priority */
  1442. /*******************************************************************************
  1443. *
  1444. * rBuffLibInit - initialise the ring of buffers library
  1445. *
  1446. * This routine initialises the ring of buffers library. If INCLUDE_RBUFF is
  1447. * defined in configAll.h, it is called by the root task, usrRoot(), in
  1448. * usrConfig.c.
  1449. *
  1450. * NOMANUAL
  1451. *
  1452. * RETURNS: OK, or ERROR if the library could not be initialized.
  1453. */
  1454. STATUS rBuffLibInit (void)
  1455.     {   
  1456.     if(rBuffLibInstalled) {
  1457.         return(TRUE);
  1458.     }
  1459.     rBuffLibInstalled = TRUE;
  1460.     /* Initialise the rBuff Manager */
  1461.     /* initialize the rBuff class structure */
  1462.     return (classInit (rBuffClassId,
  1463.                 sizeof (RBUFF_TYPE),
  1464.                 OFFSET (RBUFF_TYPE, buffDesc),
  1465.                 (FUNCPTR) rBuffCreate,
  1466.                 (FUNCPTR) NULL,
  1467.                 (FUNCPTR) rBuffDestroy));
  1468.     }
  1469.  
  1470. /*******************************************************************************
  1471. *
  1472. * rBuffCreate - create an extendable ring of buffers
  1473. *
  1474. * This routine creates an extendable ring of buffers from
  1475. * the specified partition.
  1476. *
  1477. * NOMANUAL
  1478. */
  1479. BUFFER_ID rBuffCreate
  1480.     (
  1481.     void *Params
  1482.     )
  1483.     {
  1484.     RBUFF_ID              rBuff;
  1485.     UINT32                count;
  1486.     RBUFF_PTR             newBuff;
  1487.     rBuffCreateParamsType *rBuffCreateParams = Params;
  1488.     if ((!rBuffLibInstalled) && (rBuffLibInit()) == OK)
  1489. {
  1490. rBuffLibInstalled = TRUE;
  1491. }
  1492.     if(!rBuffLibInstalled)
  1493.         {
  1494. #ifdef RBUFF_DEBUG
  1495.         logMsg ("rBuff: rBuffLib not installedn",0,0,0,0,0,0);
  1496. #endif
  1497.         return(NULL);
  1498.         }
  1499.     /* validate params */
  1500.     if (rBuffCreateParams->minimum < 2 ||
  1501.             ((rBuffCreateParams->minimum > rBuffCreateParams->maximum) ||
  1502.                (rBuffCreateParams->maximum < 2 &&
  1503.                 rBuffCreateParams->maximum != RBUFF_MAX_AVAILABLE)) ||
  1504.             rBuffCreateParams->buffSize == 0)
  1505.         {
  1506. #ifdef RBUFF_DEBUG
  1507.         logMsg ("rBuff: invalid paramsn",0,0,0,0,0,0);
  1508. #endif
  1509.         return(NULL);
  1510.         }
  1511.     /*
  1512.      *  Set source partition for object class memory allocation
  1513.      *  - note this only works overall if all rBuffs share a source
  1514.      *    partition.
  1515.      */
  1516.     classMemPartIdSet(rBuffClassId,
  1517.         rBuffCreateParams->sourcePartition);
  1518.     /* allocate control structure */
  1519.     rBuff = (RBUFF_ID) objAlloc (rBuffClassId);
  1520.     if(rBuff == NULL)
  1521.         {
  1522. #ifdef RBUFF_DEBUG
  1523.         logMsg ("rBuff: objAlloc failedn",0,0,0,0,0,0);
  1524. #endif
  1525.         return(NULL);
  1526.         }
  1527.     objCoreInit (&rBuff->buffDesc.objCore, rBuffClassId);
  1528.     /* record parameters */
  1529.     rBuff->info.srcPart   = rBuffCreateParams->sourcePartition;
  1530.     rBuff->info.options   = rBuffCreateParams->options;
  1531.     rBuff->info.buffSize  = rBuffCreateParams->buffSize;
  1532.     rBuff->info.threshold = rBuffCreateParams->threshold;
  1533.     rBuff->info.minBuffs  = rBuffCreateParams->minimum;
  1534.     rBuff->info.maxBuffs  = (unsigned int) rBuffCreateParams->maximum;
  1535.     rBuff->errorHandler   = rBuffCreateParams->errorHandler;
  1536.     if (semBInit (&rBuff->buffDesc.threshXSem, SEM_Q_PRIORITY, 
  1537.   SEM_EMPTY) == ERROR)
  1538.         {
  1539.         objFree (rBuffClassId, (UINT8 *) rBuff);
  1540.         return (NULL);
  1541.         }
  1542.     if (semBInit (&rBuff->readBlk, SEM_Q_PRIORITY, SEM_FULL) == ERROR)
  1543.         {
  1544.         semTerminate (&rBuff->buffDesc.threshXSem);
  1545.         objFree (rBuffClassId, (UINT8 *) rBuff);
  1546.         return (NULL);
  1547.         }
  1548.     if (semBInit (&rBuff->bufferFull, SEM_Q_PRIORITY, SEM_EMPTY) == ERROR)
  1549.         {
  1550.         semTerminate (&rBuff->buffDesc.threshXSem);
  1551.         semTerminate (&rBuff->readBlk);
  1552.         objFree (rBuffClassId, (UINT8 *)rBuff);
  1553.         return (NULL);
  1554.         }
  1555.     if (semCInit (&rBuff->msgSem, SEM_Q_PRIORITY, 0) == ERROR)
  1556.         {
  1557.         semTerminate (&rBuff->bufferFull);
  1558.         semTerminate (&rBuff->buffDesc.threshXSem);
  1559.         semTerminate (&rBuff->readBlk);
  1560.         objFree (rBuffClassId, (UINT8 *)rBuff);
  1561.         return (NULL);
  1562.         }
  1563.     rBuff->rBuffMgrId = 0; /* ...so we can use rBuffDestroy safely */
  1564.     /*
  1565.      *  If things go wrong from here, use rBuffDestroy to throw back what
  1566.      *  we've caught.
  1567.      */
  1568.     /* allocate 'rBuffCreateParams->minimum' buffers */
  1569.     rBuff->info.currBuffs  =
  1570.     rBuff->info.emptyBuffs = 0;
  1571.     rBuff->buffWrite = NULL;
  1572.     for (count=0;count < rBuffCreateParams->minimum;count++)
  1573.         {
  1574.         /* First we need a buffer */
  1575.         newBuff =
  1576.             (RBUFF_PTR)
  1577.                 memPartAlloc (rBuffCreateParams->sourcePartition,
  1578.                 sizeof(RBUFF_BUFF_TYPE) + rBuffCreateParams->buffSize);
  1579. #ifdef RBUFF_DEBUG
  1580.         logMsg ("rBuff: adding buffer %p to ringn",newBuff,0,0,0,0,0);
  1581. #endif
  1582.         /* newBuff will be returned as NULL if source partition is exhausted */
  1583.         /*  Don't need to lock ints around rBuffAdd as no-one knows about
  1584.          *  this rBuff.
  1585.          */
  1586.         if (newBuff == NULL || rBuffAdd (rBuff, newBuff) == ERROR)
  1587.             {
  1588. #ifdef RBUFF_DEBUG
  1589.             logMsg ("rBuff: abandoned creationn",0,0,0,0,0,0);
  1590. #endif
  1591.             rBuffDestroy ((BUFFER_ID) rBuff);
  1592.             return (NULL);
  1593.             }
  1594.         }
  1595.     rBuff->rBuffMgrId = taskSpawn ("tRBuffMgr",
  1596.       rBuffMgrPriorityDefault,
  1597.          RBUFF_MGR_OPTIONS,
  1598.          2048,
  1599.          rBuffMgr,
  1600.          rBuff,
  1601.          0,0,0,0,0,0,0,0,0);
  1602.     if(rBuff->rBuffMgrId == NULL)
  1603.         {
  1604. #ifdef RBUFF_DEBUG
  1605.         logMsg ("rBuff: error creating rBuffMgrn",0,0,0,0,0,0);
  1606. #endif
  1607.         rBuffDestroy ((BUFFER_ID) rBuff);
  1608.         return (NULL);
  1609.         }
  1610.     /* set control pointers */
  1611.     rBuff->nestLevel = 0;
  1612.     /* rBuff->buffWrite initialised by rBuffAdd */
  1613.     rBuff->buffRead  = rBuff->buffWrite;
  1614.     rBuff->dataWrite =
  1615.     rBuff->dataRead  = rBuff->buffWrite->dataStart;
  1616.     /* reset info */
  1617.     rBuff->info.maxBuffsActual   = rBuffCreateParams->minimum;
  1618.     rBuff->info.dataContent      =
  1619.     rBuff->info.writesSinceReset =
  1620.     rBuff->info.readsSinceReset  =
  1621.     rBuff->info.timesExtended    =
  1622.     rBuff->info.timesXThreshold  =
  1623.     rBuff->info.bytesWritten     =
  1624.     rBuff->info.bytesRead        =
  1625.     rBuff->info.bytesPeak        = 0;
  1626.     /* Reset msg passing mechanism */
  1627.     rBuff->msgOutstanding        = FALSE;
  1628.     rBuff->msgWriteIndex         =
  1629.     rBuff->msgReadIndex          = 0;
  1630.     /* now set up func ptrs allowing it to be called */
  1631.     rBuff->buffDesc.readReserveRtn = (FUNCPTR) rBuffReadReserve;
  1632.     rBuff->buffDesc.readCommitRtn  = (FUNCPTR) rBuffReadCommit;
  1633.     rBuff->buffDesc.writeRtn       = rBuffWrite;
  1634.     rBuff->buffDesc.flushRtn       = rBuffFlush;
  1635.     rBuff->buffDesc.threshold      = rBuffCreateParams->threshold;
  1636.     rBuff->buffDesc.nBytesRtn      = rBuffNBytes;
  1637.     /* made it! */
  1638. #ifdef RBUFF_DEBUG
  1639.     logMsg("Created rBuff with ID %pn",rBuff,0,0,0,0,0);
  1640. #endif
  1641.     return ((BUFFER_ID) rBuff);
  1642.     }
  1643. int rBuffVerify (BUFFER_ID rBuff)
  1644. {
  1645.     if (OBJ_VERIFY (rBuff, rBuffClassId) == OK) /* validate rBuff ID */
  1646.         {
  1647. return (OK);
  1648.         }
  1649.         else
  1650. {
  1651. return (ERROR);
  1652. }
  1653. }
  1654. /*******************************************************************************
  1655. *
  1656. * rBuffWrite - Write data to a ring of buffers
  1657. *
  1658. * This routine writes data to an extendable ring of buffers. If the existing
  1659. * structure is full, and the existing number of buffers is less than the
  1660. * specified minimum, then this function will attempt to add another buffer to
  1661. * the ring.
  1662. *
  1663. * This function may be called from interrupt level.
  1664. *
  1665. * Mutually exclusive access must be guaranteed by the caller.
  1666. *
  1667. * NOMANUAL
  1668. */
  1669. UINT8 *rBuffWrite
  1670.     (
  1671.     BUFFER_ID buffId,
  1672.     UINT8 *dataSrc,
  1673.     UINT32 numOfBytes
  1674.     )
  1675. {
  1676.     BOOL startUploading;
  1677.     RBUFF_ID rBuff; /* access this particular rBuff */
  1678.     UINT8 *returnPtr = (UINT8 *) ~NULL; /* Return a non-zero value if OK */
  1679.     /* Get access to the private members of this buffer's descriptor. */
  1680.     rBuff = (RBUFF_ID) buffId;
  1681.     /* Get out early if this request makes no sense. */
  1682.     if (numOfBytes > rBuff->info.buffSize)
  1683.         {
  1684.             return (NULL);
  1685.         }
  1686.     /* Critical Region Start */
  1687.     if (rBuff->info.dataContent >= rBuff->info.threshold)
  1688.         {
  1689.         startUploading = TRUE;
  1690.         }
  1691.     else
  1692.         {
  1693.         startUploading = FALSE;
  1694.         }
  1695.     if (rBuff->buffWrite->spaceAvail >= numOfBytes)
  1696.         {
  1697.         if (dataSrc)
  1698.             {
  1699.             /* We are writing the data, not just reserving the space */
  1700.             memcpy (rBuff->dataWrite, dataSrc, numOfBytes);
  1701.             }
  1702.         else
  1703.             {
  1704.             /* Record the start of the reserved area */
  1705.             returnPtr = rBuff->dataWrite;
  1706.             }
  1707.         /*
  1708.          *  If we are consuming one of our precious empty buffs,
  1709.          *  check we have enough in reserve.
  1710.          */
  1711.         if (rBuff->buffWrite->dataLen == 0) {
  1712.             --rBuff->info.emptyBuffs;
  1713.      }
  1714. if (rBuff->info.emptyBuffs < RBUFF_EMPTY_KEEP &&
  1715.             rBuff->info.currBuffs != rBuff->info.maxBuffs)
  1716.             {
  1717.             /* Schedule the rBuff Mgr to extend the buffer */
  1718.             RBUFF_SEND_MSG (RBUFF_MSG_ADD, MSG_PRI_URGENT, rBuff, 0);
  1719.     }
  1720.         rBuff->buffWrite->dataLen    += numOfBytes;
  1721.         rBuff->dataWrite             += numOfBytes;
  1722.         rBuff->buffWrite->spaceAvail -= numOfBytes;
  1723.         /*
  1724.          *  It may be that the current buffer is full at this point,
  1725.          *  but don't do anything about it yet as the situation will
  1726.          *  be handled next time through. Also, it's possible that
  1727.          *  the current buffer may even have been emptied by then.
  1728.          */
  1729.         }
  1730.     else
  1731.         {
  1732.         UINT32 dataWritten1stBuff;
  1733.         UINT32 dataWritten2ndBuff;
  1734.         /*
  1735.          *  Data won't fit in this buffer (at least not entirely),
  1736.          *  is the next buffer available?
  1737.          */
  1738.         if (rBuff->buffWrite->next == rBuff->buffRead)
  1739.             {
  1740.             /*  We've caught the reader. This will only happen when
  1741.              *  we have actually filled the maximum allocation of
  1742.              *  buffers *or* the reserved buffer has been filled
  1743.              *  before the buffer has had the opportunity to
  1744.              *  be extended. We cannot extend the buffer at this point
  1745.              *  as we may be in a critical region, the design is such
  1746.              *  that if the buffer could be extended it should have
  1747.              *  been done by now (for that matter, the wrap-around
  1748.              *  should have also occurred).
  1749.              *
  1750.              *  If we have filled the reserved buffer without having
  1751.              *  the opportunity to extend the buffer then the buffer
  1752.              *  is configured badly and must be retuned.
  1753.              *
  1754.              *  Meanwhile, at this moment, options are:
  1755.              *
  1756.              *  1) If we have filled the entire buffer and cannot wrap-
  1757.              *     around then return ERROR.
  1758.              *  2) If we have filled the entire buffer but can wrap-
  1759.              *     around then do that.
  1760.              */           
  1761.             if (rBuff->info.options & RBUFF_WRAPAROUND)
  1762.                 {
  1763.                 /*
  1764.                  *  OK, perform an inline ring extension supplying NULL
  1765.                  *  as the new buffer forcing the ring to wrap-around.
  1766.                  *  This is a deterministic action.
  1767.                  */
  1768.                 /* Interrupts already locked out */
  1769.                 rBuffAdd(rBuff, NULL);
  1770.                 }
  1771.             else
  1772.                 {
  1773.                 /* Oh dear, can't wrap-round */
  1774.                 return (NULL);
  1775.                 }
  1776.             }
  1777.         /*
  1778.          *  OK.
  1779.          *  In the case that this function is writing the data, it
  1780.          *  can be shared between this and next buffer.
  1781.          *  In the case that we are only reserving the space, we must
  1782.          *  return a pointer to contiguous space and therefore skip the
  1783.          *  remainder of the previous buffer.
  1784.          */
  1785.         if (dataSrc == NULL)
  1786.             {
  1787.             /* skip the remainder of the current buffer */
  1788.             rBuff->buffWrite->spaceAvail = 0;
  1789.             /* Move on to the next buffer */
  1790.             rBuff->buffWrite = rBuff->buffWrite->next;
  1791.             /* Record the start of the reserved area */
  1792.             returnPtr = rBuff->buffWrite->dataStart;
  1793.             /* Point dataWrite past the reserved area */
  1794.             rBuff->dataWrite = rBuff->buffWrite->dataStart;
  1795.             dataWritten1stBuff = 0;
  1796.             dataWritten2ndBuff = numOfBytes;
  1797.             }
  1798.         else
  1799.             {
  1800.             /* first make use of the space in this buffer */
  1801.             memcpy (rBuff->dataWrite,
  1802.                 dataSrc,
  1803.                 (dataWritten1stBuff = rBuff->buffWrite->spaceAvail));
  1804.             rBuff->buffWrite->dataLen    += dataWritten1stBuff;
  1805.             rBuff->buffWrite->spaceAvail = 0;
  1806.             /* Move on to the next buffer */
  1807.             dataWritten2ndBuff = numOfBytes - dataWritten1stBuff;
  1808.             rBuff->buffWrite = rBuff->buffWrite->next;
  1809.             rBuff->dataWrite = rBuff->buffWrite->dataStart;
  1810.             memcpy (rBuff->dataWrite,
  1811.                 dataSrc + dataWritten1stBuff,
  1812.                 dataWritten2ndBuff);
  1813.             }
  1814.         rBuff->buffWrite->dataLen    = dataWritten2ndBuff;
  1815.         rBuff->dataWrite            += dataWritten2ndBuff;
  1816.         rBuff->buffWrite->spaceAvail =
  1817.             rBuff->info.buffSize - dataWritten2ndBuff;
  1818.         if (--rBuff->info.emptyBuffs < RBUFF_EMPTY_KEEP &&
  1819.             rBuff->info.currBuffs != rBuff->info.maxBuffs)
  1820.             {
  1821.             /* Schedule the rBuff Mgr to extend the buffer */
  1822.             RBUFF_SEND_MSG (RBUFF_MSG_ADD, MSG_PRI_URGENT, rBuff, 0);
  1823.             }
  1824.         }
  1825.     rBuff->info.dataContent  += numOfBytes;
  1826.     /* update info */
  1827.     if(rBuff->info.dataContent > rBuff->info.bytesPeak)
  1828.         {
  1829.         rBuff->info.bytesPeak = rBuff->info.dataContent;
  1830.         }
  1831.     rBuff->info.bytesWritten += numOfBytes;
  1832.     rBuff->info.writesSinceReset++;
  1833.     if (!startUploading && rBuff->info.dataContent >= rBuff->info.threshold)
  1834.         {
  1835.         rBuff->info.timesXThreshold++;
  1836.         if (!(rBuff->info.options & RBUFF_UP_DEFERRED))
  1837.             {
  1838.             /*
  1839.              *  Signal for uploading to begin. Note that if we have just
  1840.              *  reserved space it is imperative that uploading does not
  1841.              *  actually begin until the data is in the buffer.
  1842.              */
  1843. #if (CPU_FAMILY == I80X86)
  1844.             portWorkQAdd1 ((FUNCPTR)semBGiveDefer,
  1845.                 (int) &rBuff->buffDesc.threshXSem);
  1846. #else
  1847.             workQAdd1 ((FUNCPTR)semBGiveDefer,
  1848.                 (int) &rBuff->buffDesc.threshXSem);
  1849. #endif
  1850.             }
  1851.         }
  1852.     /* Critical Region End */
  1853.     return(returnPtr);
  1854. }
  1855. /*******************************************************************************
  1856. *
  1857. * rBuffRead - Read data from a ring of buffers
  1858. *
  1859. * This routine reads data from an extendable ring of buffers.
  1860. *
  1861. * This function assumes mutually exclusive access is guaranteed by the caller.
  1862. *
  1863. * NOMANUAL
  1864. */
  1865. INT32 rBuffRead
  1866.     (
  1867.     BUFFER_ID buffId, /* generic buffer descriptor */
  1868.     UINT8    *dataDest,
  1869.     UINT32  numOfBytes
  1870.     )
  1871.     {
  1872.     UINT32 bytesToCopy, remaining = numOfBytes;
  1873.     RBUFF_ID rBuff; /* access private members of this rBuff desc */
  1874.     /* Get access to the private members of this particular rBuff. */
  1875.     rBuff = (RBUFF_ID) buffId;
  1876.     /* Critical Region Start */
  1877.     while(remaining)
  1878.         {
  1879.         bytesToCopy = (rBuff->buffRead->dataLen < remaining ?
  1880.                         rBuff->buffRead->dataLen : remaining);
  1881.         if (bytesToCopy > 0)
  1882.             {
  1883.             memcpy (dataDest,rBuff->dataRead,bytesToCopy);
  1884.             remaining                -= bytesToCopy;
  1885.             dataDest                 += bytesToCopy;
  1886.             /* Update buffer */
  1887.             rBuff->buffRead->dataLen -= bytesToCopy;
  1888.             rBuff->dataRead          += bytesToCopy;
  1889.             rBuff->info.dataContent  -= bytesToCopy;
  1890.             }
  1891.         if (!rBuff->buffRead->dataLen)
  1892.             {
  1893.             /* This buffer is now empty */
  1894.             rBuffHandleEmpty (rBuff);
  1895.             }
  1896.         else
  1897.             {
  1898.             /* this buffer is not yet emptied */
  1899.             rBuff->dataRead += bytesToCopy;
  1900.             }
  1901.         }
  1902.     /* update info */
  1903.     rBuff->info.bytesRead += (numOfBytes - remaining);
  1904.     rBuff->info.readsSinceReset++;
  1905.     /* Critical Region End */
  1906.     return (numOfBytes - remaining);
  1907.     }
  1908. /*******************************************************************************
  1909. *
  1910. * rBuffReadReserve - Return the number of contiguous bytes available for
  1911. *                    reading.
  1912. *
  1913. * NOMANUAL
  1914. */
  1915. UINT32 rBuffReadReserve
  1916.     (
  1917.     BUFFER_ID buffId, /* generic identifier for this buffer */
  1918.     UINT8 **src
  1919.     )
  1920.     {
  1921.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  1922.     INT32 bytesAvailable; 
  1923.     /* Get access to the private members of this particular rBuff. */
  1924.     rBuff = (RBUFF_ID) buffId;
  1925.     /* Generate and return the available contiguous bytes. */
  1926.     if ((bytesAvailable = rBuff->buffRead->dataLen))
  1927.         {
  1928.         *src = rBuff->dataRead;
  1929.         }
  1930.     else
  1931.         {
  1932.         *src = NULL;
  1933.         }
  1934.     return (bytesAvailable);
  1935.     }
  1936. /*******************************************************************************
  1937. *
  1938. * rBuffReadCommit - Move the read data ptr along a ring of buffers
  1939. *
  1940. * This routine moves the data ptr along a ring of buffers.
  1941. *
  1942. * It is equivalent to reading data from the buffers and should be used
  1943. * when the data has been copied elsewhere.
  1944. *
  1945. * This function assumes mutually exclusive access is guaranteed by the caller.
  1946. *
  1947. * NOMANUAL
  1948. */
  1949. STATUS rBuffReadCommit
  1950.     (
  1951.     BUFFER_ID buffId, /* generic identifier for this buffer */
  1952.     UINT32  numOfBytes
  1953.     )
  1954.     {
  1955.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  1956.     /* Get access to the private members of this particular rBuff. */
  1957.     if (!numOfBytes)
  1958.     {
  1959.         return (OK);
  1960.     }
  1961.     rBuff = (RBUFF_ID) buffId;
  1962.     /* Critical Region Start */
  1963.     if (numOfBytes == rBuff->buffRead->dataLen)
  1964.         {
  1965.         rBuffHandleEmpty (rBuff);
  1966.         }
  1967.     else if (numOfBytes < rBuff->buffRead->dataLen)
  1968.         {
  1969.         rBuff->buffRead->dataLen -= numOfBytes;
  1970.         rBuff->dataRead += numOfBytes;
  1971.         }
  1972.     else
  1973.         {
  1974.         /* Moving ahead through multiple buffers */
  1975.         /* Not yet supported */
  1976.         return(ERROR);
  1977.         }
  1978.     rBuff->info.dataContent -= numOfBytes;
  1979.     /* update info */
  1980.     rBuff->info.bytesRead += numOfBytes;
  1981.     rBuff->info.readsSinceReset++;
  1982.     /* Critical Region End */
  1983.     return (OK);
  1984.     }
  1985. /*******************************************************************************
  1986. *
  1987. * rBuffFlush - Flush data from a ring of buffers
  1988. *
  1989. * This routine causes any data held in a buffer to be uploaded and is
  1990. * used to clear data that falls below the specified threshold.
  1991. *
  1992. * NOMANUAL
  1993. */
  1994. STATUS rBuffFlush
  1995.     (
  1996.     BUFFER_ID buffId /* generic identifier for this buffer */
  1997.     )
  1998.     {
  1999.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  2000.     int result, originalThreshold;
  2001.     /* Get access to the private members of this particular rBuff. */
  2002.     rBuff = (RBUFF_ID) buffId;
  2003.     result = OK;
  2004.     if (!rBuff->info.dataContent)
  2005.         {
  2006.         return(OK);
  2007.         }
  2008.     /* Store the original threshold */
  2009.     originalThreshold = rBuff->info.threshold;
  2010.     rBuff->info.threshold = 0;
  2011.     while (rBuff->info.dataContent > 0 && result != ERROR)
  2012.         {
  2013.         if (semGive (&rBuff->buffDesc.threshXSem) == OK)
  2014.             {
  2015.             /* Cause a reschedule to allow uploader in */
  2016.             taskDelay(0);
  2017.             }
  2018.         else
  2019.             {
  2020.             result = ERROR;
  2021.             }
  2022.         }
  2023.     rBuff->info.threshold = originalThreshold;
  2024.     return(result);
  2025. }
  2026. /*******************************************************************************
  2027. *
  2028. * rBuffReset - reset an extendable ring of buffers
  2029. *
  2030. * This routine resets an already created extendable ring of buffers to its
  2031. * initial state. This loses any data held in the buffer. Any buffers held
  2032. * above the specified minimum number are deallocated.
  2033. *
  2034. * NOMANUAL
  2035. */
  2036. STATUS rBuffReset
  2037.     (
  2038.     BUFFER_ID buffId /* generic identifier for this buffer */
  2039.     )
  2040.     {
  2041.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  2042.     RBUFF_LOCK (rBuff);
  2043.     /* Get access to the private members of this particular rBuff. */
  2044.     rBuff = (RBUFF_ID) buffId;
  2045.     /* Now reset the ring of buffers. */
  2046.     if(rBuff->info.currBuffs > rBuff->info.minBuffs)
  2047.         {
  2048.         UINT32 excessBuffs, count;
  2049.         /* drop the excess buffers */
  2050.         excessBuffs = rBuff->info.currBuffs - rBuff->info.minBuffs;
  2051.         for (count=0;count < excessBuffs;count++)
  2052.             {
  2053.             RBUFF_PTR tempPtr;
  2054.             tempPtr = rBuff->buffWrite->next; /* should not be NULL! */
  2055.             rBuffFree (rBuff,rBuff->buffWrite);
  2056.             rBuff->buffWrite = tempPtr;
  2057.             }
  2058.         }
  2059.     /* Make sure the 'read' buffer pointer points somewhere sensible */
  2060.     rBuff->buffRead = rBuff->buffWrite;
  2061.     /* and reset the byte ptrs */
  2062.     rBuff->dataRead         =
  2063.     rBuff->dataWrite        = rBuff->buffWrite->dataStart;
  2064.     rBuff->info.currBuffs        =
  2065.     rBuff->info.maxBuffsActual   = rBuff->info.minBuffs;
  2066.     /* now traverse the ring resetting the individual buffers */
  2067.     {
  2068.     RBUFF_PTR backHome = rBuff->buffWrite;
  2069.     RBUFF_PTR currBuff = rBuff->buffWrite;
  2070.     do  {
  2071.         currBuff->dataLen    = 0;
  2072.         currBuff->spaceAvail = rBuff->info.buffSize;
  2073.         currBuff = currBuff->next;
  2074.         }
  2075.     while (currBuff != backHome);
  2076.     }
  2077.     rBuff->nestLevel = 0;
  2078.     /* reset info */
  2079.     rBuff->info.emptyBuffs       = rBuff->info.minBuffs;
  2080.     rBuff->info.dataContent      =
  2081.     rBuff->info.writesSinceReset =
  2082.     rBuff->info.readsSinceReset  =
  2083.     rBuff->info.timesExtended    =
  2084.     rBuff->info.timesXThreshold  =
  2085.     rBuff->info.bytesWritten     =
  2086.     rBuff->info.bytesRead        = 0;
  2087.     semGive (&rBuff->bufferFull);
  2088.     RBUFF_UNLOCK (rBuff);
  2089.     return (OK);
  2090. }
  2091. /*******************************************************************************
  2092. *
  2093. * rBuffNBytes - Returns the total number of bytes held in a ring of buffers
  2094. *
  2095. * NOMANUAL
  2096. */
  2097. INT32 rBuffNBytes
  2098.     (
  2099.     BUFFER_ID buffId /* generic identifier for this buffer */
  2100.     )
  2101.     {
  2102.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  2103.     /* Get access to the private members of this particular rBuff. */
  2104.     rBuff = (RBUFF_ID) buffId;
  2105.     return (rBuff->info.dataContent);
  2106.     }
  2107. /*******************************************************************************
  2108. *
  2109. * rBuffAdd - Add a new buffer to an extendable ring of buffers
  2110. *
  2111. * This routine adds a further buffer to an already created or partially created
  2112. * extendable ring of buffers unless the maximum number is already allocated.
  2113. *
  2114. * This function assumes mutually exclusive access is guaranteed by the caller.
  2115. *
  2116. * NOMANUAL
  2117. */
  2118. STATUS rBuffAdd
  2119.     (
  2120.     RBUFF_ID rBuff,
  2121.     RBUFF_PTR newBuff
  2122.     )
  2123.     {
  2124.     if (rBuff->info.emptyBuffs >= RBUFF_EMPTY_KEEP &&
  2125.         rBuff->info.currBuffs  >= rBuff->info.minBuffs)
  2126.         {
  2127.         /*
  2128.          *  OK, the uploader got in so now we don't need to extend the
  2129.          *  buffer.
  2130.          */
  2131. #ifdef RBUFF_DEBUG
  2132.         logMsg ("rBuff: abandoned addn",0,0,0,0,0,0);
  2133. #endif
  2134.         if (newBuff)
  2135.             {
  2136.             memPartFree (rBuff->info.srcPart, (UINT8 *) newBuff);
  2137.             }
  2138.         return (OK);
  2139.         }
  2140.     if (rBuff->info.currBuffs == rBuff->info.maxBuffs || newBuff == NULL)
  2141.         {
  2142.         /*
  2143.          *  We are at the maximum ring size already or the source
  2144.          *  partition is exhausted, there's still hope...
  2145.          *
  2146.          *  ...can we wrap-around?
  2147.          */
  2148.         if (!(rBuff->info.options & RBUFF_WRAPAROUND))
  2149.             {
  2150.             /* We aren't allowed to wrap around */
  2151.             return (ERROR);
  2152.             }
  2153.         else
  2154.             {
  2155.             RBUFF_PTR reclaim;
  2156.             /*  We can wrap around by comandeering the 'oldest'
  2157.              *  buffer in the ring.
  2158.              *
  2159.              *  It is possible (probable?) that this buffer is the
  2160.              *  one to be read from next so handle this.
  2161.              */
  2162.             reclaim = rBuff->buffWrite->next;
  2163.             if (rBuff->buffRead == reclaim)
  2164.                 {
  2165.                 /* Move the reader along */
  2166.                 rBuff->buffRead = rBuff->buffRead->next;
  2167.                 rBuff->dataRead = rBuff->buffRead->dataStart;
  2168.                 }
  2169.             rBuff->info.dataContent  -= reclaim->dataLen;
  2170.             /* Reset the buffer */
  2171.             reclaim->dataLen    = 0;
  2172.             reclaim->spaceAvail = rBuff->info.buffSize;
  2173.             rBuff->info.emptyBuffs++;
  2174.             return (OK);
  2175.             }
  2176.         }
  2177.     newBuff->dataStart  = (UINT8 *) newBuff + sizeof(RBUFF_BUFF_TYPE);
  2178.     newBuff->dataEnd    = newBuff->dataStart + rBuff->info.buffSize;
  2179.     newBuff->spaceAvail = rBuff->info.buffSize;
  2180.     newBuff->dataLen    = 0;
  2181.     /* Now link the buffer into the ring */
  2182.     if (rBuff->buffWrite != NULL)
  2183.         {
  2184.         RBUFF_PTR tempPtr;
  2185.         tempPtr = rBuff->buffWrite->next;
  2186.         rBuff->buffWrite->next = newBuff;
  2187.         /* close the ring */
  2188.         newBuff->next = tempPtr;
  2189.         }
  2190.     else
  2191.         {
  2192.         /* ring is empty, must be creation time */
  2193.         rBuff->buffWrite =
  2194.         rBuff->buffRead  =
  2195.         newBuff->next    = newBuff;
  2196.         }
  2197.     /* Maintain statistics */
  2198.     if (++(rBuff->info.currBuffs) > rBuff->info.maxBuffsActual)
  2199.         {
  2200.         rBuff->info.maxBuffsActual++;
  2201.         }
  2202.     rBuff->info.timesExtended++;
  2203.     rBuff->info.emptyBuffs++;
  2204.     return (OK);
  2205. }
  2206. /*******************************************************************************
  2207. *
  2208. * rBuffFree - Free a specified buffer
  2209. *
  2210. * This function must only be called from task level.
  2211. * Semaphores are used to protect access at task-level. However, protection
  2212. * from access at interrupt level must be guaranteed by the caller.
  2213. *
  2214. * NOMANUAL
  2215. */
  2216. STATUS rBuffFree
  2217.     (
  2218.     RBUFF_ID rBuff,
  2219.     RBUFF_PTR buffToFree
  2220.     )
  2221.     {
  2222.     RBUFF_PTR ptrToBuff, backHome, ptrToPreviousBuff;
  2223.     if (buffToFree == NULL)
  2224.         {
  2225.         return(ERROR);
  2226.         }
  2227.     /* find the pointer to the buffer to be freed */
  2228.     ptrToBuff         = rBuff->buffWrite->next;
  2229.     backHome          = rBuff->buffWrite;
  2230.     ptrToPreviousBuff = rBuff->buffWrite;
  2231.     while ((ptrToBuff != buffToFree) && (ptrToBuff != backHome))
  2232.         {
  2233.         ptrToPreviousBuff = ptrToBuff;
  2234.         ptrToBuff         = buffToFree;
  2235.         }
  2236.     if (ptrToBuff == backHome)
  2237.         {
  2238.         /* an error has occured, possibly invalid buff ptr passed */
  2239.         return (ERROR);
  2240.         }
  2241.     /* OK, de-link the buffer to be freed */
  2242.     ptrToPreviousBuff->next = buffToFree->next;
  2243.     /* Schedule the rBuff Mgr to actually free the buffer */
  2244.     RBUFF_SEND_MSG (RBUFF_MSG_FREE, MSG_PRI_NORMAL, rBuff, buffToFree);
  2245.     /* Maintain statistics */
  2246.     rBuff->info.emptyBuffs--;
  2247.     rBuff->info.currBuffs--;
  2248.     return (OK);
  2249.     }
  2250. /*******************************************************************************
  2251. *
  2252. * rBuffDestroy - Destroy an extendable ring of buffers
  2253. *
  2254. * This routine destroys an already created or partially created extendable ring
  2255. * of buffers. This loses any data held in the buffer. All resources held are
  2256. * returned to the system.
  2257. *
  2258. * NOMANUAL
  2259. */
  2260. STATUS rBuffDestroy
  2261.     (
  2262.     BUFFER_ID buffId /* generic identifier for this buffer */
  2263.     )
  2264.     {
  2265.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  2266.     RBUFF_PTR tempPtr;
  2267.     /* Get access to the private members of this particular rBuff. */
  2268.     rBuff = (RBUFF_ID) buffId;
  2269.     RBUFF_LOCK (rBuff);
  2270.     if(rBuff->rBuffMgrId != NULL)
  2271.         {
  2272.         taskDelete(rBuff->rBuffMgrId);
  2273.         }
  2274. #if 0
  2275.     if (OBJ_VERIFY (rBuff, rBuffClassId) != OK) /* validate rBuff ID */
  2276. {
  2277. ((OBJ_ID)rBuff)->pObjClass, rBuffClassId);
  2278. RBUFF_UNLOCK (rBuff);
  2279. return (ERROR);
  2280. }
  2281. #endif
  2282.     objCoreTerminate (&rBuff->buffDesc.objCore);   /* invalidate this object */
  2283.     /* Break the ring and traverse the list, freeing off   */
  2284.     /* the buffers. buffWrite is used as the start point   */
  2285.     /* this works if the ring creation is abandoned early. */
  2286.     if (rBuff->buffWrite != NULL)
  2287.         {
  2288.         /* Break the ring */
  2289.         tempPtr = rBuff->buffWrite->next;
  2290.         rBuff->buffWrite->next = NULL;
  2291.         rBuff->buffWrite = tempPtr;
  2292.         /* traverse and free */
  2293.         while(rBuff->buffWrite != NULL)
  2294.             {
  2295.             tempPtr = rBuff->buffWrite->next;
  2296.             memPartFree (rBuff->info.srcPart,(UINT8 *)rBuff->buffWrite);
  2297.             rBuff->buffWrite = tempPtr;
  2298.             }
  2299.         }
  2300.     else
  2301.         {
  2302.         /* ring hasn't been created so don't worry about it */
  2303.         }
  2304.     /* now free off the control structure */
  2305.     semTerminate (&rBuff->buffDesc.threshXSem);
  2306.     semTerminate (&rBuff->readBlk);
  2307.     semTerminate (&rBuff->bufferFull);
  2308.     objFree (rBuffClassId, (UINT8 *) rBuff);
  2309.     /* we're done */
  2310.     return (OK);
  2311.     }
  2312. /*******************************************************************************
  2313. *
  2314. * rBuffSetFd - Set a new fd as the data upload destination
  2315. *
  2316. *
  2317. * NOMANUAL
  2318. */
  2319. STATUS rBuffSetFd
  2320.     (
  2321.     BUFFER_ID buffId, /* generic identifier for this buffer */
  2322.     int fd
  2323.     )
  2324.     {
  2325.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  2326.     RBUFF_LOCK (rBuff);
  2327.     /* Get access to the private members of this particular rBuff. */
  2328.     rBuff = (RBUFF_ID) buffId;
  2329.     rBuff->fd = fd;
  2330.     RBUFF_UNLOCK (rBuff);
  2331.     return (OK);
  2332.     }
  2333. /*******************************************************************************
  2334. *
  2335. * rBuffHandleEmpty - Handles a newly empty buffer by deciding whether to free
  2336. *                    it off.
  2337. *
  2338. * This function assumes mutually exclusive access is guaranteed by the caller.
  2339. *
  2340. * NOMANUAL
  2341. */
  2342. LOCAL STATUS rBuffHandleEmpty
  2343.     (
  2344.     RBUFF_ID rBuff
  2345.     )
  2346.     {
  2347.     BOOL      moveAlong = TRUE;
  2348.     RBUFF_PTR buffToFree;
  2349.     /*
  2350.      *  Determine if we are to move around the ring and if the
  2351.      *  newly empty buffer is to be freed, and then do the actions.
  2352.      *  This avoids having to fumble with ptrs as we move around
  2353.      *  from a buffer that has been freed.
  2354.      */
  2355.     if (rBuff->buffRead == rBuff->buffWrite)
  2356.         {
  2357.         /*
  2358.          *  We've caught the writer so might as well reset this
  2359.          *  buffer and make efficient use of it.
  2360.          */
  2361.         rBuff->dataRead  =
  2362.             rBuff->dataWrite = rBuff->buffWrite->dataStart;
  2363.         rBuff->buffRead->spaceAvail = rBuff->info.buffSize;
  2364.         rBuff->buffRead->dataLen     = 0;
  2365.         /* In this case, we don't move along to the next buffer */
  2366.         moveAlong = FALSE;
  2367.         }
  2368.     if (++(rBuff->info.emptyBuffs) > RBUFF_EMPTY_KEEP &&
  2369.            rBuff->info.currBuffs > rBuff->info.minBuffs)
  2370.         {
  2371.         /* We already have enough empty buffs, so free one off */
  2372.         if (rBuff->buffRead != rBuff->buffWrite)
  2373.             {
  2374.             buffToFree = rBuff->buffRead;
  2375.             }
  2376.             else
  2377.             {
  2378.             /*
  2379.              *  As the reader and writer are in the same buffer
  2380.              *  we know it's safe to free off the next buffer.
  2381.              */
  2382.             buffToFree = rBuff->buffRead->next;
  2383.             }
  2384.         }
  2385.     else
  2386.         {
  2387.         /* we've just emptied one of the 'core' buffers */
  2388.         rBuff->buffRead->spaceAvail = rBuff->info.buffSize;
  2389.         rBuff->buffRead->dataLen    = 0;
  2390.         /* Don't free */
  2391.         buffToFree = NULL;
  2392.         }
  2393.     if (moveAlong)
  2394.         {
  2395.         /* Move round the ring */
  2396.         rBuff->buffRead = rBuff->buffRead->next;
  2397.         rBuff->dataRead = rBuff->buffRead->dataStart;
  2398.         }
  2399.     else
  2400.         {
  2401.         /* reset flag for next time */
  2402.         moveAlong = TRUE;
  2403.         }
  2404.     if (/* there's a */ buffToFree)
  2405.         {
  2406. #ifdef RBUFF_DEBUG
  2407.         logMsg ("rBuff: Freeing buffer %pn",
  2408.             buffToFree,0,0,0,0,0);
  2409. #endif
  2410.         rBuffFree (rBuff, buffToFree);
  2411.         }
  2412.     return (OK);
  2413.     }
  2414. /*******************************************************************************
  2415. *
  2416. * rBuffMgr - The function is spawned as a task to manage rBuff extension.
  2417. *
  2418. * It waits for a msg which carries the ID of a buffer which has had a change
  2419. * of the number of empty buffers held. If there are less the requested to be
  2420. * reserved than an attempt will be made to make more available. If there are
  2421. * more empty buffers than required than some will be freed.
  2422. *
  2423. * For each msg received, the task will achieve the required number of free
  2424. * buffers. This may result in redundant msgs being received.
  2425. *
  2426. * NOMANUAL
  2427. */
  2428. int rBuffMgr(RBUFF_TYPE *rBuffId)
  2429.     {
  2430.     UINT32     busy;
  2431.     int        key;
  2432.     RBUFF_PTR  newBuff;
  2433. #ifdef RBUFF_DEBUG
  2434.         logMsg ("rBuff: Mgr for rBuff %p createdn",rBuffId,0,0,0,0,0);
  2435. #endif
  2436.     for(;;)
  2437.         {
  2438. semTake (&(rBuffId->msgSem), WAIT_FOREVER);
  2439. #ifdef RBUFF_DEBUG
  2440.         logMsg ("rBuff: Msg type 0x%x received from rBuff %pn",
  2441.             rBuffId->msg[rBuffId->msgReadIndex][0],rBuffId,0,0,0,0);
  2442. #endif
  2443.         busy = TRUE;
  2444.         /* Determine what needs to be done */
  2445.         switch (rBuffId->msg[rBuffId->msgReadIndex][0])
  2446.             {
  2447.             case RBUFF_MSG_ADD :
  2448.                 {
  2449.                 /*
  2450.                  *  This message may be generated one or more times by
  2451.                  *  event logging, and the condition that caused the msg
  2452.                  *  may no longer be TRUE, so just take this as a prompt
  2453.                  *  to see if the ring needs extending.
  2454.                  */
  2455.                 /* Make sure that we don't request extension recursively */
  2456.                 rBuffId->nestLevel++;
  2457.                 while
  2458.                     (rBuffId->info.emptyBuffs < RBUFF_EMPTY_KEEP &&
  2459.                     (rBuffId->info.currBuffs  < rBuffId->info.maxBuffs ||
  2460.                         rBuffId->info.options & RBUFF_WRAPAROUND) &&
  2461.                     busy)
  2462.                     {
  2463.                     /* Looks like we are going to need a buffer */
  2464.                     newBuff = (RBUFF_PTR)
  2465.                         memPartAlloc (rBuffId->info.srcPart,
  2466.                             sizeof(RBUFF_BUFF_TYPE) + rBuffId->info.buffSize);
  2467.                     /* of course, newBuff may be NULL... */
  2468.                     key = intLock();
  2469. #ifdef RBUFF_DEBUG
  2470.                     logMsg ("rBuff: adding buffer %pn",newBuff,0,0,0,0,0);
  2471. #endif
  2472.     if (rBuffAdd (rBuffId, newBuff) == ERROR)
  2473.                         {
  2474.                         /* ring cannot be extended so give up trying */
  2475.                         busy = FALSE;
  2476.                         }
  2477.                     intUnlock (key);
  2478.                     }
  2479.                 }
  2480.                 rBuffId->nestLevel--;
  2481.             break;
  2482.             case RBUFF_MSG_FREE :
  2483.                 {
  2484.                 /* This message carries a ptr to the buffer to be freed */
  2485. #ifdef RBUFF_DEBUG
  2486.                 logMsg ("rBuff: freeing buffer %pn",rBuffId->msg[rBuffId->msgReadIndex][1],0,0,0,0,0);
  2487. #endif
  2488.                 memPartFree (rBuffId->info.srcPart,
  2489.                     (UINT8 *) rBuffId->msg[rBuffId->msgReadIndex][1]);
  2490.                 }
  2491.             break;
  2492.             }
  2493.          if(++rBuffId->msgReadIndex > RBUFF_MAX_MSGS)
  2494.              {
  2495.              rBuffId->msgReadIndex = 0;
  2496.              }
  2497.          rBuffId->msgOutstanding = FALSE;
  2498.          }
  2499.    }
  2500. /*******************************************************************************
  2501. *
  2502. * rBuffMgrPrioritySet - set the priority of ring Buffer Manager task
  2503. *
  2504. * This routine sets the priority of the rBuffMgr task to the priority given.
  2505. * Two parameters are expected:
  2506. * rBuffId : can be NULL or a valid ring Buffer Id.
  2507. *           If NULL, the default priority of any future ring buffer manager
  2508. *           tasks spawned will be set to the priority given. The priority of any
  2509. *         existing ring buffer manager tasks running will be unaffected.
  2510. *
  2511. *           If a valid ring buffer id is given, the priority of its associated
  2512. *           ring buffer manager will be changed to that given. In addition, the
  2513. *           priority of any future ring buffer manager tasks spawned will be
  2514. *           changed to the priority given. If the priority of the associated
  2515. *           manager cannot be set for any reason, the routine returns ERROR and
  2516. *           the default remains unchanged.
  2517. * priority :The desired priority of the ring buffer manager task (0-255).
  2518. *
  2519. * NOMANUAL
  2520. *
  2521. * RETURNS: OK, or ERROR if the priority could not be set.
  2522. */
  2523. STATUS rBuffMgrPrioritySet
  2524.     (
  2525.     RBUFF_ID rBuffId, /* rBuff identifier */
  2526.     int      priority           /* new priority */
  2527.     )
  2528.     {
  2529.     if (rBuffId != NULL)
  2530.   if (taskPrioritySet (rBuffId->rBuffMgrId, priority) != OK)
  2531.     return (ERROR);
  2532.     rBuffMgrPriorityDefault = priority;
  2533.     return (OK);
  2534.     }
  2535. /*******************************************************************************
  2536. *
  2537. * rBuffUpload - Copy data that is added to the buffer to the specified 'fd'
  2538. *
  2539. * NOMANUAL
  2540. */
  2541. STATUS rBuffUpload
  2542.     (
  2543.     BUFFER_ID buffId, /* generic identifier for this buffer */
  2544.     int fd
  2545.     )
  2546.     {
  2547.     RBUFF_ID rBuff; /* specific identifier for this rBuff */
  2548.     UINT8 *src;
  2549.     int lockKey;
  2550.     STATUS result = OK;
  2551.     /* Get access to the private members of this particular rBuff. */
  2552.     rBuff = (RBUFF_ID) buffId;
  2553.     rBuff->fd = fd;
  2554.     while(result == OK)
  2555.         {
  2556.         /* Wait for the dinner gong */
  2557.         logMsg ("Waiting for datan",0,0,0,0,0,0);
  2558.         semTake (&rBuff->buffDesc.threshXSem,WAIT_FOREVER);
  2559.         logMsg("Uploading...n",0,0,0,0,0,0);
  2560.         /* tuck in... */
  2561.         while (result == OK && rBuff->info.dataContent >
  2562.               (rBuff->info.threshold / 4))
  2563.             {
  2564.             UINT32 bytesToWrite = rBuffReadReserve(buffId, &src);
  2565.             UINT32 bytesWritten;
  2566.             if (bytesToWrite > 4096)
  2567.                 {
  2568.                     bytesToWrite = 4096;
  2569.                 }
  2570. #ifdef RBUFF_DEBUG
  2571.             logMsg ("%#x bytes from %p (dataContent=%#x)n",
  2572.                 bytesToWrite,
  2573.                 (int) src,
  2574.                 rBuff->info.dataContent,0,0,0);
  2575. #endif
  2576.             /* move the data */
  2577. #if 0
  2578. {
  2579. UINT8 buffer[100];
  2580. bcopy(src,buffer,bytesToWrite);
  2581. buffer[bytesToWrite] = '';
  2582. printf("%sn",buffer);
  2583. }
  2584. #endif
  2585.             if ((bytesWritten =
  2586.                 write (fd, src, bytesToWrite)) == -1)
  2587.                 {
  2588.                 logMsg ("Upload error!n",0,0,0,0,0,0);
  2589.                 if (rBuff->errorHandler)
  2590.                     {
  2591.                     /* Dial 999 / 911 */
  2592.                     (*rBuff->errorHandler)();
  2593.                     }
  2594.                 result = ERROR;
  2595.                 }
  2596.             else
  2597.                 {
  2598.                 /* move the buffer pointers along */
  2599.                 lockKey = intLock();
  2600.                 result = rBuffReadCommit (buffId,bytesWritten);
  2601.                 intUnlock (lockKey);
  2602.                 taskDelay (0);
  2603.                 }
  2604.             }
  2605.         }
  2606.     return (result);
  2607.     }
  2608. #endif /* GENERIC_RBUFF */
  2609. #if (CPU_FAMILY == I80X86)
  2610. /*******************************************************************************
  2611. *
  2612. * portWorkQAdd1 - add work with one parameter to the wind work queue
  2613. *
  2614. * When the kernel is interrupted, new kernel work must be queued to an internal
  2615. * work queue.  The work queue is emptied by whatever task or interrupt service
  2616. * routine that entered the kernel first.  The work is emptied as the last
  2617. * code of reschedule().
  2618. *
  2619. * INTERNAL
  2620. * The work queue is single reader, multiple writer, so we should have to lock
  2621. * out interrupts while the writer is copying into the ring, but because the
  2622. * reader can never interrupt a writer, interrupts need only be locked while
  2623. * we advance the write queue pointer.
  2624. *
  2625. * RETURNS: OK
  2626. *
  2627. * SEE ALSO: reschedule()
  2628. *
  2629. * NOMANUAL
  2630. */
  2631. void portWorkQAdd1
  2632.     (
  2633.     FUNCPTR func,       /* function to invoke */
  2634.     int arg1            /* parameter one to function */
  2635.     )
  2636.     {
  2637.     int level = intLock ();             /* LOCK INTERRUPTS */
  2638.     FAST JOB *pJob = (JOB *) &pJobPool [workQWriteIx];
  2639.     workQWriteIx += 4;                  /* advance write index */
  2640.     if (workQWriteIx == workQReadIx)
  2641.         workQPanic ();                  /* leave interrupts locked */
  2642.     intUnlock (level);                  /* UNLOCK INTERRUPTS */
  2643.     workQIsEmpty = FALSE;               /* we put something in it */
  2644.     pJob->function = func;              /* fill in function */
  2645.     pJob->arg1 = arg1;                  /* fill in argument */
  2646.     }
  2647. #endif /* CPU_FAMILY == I80X86 */