Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/drm2/include/linux Rewrite <linux/kfifo.h>.



details:   https://anonhg.NetBSD.org/src/rev/4bdc4fa5fc51
branches:  trunk
changeset: 366222:4bdc4fa5fc51
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Aug 27 14:00:26 2018 +0000

description:
Rewrite <linux/kfifo.h>.

pcq isn't flexible enough for its needs now.  Just use a spinlocked
circular buffer.

diffstat:

 sys/external/bsd/drm2/include/linux/kfifo.h |  206 +++++++++++++++++++++++++--
 1 files changed, 184 insertions(+), 22 deletions(-)

diffs (226 lines):

diff -r c454e974e1b8 -r 4bdc4fa5fc51 sys/external/bsd/drm2/include/linux/kfifo.h
--- a/sys/external/bsd/drm2/include/linux/kfifo.h       Mon Aug 27 13:58:16 2018 +0000
+++ b/sys/external/bsd/drm2/include/linux/kfifo.h       Mon Aug 27 14:00:26 2018 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: kfifo.h,v 1.1 2014/07/16 20:56:25 riastradh Exp $      */
+/*     $NetBSD: kfifo.h,v 1.2 2018/08/27 14:00:26 riastradh Exp $      */
 
 /*-
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -32,30 +32,192 @@
 #ifndef        _LINUX_KFIFO_H_
 #define        _LINUX_KFIFO_H_
 
-#include <sys/pcq.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/mutex.h>
+
+#include <linux/gfp.h>
+#include <linux/slab.h>
+
+struct kfifo_meta {
+       kmutex_t        kfm_lock;
+       size_t          kfm_head;
+       size_t          kfm_tail;
+       size_t          kfm_nbytes;
+};
+
+#define        _KFIFO_PTR_TYPE(TAG, TYPE)                                            \
+       struct TAG {                                                          \
+               struct kfifo_meta       kf_meta;                              \
+               TYPE                    *kf_buf;                              \
+       }
+
+#define        DECLARE_KFIFO_PTR(FIFO, TYPE)   _KFIFO_PTR_TYPE(, TYPE) FIFO
+
+_KFIFO_PTR_TYPE(kfifo, void);
+
+#define        kfifo_alloc(FIFO, SIZE, GFP)                                          \
+       _kfifo_alloc(&(FIFO)->kf_meta, &(FIFO)->kf_buf, (SIZE), (GFP))
+
+static inline int
+_kfifo_alloc(struct kfifo_meta *meta, void *bufp, size_t nbytes, gfp_t gfp)
+{
+       void *buf;
+
+       buf = kmalloc(nbytes, gfp);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       /* Type pun!  Hope void * == struct whatever *.  */
+       memcpy(bufp, &buf, sizeof(void *));
+
+       mutex_init(&meta->kfm_lock, MUTEX_DEFAULT, IPL_NONE);
+       meta->kfm_head = 0;
+       meta->kfm_tail = 0;
+       meta->kfm_nbytes = nbytes;
 
-#define        DECLARE_KFIFO_PTR(fifo, type)                                         \
-       struct {                                                              \
-               pcq_t   *pcq;                                                 \
-               type    *dummy;                                               \
-       } fifo
+       return 0;
+}
+
+#define        kfifo_free(FIFO)                                                      \
+       _kfifo_free(&(FIFO)->kf_meta, &(FIFO)->kf_buf)
+
+static inline void
+_kfifo_free(struct kfifo_meta *meta, void *bufp)
+{
+       void *buf;
+
+       mutex_destroy(&meta->kfm_lock);
+
+       memcpy(&buf, bufp, sizeof(void *));
+       kfree(buf);
+
+       /* Paranoia.  */
+       buf = NULL;
+       memcpy(bufp, &buf, sizeof(void *));
+}
+
+#define        kfifo_is_empty(FIFO)    (kfifo_len(FIFO) == 0)
+#define        kfifo_len(FIFO)         _kfifo_len(&(FIFO)->kf_meta)
+
+static inline size_t
+_kfifo_len(struct kfifo_meta *meta)
+{
+       const size_t head = meta->kfm_head;
+       const size_t tail = meta->kfm_tail;
+       const size_t nbytes = meta->kfm_nbytes;
+
+       return (head <= tail ? tail - head : nbytes + tail - head);
+}
+
+#define        kfifo_out_peek(FIFO, PTR, SIZE)                                       \
+       _kfifo_out_peek(&(FIFO)->kf_meta, (FIFO)->kf_buf, (PTR), (SIZE))
+
+static inline size_t
+_kfifo_out_peek(struct kfifo_meta *meta, void *buf, void *ptr, size_t size)
+{
+       const char *src = buf;
+       char *dst = ptr;
+       size_t copied = 0;
 
-#define        kfifo_put(fifo, item)                                                 \
-       pcq_put((fifo)->pcq, __UNCONST((const char *)(item) +                 \
-               0*sizeof((item) == *(fifo)->dummy)))
-#define        kfifo_get(fifo, itemp)                                                \
-       ((*((itemp) + 0*sizeof((itemp) - (fifo)->dummy)) =                    \
-           pcq_get((fifo)->pcq)) != NULL)
+       mutex_enter(&meta->kfm_lock);
+       const size_t head = meta->kfm_head;
+       const size_t tail = meta->kfm_tail;
+       const size_t nbytes = meta->kfm_nbytes;
+       if (head <= tail) {
+               if (size <= tail - head) {
+                       memcpy(dst, src + head, size);
+                       copied = size;
+               }
+       } else {
+               if (size <= nbytes - head) {
+                       memcpy(dst, src + head, size);
+                       copied = size;
+               } else if (size <= nbytes + tail - head) {
+                       memcpy(dst, src + head, nbytes - head);
+                       memcpy(dst + nbytes - head, src,
+                           size - (nbytes - head));
+                       copied = size;
+               }
+       }
+       mutex_exit(&meta->kfm_lock);
+
+       return copied;
+}
+
+#define        kfifo_out(FIFO, PTR, SIZE)                                            \
+       _kfifo_out(&(FIFO)->kf_meta, (FIFO)->kf_buf, (PTR), (SIZE))
+
+static inline size_t
+_kfifo_out(struct kfifo_meta *meta, const void *buf, void *ptr, size_t size)
+{
+       const char *src = buf;
+       char *dst = ptr;
+       size_t copied = 0;
 
-#define        kfifo_is_empty(fifo)                                                  \
-       (pcq_peek((fifo)->pcq) == NULL)
+       mutex_enter(&meta->kfm_lock);
+       const size_t head = meta->kfm_head;
+       const size_t tail = meta->kfm_tail;
+       const size_t nbytes = meta->kfm_nbytes;
+       if (head <= tail) {
+               if (size <= tail - head) {
+                       memcpy(dst, src + head, size);
+                       meta->kfm_head = head + size;
+                       copied = size;
+               }
+       } else {
+               if (size <= nbytes - head) {
+                       memcpy(dst, src + head, size);
+                       meta->kfm_head = head + size;
+                       copied = size;
+               } else if (size <= nbytes + tail - head) {
+                       memcpy(dst, src + head, nbytes - head);
+                       memcpy(dst + nbytes - head, src,
+                           size - (nbytes - head));
+                       meta->kfm_head = size - (nbytes - head);
+                       copied = size;
+               }
+       }
+       mutex_exit(&meta->kfm_lock);
+
+       return copied;
+}
+
+#define        kfifo_in(FIFO, PTR, SIZE)                                             \
+       _kfifo_in(&(FIFO)->kf_meta, (FIFO)->kf_buf, (PTR), (SIZE))
 
-#define        kfifo_alloc(fifo, size, gfp)                                          \
-       (((fifo)->pcq = pcq_create((size),                                    \
-               ISSET((gfp), __GFP_WAIT)? KM_SLEEP : KM_NOSLEEP))             \
-           == NULL? -ENOMEM : 0)
+static inline size_t
+_kfifo_in(struct kfifo_meta *meta, void *buf, const void *ptr, size_t size)
+{
+       const char *src = ptr;
+       char *dst = buf;
+       size_t copied = 0;
 
-#define        kfifo_free(fifo)                                                      \
-       pcq_destroy((fifo)->pcq)
+       mutex_enter(&meta->kfm_lock);
+       const size_t head = meta->kfm_head;
+       const size_t tail = meta->kfm_tail;
+       const size_t nbytes = meta->kfm_nbytes;
+       if (tail <= head) {
+               if (size <= head - tail) {
+                       memcpy(dst + tail, src, size);
+                       meta->kfm_tail = tail + size;
+                       copied = size;
+               }
+       } else {
+               if (size <= nbytes - tail) {
+                       memcpy(dst + tail, src, size);
+                       meta->kfm_tail = tail + size;
+               } else if (size <= nbytes + tail - head) {
+                       memcpy(dst + tail, src, nbytes - tail);
+                       memcpy(dst, src + nbytes - tail,
+                           size - (nbytes - tail));
+                       meta->kfm_tail = size - (nbytes - tail);
+                       copied = size;
+               }
+       }
+       mutex_exit(&meta->kfm_lock);
+
+       return copied;
+}
 
 #endif /* _LINUX_KFIFO_H_ */



Home | Main Index | Thread Index | Old Index