Kernel - Fixed concurrency in the RingBuffer type
authorJohn Hodge <[email protected]>
Sun, 7 Aug 2011 03:44:24 +0000 (11:44 +0800)
committerJohn Hodge <[email protected]>
Sun, 7 Aug 2011 03:44:24 +0000 (11:44 +0800)
Kernel/adt.c
Kernel/include/adt.h

index 77c8d99..1a001c9 100644 (file)
@@ -21,45 +21,66 @@ tRingBuffer *RingBuffer_Create(size_t Space)
 
 size_t RingBuffer_Read(void *Dest, tRingBuffer *Buffer, size_t Length)
 {
-       if(Length > Buffer->Length)     Length = Buffer->Length;
+       size_t  tmpLen;
+
+       tmpLen = Buffer->Length;        // Changed in Write, so cache it for our read
+
+       if(Length > tmpLen)     Length = tmpLen;
        
        if( Buffer->Start + Length > Buffer->Space )
        {
                 int    endData = Buffer->Space - Buffer->Start;
                memcpy(Dest, &Buffer->Data[Buffer->Start], endData);
-               memcpy((Uint8*)Dest + endData, &Buffer->Data, Length - endData);
+               memcpy((Uint8*)Dest + endData, Buffer->Data, Length - endData);
        }
        else
        {
                memcpy(Dest, &Buffer->Data[Buffer->Start], Length);
        }
+
+       // Lock then modify
+       SHORTLOCK( &Buffer->Lock );
        Buffer->Start += Length;
        if( Buffer->Start > Buffer->Space )
                Buffer->Start -= Buffer->Space;
        Buffer->Length -= Length;
+       SHORTREL( &Buffer->Lock );
+
        return Length;
 }
 
 size_t RingBuffer_Write(tRingBuffer *Buffer, const void *Source, size_t Length)
 {
-       size_t  bufEnd = Buffer->Start + Buffer->Length;
-       size_t  endSpace = Buffer->Space - bufEnd;
+       size_t  bufEnd, endSpace;
+       size_t  tmpLen, tmpStart;
+       
+       // Cache Start and Length because _Read can change these
+       SHORTLOCK( &Buffer->Lock );
+       tmpStart = Buffer->Start;
+       tmpLen = Buffer->Length;
+       SHORTREL( &Buffer->Lock );
+
+       bufEnd = (Buffer->Start + Buffer->Length) % Buffer->Space;
+       endSpace = Buffer->Space - bufEnd;
        
        // Force to bounds
-       if(Length > Buffer->Space - Buffer->Length)
-               Length = Buffer->Space - Buffer->Length;
+       if(Length > Buffer->Space - tmpLen)     Length = Buffer->Space - tmpLen;
        
        if(endSpace < Length)
        {
                memcpy( &Buffer->Data[bufEnd], Source, endSpace );
                memcpy( Buffer->Data, (Uint8*)Source + endSpace, Length - endSpace );
-               Buffer->Length = Length - endSpace;
        }
        else
        {
                memcpy( &Buffer->Data[bufEnd], Source, Length );
-               Buffer->Length += Length;
        }
+
+       // Lock then modify
+       SHORTLOCK( &Buffer->Lock );
+       Buffer->Length += Length;
+       SHORTREL( &Buffer->Lock );
        
        return Length;
 }
+
index 91a8ae5..67e1266 100644 (file)
@@ -14,6 +14,7 @@ typedef struct sRingBuffer
        size_t  Start;  //!< Start of data in ring buffer
        size_t  Length; //!< Number of data bytes in buffer
        size_t  Space;  //!< Allocated space in buffer
+       tShortSpinlock  Lock;   //!< Lock to prevent collisions
        char    Data[]; //!< Buffer
 }      tRingBuffer;
 

UCC git Repository :: git.ucc.asn.au