From a2267936a2f08f0c3bca6ebb2907fdac5a6b7abe Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 7 Aug 2011 11:44:24 +0800 Subject: [PATCH] Kernel - Fixed concurrency in the RingBuffer type --- Kernel/adt.c | 37 +++++++++++++++++++++++++++++-------- Kernel/include/adt.h | 1 + 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Kernel/adt.c b/Kernel/adt.c index 77c8d995..1a001c99 100644 --- a/Kernel/adt.c +++ b/Kernel/adt.c @@ -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; } + diff --git a/Kernel/include/adt.h b/Kernel/include/adt.h index 91a8ae5f..67e12665 100644 --- a/Kernel/include/adt.h +++ b/Kernel/include/adt.h @@ -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; -- 2.20.1