summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2016-10-19 10:26:56 -0500
committerBenjamin Walsh <benjamin.walsh@windriver.com>2016-10-21 15:33:31 +0000
commit11a1bb4125329c065720554fcaa23328f24997ba (patch)
tree65dfb2631bb87b0f78269209489b9a5d138061c8 /doc
parentb9a4bd906c8b4d6edbc8cbd94668bde7fdcb71ca (diff)
unified/doc: Update ring buffers section of Kernel Primer
Ring buffer section now resides under "other" topic, since the ring buffer type is a general purpose type (like the singly and doubly linked list types), rather than a kernel-specific type. Enhances ring buffer section to improve content and improve consistency with the form used elsewhere in the Kernel Primer. Also corrects a minor error in the ring buffer API documentation. Change-Id: Icaa8661524f80e31f173adee859844cadb38967f Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Diffstat (limited to 'doc')
-rw-r--r--doc/kernel_v2/data_passing/data_passing.rst1
-rw-r--r--doc/kernel_v2/data_passing/ring_buffers.rst143
-rw-r--r--doc/kernel_v2/other/other.rst1
-rw-r--r--doc/kernel_v2/other/ring_buffers.rst184
4 files changed, 185 insertions, 144 deletions
diff --git a/doc/kernel_v2/data_passing/data_passing.rst b/doc/kernel_v2/data_passing/data_passing.rst
index 6ba38a72b..cae29b9ea 100644
--- a/doc/kernel_v2/data_passing/data_passing.rst
+++ b/doc/kernel_v2/data_passing/data_passing.rst
@@ -13,6 +13,5 @@ between different threads, or between an ISR and a thread.
lifos.rst
stacks.rst
message_queues.rst
- ring_buffers.rst
mailboxes.rst
pipes.rst
diff --git a/doc/kernel_v2/data_passing/ring_buffers.rst b/doc/kernel_v2/data_passing/ring_buffers.rst
deleted file mode 100644
index ca0b63a96..000000000
--- a/doc/kernel_v2/data_passing/ring_buffers.rst
+++ /dev/null
@@ -1,143 +0,0 @@
-.. _ring_buffers_v2:
-
-Ring Buffers [TBD]
-##################
-
-Definition
-**********
-
-The ring buffer is defined in :file:`include/misc/ring_buffer.h` and
-:file:`kernel/nanokernel/ring_buffer.c`. This is an array-based
-circular buffer, stored in first-in-first-out order. The APIs allow
-for enqueueing and retrieval of chunks of data up to 1024 bytes in size,
-along with two metadata values (type ID and an app-specific integer).
-
-Unlike nanokernel FIFOs, storage of enqueued items and their metadata
-is managed in a fixed buffer and there are no preconditions on the data
-enqueued (other than the size limit). Since the size annotation is only
-an 8-bit value, sizes are expressed in terms of 32-bit chunks.
-
-Internally, the ring buffer always maintains an empty 32-bit block in the
-buffer to distinguish between empty and full buffers. Any given entry
-in the buffer will use a 32-bit block for metadata plus any data attached.
-If the size of the buffer array is a power of two, the ring buffer will
-use more efficient masking instead of expensive modulo operations to
-maintain itself.
-
-Concurrency
-***********
-
-Concurrency control of ring buffers is not implemented at this level.
-Depending on usage (particularly with respect to number of concurrent
-readers/writers) applications may need to protect the ring buffer with
-mutexes and/or use semaphores to notify consumers that there is data to
-read.
-
-For the trivial case of one producer and one consumer, concurrency
-shouldn't be needed.
-
-Example: Initializing a Ring Buffer
-===================================
-
-There are three ways to initialize a ring buffer. The first two are through use
-of macros which defines one (and an associated private buffer) in file scope.
-You can declare a fast ring buffer that uses mask operations by declaring
-a power-of-two sized buffer:
-
-.. code-block:: c
-
- /* Buffer with 2^8 or 256 elements */
- SYS_RING_BUF_DECLARE_POW2(my_ring_buf, 8);
-
-Arbitrary-sized buffers may also be declared with a different macro, but
-these will always be slower due to use of modulo operations:
-
-.. code-block:: c
-
- #define MY_RING_BUF_SIZE 93
- SYS_RING_BUF_DECLARE_SIZE(my_ring_buf, MY_RING_BUF_SIZE);
-
-Alternatively, a ring buffer may be initialized manually. Whether the buffer
-will use modulo or mask operations will be detected automatically:
-
-.. code-block:: c
-
- #define MY_RING_BUF_SIZE 64
-
- struct my_struct {
- struct ring_buffer rb;
- uint32_t buffer[MY_RING_BUF_SIZE];
- ...
- };
- struct my_struct ms;
-
- void init_my_struct {
- sys_ring_buf_init(&ms.rb, sizeof(ms.buffer), ms.buffer);
- ...
- }
-
-Example: Enqueuing data
-=======================
-
-.. code-block:: c
-
- int ret;
-
- ret = sys_ring_buf_put(&ring_buf, TYPE_FOO, 0, &my_foo, SIZE32_OF(my_foo));
- if (ret == -EMSGSIZE) {
- ... not enough room for the message ..
- }
-
-If the type or value fields are sufficient, the data pointer and size may be 0.
-
-.. code-block:: c
-
- int ret;
-
- ret = sys_ring_buf_put(&ring_buf, TYPE_BAR, 17, NULL, 0);
- if (ret == -EMSGSIZE) {
- ... not enough room for the message ..
- }
-
-Example: Retrieving data
-========================
-
-.. code-block:: c
-
- int ret;
- uint32_t data[6];
-
- size = SIZE32_OF(data);
- ret = sys_ring_buf_get(&ring_buf, &type, &value, data, &size);
- if (ret == -EMSGSIZE) {
- printk("Buffer is too small, need %d uint32_t\n", size);
- } else if (ret == -EAGAIN) {
- printk("Ring buffer is empty\n");
- } else {
- printk("got item of type %u value &u of size %u dwords\n",
- type, value, size);
- ...
- }
-
-APIs
-****
-
-The following APIs for ring buffers are provided by :file:`ring_buffer.h`:
-
-:cpp:func:`sys_ring_buf_init()`
- Initializes a ring buffer.
-
-:c:func:`SYS_RING_BUF_DECLARE_POW2()`, :c:func:`SYS_RING_BUF_DECLARE_SIZE()`
- Declare and init a file-scope ring buffer.
-
-:cpp:func:`sys_ring_buf_space_get()`
- Returns the amount of free buffer storage space in 32-bit dwords.
-
-:cpp:func:`sys_ring_buf_is_empty()`
- Indicates whether a buffer is empty.
-
-:cpp:func:`sys_ring_buf_put()`
- Enqueues an item.
-
-:cpp:func:`sys_ring_buf_get()`
- De-queues an item.
diff --git a/doc/kernel_v2/other/other.rst b/doc/kernel_v2/other/other.rst
index 47f189430..c1479a031 100644
--- a/doc/kernel_v2/other/other.rst
+++ b/doc/kernel_v2/other/other.rst
@@ -10,6 +10,7 @@ This section describes other services provided by the kernel.
atomic.rst
float.rst
+ ring_buffers.rst
event_logger.rst
c_library.rst
cxx_support.rst
diff --git a/doc/kernel_v2/other/ring_buffers.rst b/doc/kernel_v2/other/ring_buffers.rst
new file mode 100644
index 000000000..2d4025f14
--- /dev/null
+++ b/doc/kernel_v2/other/ring_buffers.rst
@@ -0,0 +1,184 @@
+.. _ring_buffers_v2:
+
+Ring Buffers
+############
+
+A :dfn:`ring buffer` is a circular buffer of 32-bit words, whose contents
+are stored in first-in-first-out order. Data items can be enqueued and dequeued
+from a ring buffer in chunks of up to 1020 bytes. Each data item also has
+two associated metadata values: a type identifier and a 16-bit integer value,
+both of which are application-specific.
+
+.. contents::
+ :local:
+ :depth: 2
+
+Concepts
+********
+
+Any number of ring buffers can be defined. Each ring buffer is referenced
+by its memory address.
+
+A ring buffer has the following key properties:
+
+* A **data buffer** of 32-bit words. The data buffer contains the data items
+ that have been added to the ring buffer but not yet removed.
+
+* A **data buffer size**, measured in 32-bit words. This governs the maximum
+ amount of data (including metadata values) the ring buffer can hold.
+
+A ring buffer must be initialized before it can be used. This sets its
+data buffer to empty.
+
+A ring buffer **data item** is an array of 32-bit words from 0 to 1020 bytes
+in length. When a data item is **enqueued** its contents are copied
+to the data buffer, along with its associated metadata values (which occupy
+one additional 32-bit word).
+If the ring buffer has insufficient space to hold the new data item
+the enqueue operation fails.
+
+A data items is **dequeued** from a ring buffer by removing the oldest
+enqueued item. The contents of the dequeued data item, as well as its
+two metadata values, are copied to areas supplied by the retriever.
+If the ring buffer is empty, or if the data array supplied by the retriever
+is not large enough to hold the data item's data, the dequeue operation fails.
+
+Concurrency
+===========
+
+The ring buffer APIs do not provide any concurrency control.
+Depending on usage (particularly with respect to number of concurrent
+readers/writers) applications may need to protect the ring buffer with
+mutexes and/or use semaphores to notify consumers that there is data to
+read.
+
+For the trivial case of one producer and one consumer, concurrency
+shouldn't be needed.
+
+Internal Operation
+==================
+
+The ring buffer always maintains an empty 32-bit word in its data buffer
+to allow it to distinguish between empty and full states.
+
+If the size of the data buffer is a power of two, the ring buffer
+uses efficient masking operations instead of expensive modulo operations
+when enqueuing and dequeuing data items.
+
+Implementation
+**************
+
+Defining a Ring Buffer
+======================
+
+A ring buffer is defined using a variable of type :c:type:`struct ring_buf`.
+It must then be initialized by calling :cpp:func:`sys_ring_buf_init()`.
+
+The following code defines and initializes an empty ring buffer
+(which is part of a larger data structure). The ring buffer's data buffer
+is capable of holding 64 words of data and metadata information.
+
+.. code-block:: c
+
+ #define MY_RING_BUF_SIZE 64
+
+ struct my_struct {
+ struct ring_buffer rb;
+ uint32_t buffer[MY_RING_BUF_SIZE];
+ ...
+ };
+ struct my_struct ms;
+
+ void init_my_struct {
+ sys_ring_buf_init(&ms.rb, sizeof(ms.buffer), ms.buffer);
+ ...
+ }
+
+Alternatively, a ring buffer can be defined and initialized at compile time
+using one of two macros at file scope. Each macro defines both the ring
+buffer itself and its data buffer.
+
+The following code defines a ring buffer with a power-of-two sized data buffer,
+which can be accessed using efficient masking operations.
+
+.. code-block:: c
+
+ /* Buffer with 2^8 (or 256) words */
+ SYS_RING_BUF_DECLARE_POW2(my_ring_buf, 8);
+
+The following code defines a ring buffer with an arbitraty-sized data buffer,
+which can be accessed using less efficient modulo operations.
+
+.. code-block:: c
+
+ #define MY_RING_BUF_WORDS 93
+ SYS_RING_BUF_DECLARE_SIZE(my_ring_buf, MY_RING_BUF_WORDS);
+
+Enqueuing Data
+==============
+
+A data item is added to a ring buffer by calling :cpp:func:`sys_ring_buf_put()`.
+
+.. code-block:: c
+
+ uint32_t my_data[MY_DATA_WORDS];
+ int ret;
+
+ ret = sys_ring_buf_put(&ring_buf, TYPE_FOO, 0, my_data, SIZE32_OF(my_data));
+ if (ret == -EMSGSIZE) {
+ /* not enough room for the data item */
+ ...
+ }
+
+If the data item requires only the type or application-specific integer value
+(i.e. it has no data array), a size of 0 and data pointer of :c:macro:`NULL`
+can be specified.
+
+.. code-block:: c
+
+ int ret;
+
+ ret = sys_ring_buf_put(&ring_buf, TYPE_BAR, 17, NULL, 0);
+ if (ret == -EMSGSIZE) {
+ /* not enough room for the data item */
+ ...
+ }
+
+Retrieving Data
+===============
+
+A data item is removed from a ring buffer by calling
+:cpp:func:`sys_ring_buf_get()`.
+
+.. code-block:: c
+
+ uint32_t my_data[MY_DATA_WORDS];
+ uint16_t my_type;
+ uint8_t my_value;
+ uint8_t my_size;
+ int ret;
+
+ my_size = SIZE32_OF(my_data);
+ ret = sys_ring_buf_get(&ring_buf, &my_type, &my_value, my_data, &my_size);
+ if (ret == -EMSGSIZE) {
+ printk("Buffer is too small, need %d uint32_t\n", my_size);
+ } else if (ret == -EAGAIN) {
+ printk("Ring buffer is empty\n");
+ } else {
+ printk("Got item of type %u value &u of size %u dwords\n",
+ my_type, my_value, my_size);
+ ...
+ }
+
+APIs
+****
+
+The following ring buffer APIs are provided by :file:`misc/ring_buffer.h`:
+
+* :c:func:`SYS_RING_BUF_DECLARE_POW2()`
+* :c:func:`SYS_RING_BUF_DECLARE_SIZE()`
+* :cpp:func:`sys_ring_buf_init()`
+* :cpp:func:`sys_ring_buf_is_empty()`
+* :cpp:func:`sys_ring_buf_space_get()`
+* :cpp:func:`sys_ring_buf_put()`
+* :cpp:func:`sys_ring_buf_get()`