text: /*
   * A generic kernel FIFO implementation
   *
   * Copyright (C) 2013 Stefani Seibold <stefani@seibold.net>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   */
  
  #ifndef BUBBLEFS_UTILS_LINUX_KFIFO_H_
  #define BUBBLEFS_UTILS_LINUX_KFIFO_H_
  
  #include <errno.h>
  #include <string.h>
  
  /*
   * How to porting drivers to the new generic FIFO API:
   *
   * - Modify the declaration of the "struct kfifo *" object into a
   *   in-place "struct kfifo" object
   * - Init the in-place object with kfifo_alloc() or kfifo_init()
   *   Note: The address of the in-place "struct kfifo" object must be
   *   passed as the first argument to this functions
   * - Replace the use of __kfifo_put into kfifo_in and __kfifo_get
   *   into kfifo_out
   * - Replace the use of kfifo_put into kfifo_in_spinlocked and kfifo_get
   *   into kfifo_out_spinlocked
   *   Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc
   *   must be passed now to the kfifo_in_spinlocked and kfifo_out_spinlocked
   *   as the last parameter
   * - The formerly __kfifo_* functions are renamed into kfifo_*
   */
  
  /*
  #include <linux/kernel.h>
  #include <linux/spinlock.h>
  #include <linux/stddef.h>
  #include <linux/scatterlist.h>
  */
  
  namespace bubblefs {
  namespace mylinux {
    
  // Note: make sure use in one thread
  //#define barrier() __asm__ __volatile__("": : :"memory")
  //#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
  //#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
  #define smp_wmb()  
    
  struct __kfifo {
          unsigned int    in;
          unsigned int    out;
          unsigned int    mask;
          unsigned int    esize;
          char            *data;
  };
  
  #define __STRUCT_KFIFO_COMMON(datatype, recsize, ptrtype) \
          union { \
                  struct __kfifo  kfifo; \
                  datatype        *type; \
                  const datatype  *const_type; \
                  char            (*rectype)[recsize]; \
                  ptrtype         *ptr; \
                  ptrtype const   *ptr_const; \
          }
  
  #define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
  { \
          __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
          type            buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
  }
  
  #define STRUCT_KFIFO(type, size) \
          struct __STRUCT_KFIFO(type, size, 0, type)
  
  #define __STRUCT_KFIFO_PTR(type, recsize, ptrtype) \
  { \
          __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
          type            buf[0]; \
  }
  
  #define STRUCT_KFIFO_PTR(type) \
          struct __STRUCT_KFIFO_PTR(type, 0, type)
  
  //#define STRUCT_KFIFO_REC_1(size) \
  //        struct __STRUCT_KFIFO(unsigned char, size, 1, void)
  
  //#define STRUCT_KFIFO_REC_2(size) \
  //        struct __STRUCT_KFIFO(unsigned char, size, 2, void)
  
  /*
   * define kfifo_rec types
   */
  //struct kfifo_rec_ptr_1 __STRUCT_KFIFO_PTR(unsigned char, 1, void);
  //struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
  
  /*
   * helper macro to distinguish between real in place fifo where the fifo
   * array is a part of the structure and the fifo type where the array is
   * outside of the fifo structure.
   */
  #define __is_kfifo_ptr(fifo)    (sizeof(*fifo) == sizeof(struct __kfifo))
  
  /**
   * DECLARE_KFIFO_PTR - macro to declare a fifo pointer object
   * @fifo: name of the declared fifo
   * @type: type of the fifo elements
   */
  #define DECLARE_KFIFO_PTR(fifo, type)   STRUCT_KFIFO_PTR(type) fifo
  
  /**
   * DECLARE_KFIFO - macro to declare a fifo object
   * @fifo: name of the declared fifo
   * @type: type of the fifo elements
   * @size: the number of elements in the fifo, this must be a power of 2
   */
  #define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo
  
  /**
   * INIT_KFIFO - Initialize a fifo declared by DECLARE_KFIFO
   * @fifo: name of the declared fifo datatype
   */
  #define INIT_KFIFO(fifo) \
  (void)({ \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          __kfifo->in = 0; \
          __kfifo->out = 0; \
          __kfifo->mask = __is_kfifo_ptr(fifo) ? 0 : ARRAY_SIZE(fifo->buf) - 1;\
          __kfifo->esize = sizeof(*fifo->buf); \
          __kfifo->data = __is_kfifo_ptr(fifo) ?  NULL : fifo->buf; \
  })
  
  /**
   * DEFINE_KFIFO - macro to define and initialize a fifo
   * @fifo: name of the declared fifo datatype
   * @type: type of the fifo elements
   * @size: the number of elements in the fifo, this must be a power of 2
   *
   * Note: the macro can be used for global and local fifo data type variables.
   */
  /*
  #define DEFINE_KFIFO(fifo, type, size) \
          DECLARE_KFIFO(fifo, type, size) = \
          (typedef(fifo)) { \
                  { \
                          { \
                          .in     = 0, \
                          .out    = 0, \
                          .mask   = __is_kfifo_ptr(&(fifo)) ? \
                                    0 : \
                                    ARRAY_SIZE((fifo).buf) - 1, \
                          .esize  = sizeof(*(fifo).buf), \
                          .data   = __is_kfifo_ptr(&(fifo)) ? \
                                  NULL : \
                                  (fifo).buf, \
                          } \
                  } \
          }
  */
  
  static inline unsigned int
  __kfifo_uint_must_check_helper(unsigned int val)
  {
          return val;
  }
  
  static inline int
  __kfifo_int_must_check_helper(int val)
  {
          return val;
  }
  
  /**
   * kfifo_initialized - Check if the fifo is initialized
   * @fifo: address of the fifo to check
   *
   * Return %true if fifo is initialized, otherwise %false.
   * Assumes the fifo was 0 before.
   */
  #define kfifo_initialized(fifo) ((fifo)->kfifo.mask)
  
  /**
   * kfifo_esize - returns the size of the element managed by the fifo
   * @fifo: address of the fifo to be used
   */
  #define kfifo_esize(fifo)       ((fifo)->kfifo.esize)
  
  /**
   * kfifo_recsize - returns the size of the record length field
   * @fifo: address of the fifo to be used
   */
  #define kfifo_recsize(fifo)     (sizeof(*(fifo)->rectype))
  
  /**
   * kfifo_size - returns the size of the fifo in elements
   * @fifo: address of the fifo to be used
   */
  #define kfifo_size(fifo)        ((fifo)->kfifo.mask + 1)
  
  /**
   * kfifo_reset - removes the entire fifo content
   * @fifo: address of the fifo to be used
   *
   * Note: usage of kfifo_reset() is dangerous. It should be only called when the
   * fifo is exclusived locked or when it is secured that no other thread is
   * accessing the fifo.
   */
  #define kfifo_reset(fifo) \
  (void)({ \
          fifo->kfifo.in = fifo->kfifo.out = 0; \
  })
  
  /**
   * kfifo_reset_out - skip fifo content
   * @fifo: address of the fifo to be used
   *
   * Note: The usage of kfifo_reset_out() is safe until it will be only called
   * from the reader thread and there is only one concurrent reader. Otherwise
   * it is dangerous and must be handled in the same way as kfifo_reset().
   */
  #define kfifo_reset_out(fifo)   \
  (void)({ \
          fifo->kfifo.out = fifo->kfifo.in; \
  })
  
  /**
   * kfifo_len - returns the number of used elements in the fifo
   * @fifo: address of the fifo to be used
   */
  #define kfifo_len(fifo) \
  ({ \
          fifo->kfifo.in - fifo->kfifo.out; \
  })
  
  /**
   * kfifo_is_empty - returns true if the fifo is empty
   * @fifo: address of the fifo to be used
   */
  #define kfifo_is_empty(fifo) \
  ({ \
          fifo->kfifo.in == fifo->kfifo.out; \
  })
  
  /**
   * kfifo_is_full - returns true if the fifo is full
   * @fifo: address of the fifo to be used
   */
  #define kfifo_is_full(fifo) \
  ({ \
          kfifo_len(fifo) > fifo->kfifo.mask; \
  })
  
  /**
   * kfifo_avail - returns the number of unused elements in the fifo
   * @fifo: address of the fifo to be used
   */
  #define kfifo_avail(fifo) \
  __kfifo_uint_must_check_helper( \
  ({ \
          const size_t __recsize = sizeof(*fifo->rectype); \
          unsigned int __avail = kfifo_size(fifo) - kfifo_len(fifo); \
          (__recsize) ? ((__avail <= __recsize) ? 0 : \
          __kfifo_max_r(__avail - __recsize, __recsize)) : \
          __avail; \
  }) \
  )
  
  /**
   * kfifo_skip - skip output data
   * @fifo: address of the fifo to be used
   */
  #define kfifo_skip(fifo) \
  (void)({ \
          const size_t __recsize = sizeof(*fifo->rectype); \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          if (__recsize) \
                  __kfifo_skip_r(__kfifo, __recsize); \
          else \
                  __kfifo->out++; \
  })
  
  /**
   * kfifo_peek_len - gets the size of the next fifo record
   * @fifo: address of the fifo to be used
   *
   * This function returns the size of the next fifo record in number of bytes.
   */
  #define kfifo_peek_len(fifo) \
  __kfifo_uint_must_check_helper( \
  ({ \
          const size_t __recsize = sizeof(*fifo->rectype); \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          (!__recsize) ? kfifo_len(fifo) * sizeof(*fifo->type) : \
          __kfifo_len_r(__kfifo, __recsize); \
  }) \
  )
  
  /**
   * kfifo_alloc - dynamically allocates a new fifo buffer
   * @fifo: pointer to the fifo
   * @size: the number of elements in the fifo, this must be a power of 2
   * @gfp_mask: get_free_pages mask, passed to kmalloc()
   *
   * This macro dynamically allocates a new fifo buffer.
   *
   * The numer of elements will be rounded-up to a power of 2.
   * The fifo will be release with kfifo_free().
   * Return 0 if no error, otherwise an error code.
   */
  /* 
  #define kfifo_alloc(fifo, size, gfp_mask) \
  __kfifo_int_must_check_helper( \
  ({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          __is_kfifo_ptr(__tmp) ? \
          __kfifo_alloc(__kfifo, size, sizeof(*__tmp->type), gfp_mask) : \
          -EINVAL; \
  }) \
  ) 
  */
  
  /**
   * kfifo_free - frees the fifo
   * @fifo: the fifo to be freed
   */
  /* 
  #define kfifo_free(fifo) \
  ({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          if (__is_kfifo_ptr(__tmp)) \
                  __kfifo_free(__kfifo); \
  }) 
  */
  
  /**
   * kfifo_init - initialize a fifo using a preallocated buffer
   * @fifo: the fifo to assign the buffer
   * @buffer: the preallocated buffer to be used
   * @size: the size of the internal buffer, this have to be a power of 2
   *
   * This macro initialize a fifo using a preallocated buffer.
   *
   * The numer of elements will be rounded-up to a power of 2.
   * Return 0 if no error, otherwise an error code.
   */
  #define kfifo_init(fifo, buffer, size) \
  ({ \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          __is_kfifo_ptr(fifo) ? \
          __kfifo_init(__kfifo, buffer, size, sizeof(*fifo->type)) : \
          -EINVAL; \
  })
  
  /**
   * kfifo_put - put data into the fifo
   * @fifo: address of the fifo to be used
   * @val: the data to be added
   *
   * This macro copies the given value into the fifo.
   * It returns 0 if the fifo was full. Otherwise it returns the number
   * processed elements.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  /*
  #define kfifo_put(fifo, val) \
  ({ \
          typedef((fifo) + 1) __tmp = (fifo); \
          typedef(*__tmp->const_type) __val = (val); \
          unsigned int __ret; \
          size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          if (__recsize) \
                  __ret = __kfifo_in_r(__kfifo, &__val, sizeof(__val), \
                          __recsize); \
          else { \
                  __ret = !kfifo_is_full(__tmp); \
                  if (__ret) { \
                          (__is_kfifo_ptr(__tmp) ? \
                          ((typedef(__tmp->type))__kfifo->data) : \
                          (__tmp->buf) \
                          )[__kfifo->in & __tmp->kfifo.mask] = \
                                  (typedef(*__tmp->type))__val; \
                          smp_wmb(); \
                          __kfifo->in++; \
                  } \
          } \
          __ret; \
  })
  */
  
  /**
   * kfifo_get - get data from the fifo
   * @fifo: address of the fifo to be used
   * @val: address where to store the data
   *
   * This macro reads the data from the fifo.
   * It returns 0 if the fifo was empty. Otherwise it returns the number
   * processed elements.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  /*
  #define kfifo_get(fifo, val) \
  __kfifo_uint_must_check_helper( \
  ({ \
          typedef((fifo) + 1) __tmp = (fifo); \
          typedef(__tmp->ptr) __val = (val); \
          unsigned int __ret; \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          if (__recsize) \
                  __ret = __kfifo_out_r(__kfifo, __val, sizeof(*__val), \
                          __recsize); \
          else { \
                  __ret = !kfifo_is_empty(__tmp); \
                  if (__ret) { \
                          *(typedef(__tmp->type))__val = \
                                  (__is_kfifo_ptr(__tmp) ? \
                                  ((typedef(__tmp->type))__kfifo->data) : \
                                  (__tmp->buf) \
                                  )[__kfifo->out & __tmp->kfifo.mask]; \
                          smp_wmb(); \
                          __kfifo->out++; \
                  } \
          } \
          __ret; \
  }) \
  )
  */
  
  /**
   * kfifo_peek - get data from the fifo without removing
   * @fifo: address of the fifo to be used
   * @val: address where to store the data
   *
   * This reads the data from the fifo without removing it from the fifo.
   * It returns 0 if the fifo was empty. Otherwise it returns the number
   * processed elements.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  /*
  #define kfifo_peek(fifo, val) \
  __kfifo_uint_must_check_helper( \
  ({ \
          typedef((fifo) + 1) __tmp = (fifo); \
          typedef(__tmp->ptr) __val = (val); \
          unsigned int __ret; \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          if (__recsize) \
                  __ret = __kfifo_out_peek_r(__kfifo, __val, sizeof(*__val), \
                          __recsize); \
          else { \
                  __ret = !kfifo_is_empty(__tmp); \
                  if (__ret) { \
                          *(typedef(__tmp->type))__val = \
                                  (__is_kfifo_ptr(__tmp) ? \
                                  ((typedef(__tmp->type))__kfifo->data) : \
                                  (__tmp->buf) \
                                  )[__kfifo->out & __tmp->kfifo.mask]; \
                          smp_wmb(); \
                  } \
          } \
          __ret; \
  }) \
  )
  */
  
  /**
   * kfifo_in - put data into the fifo
   * @fifo: address of the fifo to be used
   * @buf: the data to be added
   * @n: number of elements to be added
   *
   * This macro copies the given buffer into the fifo and returns the
   * number of copied elements.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  #define kfifo_in(fifo, buf, n) \
  ({ \
          char *__buf = (buf); \
          unsigned long __n = (n); \
          const size_t __recsize = sizeof(*fifo->rectype); \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          (__recsize) ?\
          __kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
          __kfifo_in(__kfifo, __buf, __n); \
  })
  
  /**
   * kfifo_in_spinlocked - put data into the fifo using a spinlock for locking
   * @fifo: address of the fifo to be used
   * @buf: the data to be added
   * @n: number of elements to be added
   * @lock: pointer to the spinlock to use for locking
   *
   * This macro copies the given values buffer into the fifo and returns the
   * number of copied elements.
   */
  /*
  #define kfifo_in_spinlocked(fifo, buf, n, lock) \
  ({ \
          unsigned long __flags; \
          unsigned int __ret; \
          spin_lock_irqsave(lock, __flags); \
          __ret = kfifo_in(fifo, buf, n); \
          spin_unlock_irqrestore(lock, __flags); \
          __ret; \
  })
  */
  
  /* alias for kfifo_in_spinlocked, will be removed in a future release */
  /*
  #define kfifo_in_locked(fifo, buf, n, lock) \
                  kfifo_in_spinlocked(fifo, buf, n, lock)
  */
  
  /**
   * kfifo_out - get data from the fifo
   * @fifo: address of the fifo to be used
   * @buf: pointer to the storage buffer
   * @n: max. number of elements to get
   *
   * This macro get some data from the fifo and return the numbers of elements
   * copied.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  #define kfifo_out(fifo, buf, n) \
  __kfifo_uint_must_check_helper( \
  ({ \
          char *__buf = (buf); \
          unsigned long __n = (n); \
          const size_t __recsize = sizeof(*fifo->rectype); \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          (__recsize) ?\
          __kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
          __kfifo_out(__kfifo, __buf, __n); \
  }) \
  )
  
  /**
   * kfifo_out_spinlocked - get data from the fifo using a spinlock for locking
   * @fifo: address of the fifo to be used
   * @buf: pointer to the storage buffer
   * @n: max. number of elements to get
   * @lock: pointer to the spinlock to use for locking
   *
   * This macro get the data from the fifo and return the numbers of elements
   * copied.
   */
  /*
  #define kfifo_out_spinlocked(fifo, buf, n, lock) \
  __kfifo_uint_must_check_helper( \
  ({ \
          unsigned long __flags; \
          unsigned int __ret; \
          spin_lock_irqsave(lock, __flags); \
          __ret = kfifo_out(fifo, buf, n); \
          spin_unlock_irqrestore(lock, __flags); \
          __ret; \
  }) \
  )
  */
  
  /* alias for kfifo_out_spinlocked, will be removed in a future release */
  /*
  #define kfifo_out_locked(fifo, buf, n, lock) \
                  kfifo_out_spinlocked(fifo, buf, n, lock)
  */
  
  /**
   * kfifo_from_user - puts some data from user space into the fifo
   * @fifo: address of the fifo to be used
   * @from: pointer to the data to be added
   * @len: the length of the data to be added
   * @copied: pointer to output variable to store the number of copied bytes
   *
   * This macro copies at most @len bytes from the @from into the
   * fifo, depending of the available space and returns -EFAULT/0.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  /*
  #define kfifo_from_user(fifo, from, len, copied) \
  __kfifo_uint_must_check_helper( \
  ({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          const void __user *__from = (from); \
          unsigned int __len = (len); \
          unsigned int *__copied = (copied); \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          (__recsize) ? \
          __kfifo_from_user_r(__kfifo, __from, __len,  __copied, __recsize) : \
          __kfifo_from_user(__kfifo, __from, __len, __copied); \
  }) \
  )
  */
  
  /**
   * kfifo_to_user - copies data from the fifo into user space
   * @fifo: address of the fifo to be used
   * @to: where the data must be copied
   * @len: the size of the destination buffer
   * @copied: pointer to output variable to store the number of copied bytes
   *
   * This macro copies at most @len bytes from the fifo into the
   * @to buffer and returns -EFAULT/0.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  /*
  #define kfifo_to_user(fifo, to, len, copied) \
  __kfifo_uint_must_check_helper( \
  ({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          void __user *__to = (to); \
          unsigned int __len = (len); \
          unsigned int *__copied = (copied); \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          (__recsize) ? \
          __kfifo_to_user_r(__kfifo, __to, __len, __copied, __recsize) : \
          __kfifo_to_user(__kfifo, __to, __len, __copied); \
  }) \
  )
  */
  
  /**
   * kfifo_dma_in_prepare - setup a scatterlist for DMA input
   * @fifo: address of the fifo to be used
   * @sgl: pointer to the scatterlist array
   * @nents: number of entries in the scatterlist array
   * @len: number of elements to transfer
   *
   * This macro fills a scatterlist for DMA input.
   * It returns the number entries in the scatterlist array.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macros.
   */
  /*
  #define kfifo_dma_in_prepare(fifo, sgl, nents, len) \
  ({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          struct scatterlist *__sgl = (sgl); \
          int __nents = (nents); \
          unsigned int __len = (len); \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          (__recsize) ? \
          __kfifo_dma_in_prepare_r(__kfifo, __sgl, __nents, __len, __recsize) : \
          __kfifo_dma_in_prepare(__kfifo, __sgl, __nents, __len); \
  })
  */
  
  /**
   * kfifo_dma_in_finish - finish a DMA IN operation
   * @fifo: address of the fifo to be used
   * @len: number of bytes to received
   *
   * This macro finish a DMA IN operation. The in counter will be updated by
   * the len parameter. No error checking will be done.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macros.
   */
  /*
  #define kfifo_dma_in_finish(fifo, len) \
  (void)({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          unsigned int __len = (len); \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          if (__recsize) \
                  __kfifo_dma_in_finish_r(__kfifo, __len, __recsize); \
          else \
                  __kfifo->in += __len / sizeof(*__tmp->type); \
  })
  */
  
  /**
   * kfifo_dma_out_prepare - setup a scatterlist for DMA output
   * @fifo: address of the fifo to be used
   * @sgl: pointer to the scatterlist array
   * @nents: number of entries in the scatterlist array
   * @len: number of elements to transfer
   *
   * This macro fills a scatterlist for DMA output which at most @len bytes
   * to transfer.
   * It returns the number entries in the scatterlist array.
   * A zero means there is no space available and the scatterlist is not filled.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macros.
   */
  /*
  #define kfifo_dma_out_prepare(fifo, sgl, nents, len) \
  ({ \
          typeof((fifo) + 1) __tmp = (fifo);  \
          struct scatterlist *__sgl = (sgl); \
          int __nents = (nents); \
          unsigned int __len = (len); \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          (__recsize) ? \
          __kfifo_dma_out_prepare_r(__kfifo, __sgl, __nents, __len, __recsize) : \
          __kfifo_dma_out_prepare(__kfifo, __sgl, __nents, __len); \
  })
  */
  
  /**
   * kfifo_dma_out_finish - finish a DMA OUT operation
   * @fifo: address of the fifo to be used
   * @len: number of bytes transferd
   *
   * This macro finish a DMA OUT operation. The out counter will be updated by
   * the len parameter. No error checking will be done.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macros.
   */
  /*
  #define kfifo_dma_out_finish(fifo, len) \
  (void)({ \
          typeof((fifo) + 1) __tmp = (fifo); \
          unsigned int __len = (len); \
          const size_t __recsize = sizeof(*__tmp->rectype); \
          struct __kfifo *__kfifo = &__tmp->kfifo; \
          if (__recsize) \
                  __kfifo_dma_out_finish_r(__kfifo, __recsize); \
          else \
                  __kfifo->out += __len / sizeof(*__tmp->type); \
  })
  */
  
  
  /**
   * kfifo_out_peek - gets some data from the fifo
   * @fifo: address of the fifo to be used
   * @buf: pointer to the storage buffer
   * @n: max. number of elements to get
   *
   * This macro get the data from the fifo and return the numbers of elements
   * copied. The data is not removed from the fifo.
   *
   * Note that with only one concurrent reader and one concurrent
   * writer, you don't need extra locking to use these macro.
   */
  #define kfifo_out_peek(fifo, buf, n) \
  __kfifo_uint_must_check_helper( \
  ({ \
          char *__buf = (buf); \
          unsigned long __n = (n); \
          const size_t __recsize = sizeof(*fifo->rectype); \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          (__recsize) ? \
          __kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \
          __kfifo_out_peek(__kfifo, __buf, __n); \
  }) \
  )
  
  #define kfifo_out_peek_offset(fifo, buf, n, off) \
  __kfifo_uint_must_check_helper( \
  ({ \
          char *__buf = (buf); \
          unsigned long __n = (n); \
          const size_t __recsize = sizeof(*fifo->rectype); \
          struct __kfifo *__kfifo = &fifo->kfifo; \
          (__recsize) ? \
          __kfifo_out_peek_r(__kfifo, __buf, __n, __recsize) : \
          __kfifo_out_peek_offset(__kfifo, __buf, __n, off); \
  }) \
  )
  
  /*
  extern int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
          size_t esize, gfp_t gfp_mask);
  */
  extern void __kfifo_free(struct __kfifo *fifo);
  
  extern int __kfifo_init(struct __kfifo *fifo, char *buffer,
          unsigned int size, size_t esize);
  
  extern unsigned int __kfifo_in(struct __kfifo *fifo,
          const char *buf, unsigned int len);
  
  extern unsigned int __kfifo_out(struct __kfifo *fifo,
          char *buf, unsigned int len);
  /*
  extern int __kfifo_from_user(struct __kfifo *fifo,
          const void __user *from, unsigned long len, unsigned int *copied);
  extern int __kfifo_to_user(struct __kfifo *fifo,
          void __user *to, unsigned long len, unsigned int *copied);
  extern unsigned int __kfifo_dma_in_prepare(struct __kfifo *fifo,
          struct scatterlist *sgl, int nents, unsigned int len);
  extern unsigned int __kfifo_dma_out_prepare(struct __kfifo *fifo,
          struct scatterlist *sgl, int nents, unsigned int len);
  */
  
  extern unsigned int __kfifo_out_peek(struct __kfifo *fifo,
          char *buf, unsigned int len);
  
  extern unsigned int __kfifo_in_r(struct __kfifo *fifo,
          const char *buf, unsigned int len, size_t recsize);
  
  extern unsigned int __kfifo_out_r(struct __kfifo *fifo,
          char *buf, unsigned int len, size_t recsize);
  /*
  extern int __kfifo_from_user_r(struct __kfifo *fifo,
          const void __user *from, unsigned long len, unsigned int *copied,
          size_t recsize);
  extern int __kfifo_to_user_r(struct __kfifo *fifo, void __user *to,
          unsigned long len, unsigned int *copied, size_t recsize);
  extern unsigned int __kfifo_dma_in_prepare_r(struct __kfifo *fifo,
          struct scatterlist *sgl, int nents, unsigned int len, size_t recsize);
  extern void __kfifo_dma_in_finish_r(struct __kfifo *fifo,
          unsigned int len, size_t recsize);
  extern unsigned int __kfifo_dma_out_prepare_r(struct __kfifo *fifo,
          struct scatterlist *sgl, int nents, unsigned int len, size_t recsize);
  extern void __kfifo_dma_out_finish_r(struct __kfifo *fifo, size_t recsize);
  */
  
  extern unsigned int __kfifo_len_r(struct __kfifo *fifo, size_t recsize);
  
  extern void __kfifo_skip_r(struct __kfifo *fifo, size_t recsize);
  
  extern unsigned int __kfifo_out_peek_r(struct __kfifo *fifo,
          char *buf, unsigned int len, size_t recsize);
  
  extern unsigned int __kfifo_max_r(unsigned int len, size_t recsize);
  
  /*
   * define compatibility "struct kfifo" for dynamic allocated fifos
   */
  struct Kfifo __STRUCT_KFIFO_PTR(unsigned char, 0, void);
  
  extern int kfifo_pop(Kfifo *fifo, char *buffer, size_t buffer_size);
  extern int kfifo_peek_offset(Kfifo *fifo, char *buffer, size_t buffer_size, size_t offset);
  extern int kfifo_push(Kfifo *fifo, char *buffer, size_t buffer_size);
  extern int kfifo_push_force(Kfifo *fifo, char *buffer, size_t buffer_size, int *is_forced);
  
  #undef smp_wmb
  
  } // namespace mylinux
  } // namespace bubblefs
  
  #endif // BUBBLEFS_UTILS_LINUX_KFIFO_H_