X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=mware%2Ffifobuf.h;h=2b749d8fe1c748b275b4ef64d21d7817d2ceb4a1;hb=5f3952176a4e9a00ca8dd5ec4a6b994958f89e0a;hp=67528b97dd2170567d5abda0be9883977284fe10;hpb=ba17a56d0c988fee6a42ed2cd5a7da0625164121;p=bertos.git diff --git a/mware/fifobuf.h b/mware/fifobuf.h old mode 100755 new mode 100644 index 67528b97..2b749d8f --- a/mware/fifobuf.h +++ b/mware/fifobuf.h @@ -1,9 +1,9 @@ -/*! +/** * \file * * * \version $Id$ @@ -41,35 +41,72 @@ * \code head == begin && tail == end \endcode */ -/* - * $Log$ - * Revision 1.10 2004/07/29 22:57:09 bernie - * Doxygen fix. - * - * Revision 1.9 2004/07/20 23:54:27 bernie - * fifo_flush_locked(): New function; - * Revamp documentation. - * - * Revision 1.8 2004/07/20 23:47:39 bernie - * Finally remove redundant protos. - * - * Revision 1.7 2004/07/20 23:46:29 bernie - * Finally remove redundant protos. - * - * Revision 1.6 2004/06/06 17:18:04 bernie - * Remove redundant declaration of fifo_isempty_locked(). - * - * Revision 1.5 2004/06/06 16:50:35 bernie - * Import fixes for race conditions from project_ks. - * - * Revision 1.4 2004/06/06 16:11:17 bernie - * Protect MetroWerks specific pragmas with #ifdef's - */ +/*#* + *#* $Log$ + *#* Revision 1.22 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.21 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.20 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. + *#* + *#* Revision 1.19 2004/12/08 08:30:12 bernie + *#* Add missing header. + *#* + *#* Revision 1.18 2004/11/16 21:55:12 bernie + *#* Workaround for a known fifobuf bug. + *#* + *#* Revision 1.17 2004/09/14 20:57:00 bernie + *#* Use debug.h instead of kdebug.h. + *#* + *#* Revision 1.16 2004/09/06 21:39:08 bernie + *#* Simplify code using ATOMIC(). + *#* + *#* Revision 1.15 2004/08/29 22:05:16 bernie + *#* Rename BITS_PER_PTR to CPU_BITS_PER_PTR. + *#* + *#* Revision 1.14 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.13 2004/08/24 13:16:11 bernie + *#* Add type-size definitions for preprocessor. + *#* + *#* Revision 1.12 2004/08/02 20:20:29 aleph + *#* Merge from project_ks + *#* + *#* Revision 1.11 2004/07/30 14:15:53 rasky + *#* Nuovo supporto unificato per detect della CPU + *#* + *#* Revision 1.10 2004/07/29 22:57:09 bernie + *#* Doxygen fix. + *#* + *#* Revision 1.9 2004/07/20 23:54:27 bernie + *#* fifo_flush_locked(): New function; + *#* Revamp documentation. + *#* + *#* Revision 1.8 2004/07/20 23:47:39 bernie + *#* Finally remove redundant protos. + *#* + *#* Revision 1.7 2004/07/20 23:46:29 bernie + *#* Finally remove redundant protos. + *#* + *#* Revision 1.6 2004/06/06 17:18:04 bernie + *#* Remove redundant declaration of fifo_isempty_locked(). + *#* + *#* Revision 1.5 2004/06/06 16:50:35 bernie + *#* Import fixes for race conditions from project_ks. + *#* + *#* Revision 1.4 2004/06/06 16:11:17 bernie + *#* Protect MetroWerks specific pragmas with #ifdef's + *#*/ #ifndef MWARE_FIFO_H #define MWARE_FIFO_H -#include "cpu.h" +#include +#include typedef struct FIFOBuffer { @@ -80,7 +117,16 @@ typedef struct FIFOBuffer } FIFOBuffer; -/*! +#define ASSERT_VALID_FIFO(fifo) \ + ATOMIC( \ + ASSERT((fifo)->head >= (fifo)->begin); \ + ASSERT((fifo)->head <= (fifo)->end); \ + ASSERT((fifo)->tail >= (fifo)->begin); \ + ASSERT((fifo)->tail <= (fifo)->end); \ + ) + + +/** * Check whether the fifo is empty * * \note Calling fifo_isempty() is safe while a concurrent @@ -92,11 +138,12 @@ typedef struct FIFOBuffer */ INLINE bool fifo_isempty(const FIFOBuffer *fb) { + //ASSERT_VALID_FIFO(fb); return fb->head == fb->tail; } -/*! +/** * Check whether the fifo is full * * \note Calling fifo_isfull() is safe while a concurrent @@ -111,13 +158,14 @@ INLINE bool fifo_isempty(const FIFOBuffer *fb) */ INLINE bool fifo_isfull(const FIFOBuffer *fb) { + //ASSERT_VALID_FIFO(fb); return ((fb->head == fb->begin) && (fb->tail == fb->end)) || (fb->tail == fb->head - 1); } -/*! +/** * Pop a character from the fifo buffer. * * \note Calling \c fifo_push() on a full buffer is undefined. @@ -136,10 +184,12 @@ INLINE void fifo_push(FIFOBuffer *fb, unsigned char c) #ifdef __MWERKS__ #pragma interrupt called #endif + //ASSERT_VALID_FIFO(fb); + /* Write at tail position */ *(fb->tail) = c; - if (fb->tail == fb->end) + if (UNLIKELY(fb->tail == fb->end)) /* wrap tail around */ fb->tail = fb->begin; else @@ -148,7 +198,7 @@ INLINE void fifo_push(FIFOBuffer *fb, unsigned char c) } -/*! +/** * Pop a character from the fifo buffer. * * \note Calling \c fifo_pop() on an empty buffer is undefined. @@ -163,7 +213,9 @@ INLINE unsigned char fifo_pop(FIFOBuffer *fb) #ifdef __MWERKS__ #pragma interrupt called #endif - if (fb->head == fb->end) + //ASSERT_VALID_FIFO(fb); + + if (UNLIKELY(fb->head == fb->end)) { /* wrap head around */ fb->head = fb->begin; @@ -175,25 +227,30 @@ INLINE unsigned char fifo_pop(FIFOBuffer *fb) } -/*! +/** * Make the fifo empty, discarding all its current contents. */ INLINE void fifo_flush(FIFOBuffer *fb) { + //ASSERT_VALID_FIFO(fb); fb->head = fb->tail; } -#if !defined(__AVR__) +#if CPU_REG_BITS >= CPU_BITS_PER_PTR - /* No tricks needed on 16/32bit CPUs */ -# define fifo_isempty_locked(fb) fifo_isempty((fb)) -# define fifo_push_locked(fb, c) fifo_push((fb), (c)) -# define fifo_flush_locked(fb, c) fifo_flush((fb), (c)) + /* + * 16/32bit CPUs that can update a pointer with a single write + * operation, no need to disable interrupts. + */ + #define fifo_isempty_locked(fb) fifo_isempty((fb)) + #define fifo_push_locked(fb, c) fifo_push((fb), (c)) + #define fifo_pop_locked(fb) fifo_pop((fb)) + #define fifo_flush_locked(fb) fifo_flush((fb)) -#else /* !__AVR__ */ +#else /* CPU_REG_BITS < CPU_BITS_PER_PTR */ - /*! + /** * Similar to fifo_isempty(), but with stronger guarantees for * concurrent access between user and interrupt code. * @@ -204,16 +261,12 @@ INLINE void fifo_flush(FIFOBuffer *fb) INLINE bool fifo_isempty_locked(const FIFOBuffer *fb) { bool result; - cpuflags_t flags; - - DISABLE_IRQSAVE(flags); - result = fifo_isempty(fb); - ENABLE_IRQRESTORE(flags); - + ATOMIC(result = fifo_isempty(fb)); return result; } - /*! + + /** * Similar to fifo_push(), but with stronger guarantees for * concurrent access between user and interrupt code. * @@ -223,13 +276,18 @@ INLINE void fifo_flush(FIFOBuffer *fb) */ INLINE void fifo_push_locked(FIFOBuffer *fb, unsigned char c) { - cpuflags_t flags; - DISABLE_IRQSAVE(flags); - fifo_push(fb, c); - ENABLE_IRQRESTORE(flags); + ATOMIC(fifo_push(fb, c)); } - /*! + /* Probably not really needed, but hard to prove. */ + INLINE unsigned char fifo_pop_locked(FIFOBuffer *fb) + { + unsigned char c; + ATOMIC(c = fifo_pop(fb)); + return c; + } + + /** * Similar to fifo_flush(), but with stronger guarantees for * concurrent access between user and interrupt code. * @@ -239,36 +297,31 @@ INLINE void fifo_flush(FIFOBuffer *fb) */ INLINE void fifo_flush_locked(FIFOBuffer *fb) { - cpuflags_t flags; - DISABLE_IRQSAVE(flags); - fifo_flush(fb); - ENABLE_IRQRESTORE(flags); + ATOMIC(fifo_flush(fb)); } -#endif /* !__AVR__ */ +#endif /* CPU_REG_BITS < BITS_PER_PTR */ -/*! +/** * Thread safe version of fifo_isfull() */ INLINE bool fifo_isfull_locked(const FIFOBuffer *_fb) { - bool _result; - cpuflags_t _flags; - - DISABLE_IRQSAVE(_flags); - _result = fifo_isfull(_fb); - ENABLE_IRQRESTORE(_flags); - - return _result; + bool result; + ATOMIC(result = fifo_isfull(_fb)); + return result; } -/*! +/** * FIFO Initialization. */ INLINE void fifo_init(FIFOBuffer *fb, unsigned char *buf, size_t size) { + /* FIFO buffers have a known bug with 1-byte buffers. */ + ASSERT(size > 1); + fb->head = fb->tail = fb->begin = buf; fb->end = buf + size - 1; }