summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2015-02-18 14:43:52 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-24 00:27:50 +0000
commit1a0235e69ff197cb1add08ffaa38ba1470db8cbc (patch)
tree3ec35670076ace67898e9f9cc75fca44ddfd064f /include
parentfc144e940ca89a020880645a823d5c2258aae8c4 (diff)
downloadchrome-ec-1a0235e69ff197cb1add08ffaa38ba1470db8cbc.tar.gz
Streams: Define a lower level abstraction for queue access
This adds a new pair of interfaces called producer and consumer which are simpler (in that they don't hold onto the underlying queue) than the stream interfaces. This makes it easier to share a single queue between the endpoints that will manipulate it. It was not possible to share a queue between two objects that implemented the in_stream and out_stream interfaces. This also adds a pair of adaptors that can convert a producer or consumer into a stream of the correct type. These adaptors will be used for existing code once the usb-stream and usart drivers are converted over to use the producer/consumer interfaces instead of the stream interfaces. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Change-Id: I42b4b1ac15cca28e1adc6d3cea315f15e17a0b4d Reviewed-on: https://chromium-review.googlesource.com/250941 Trybot-Ready: Anton Staaf <robotboy@chromium.org> Tested-by: Anton Staaf <robotboy@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org>
Diffstat (limited to 'include')
-rw-r--r--include/consumer.h81
-rw-r--r--include/producer.h75
-rw-r--r--include/stream_adaptor.h80
3 files changed, 236 insertions, 0 deletions
diff --git a/include/consumer.h b/include/consumer.h
new file mode 100644
index 0000000000..4a456de512
--- /dev/null
+++ b/include/consumer.h
@@ -0,0 +1,81 @@
+/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Consumer interface
+ *
+ * The consumer abstraction allows for code that wants to be able to read from
+ * a queue, and be notified of new additions to the queue, or of requests to
+ * flush (empty) the queue.
+ */
+#ifndef INCLUDE_CONSUMER_H
+#define INCLUDE_CONSUMER_H
+
+#include "queue.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+struct consumer;
+struct producer;
+
+struct consumer_ops {
+ /*
+ * Inform the consumer that count units were written to the queue.
+ * This gives it the oportunity to read additional units from the queue
+ * or to wake up a task or interrupt to do the same. If a consumer has
+ * no need for this information it can set this to NULL.
+ */
+ void (*written)(struct consumer const *consumer, size_t count);
+
+ /*
+ * Flush (read) everything from the associated queue. This call blocks
+ * until the consumer has flushed the queue.
+ */
+ void (*flush)(struct consumer const *consumer);
+};
+
+struct consumer {
+ /*
+ * A consumer references the producer at the other end of the queue.
+ * This allows the consumer to notify the producer when units are
+ * removed from the queue.
+ */
+ struct producer const *producer;
+
+ /*
+ * A consumer also references the queue that it is reading from. This
+ * and the producer reference above could be more flexibly replaced by
+ * a queue manager object that could handle multiple producer/consumers
+ * or alternate notification mechanisms. But that complexity is not
+ * yet warranted.
+ */
+ struct queue const *queue;
+
+ struct consumer_ops const *ops;
+};
+
+/*
+ * Notify the consumer by calling its written method directly, as opposed to
+ * from a deferred callback or another task.
+ */
+void consumer_notify_directly(struct consumer const *consumer, size_t count);
+
+/*
+ * Read a single unit from the queue and notify the associated producer.
+ * Return the number of units read.
+ */
+size_t consumer_read_unit(struct consumer const *consumer, void *unit);
+
+/*
+ * Read multiple units from the queue, using the provided memcpy like routine
+ * and notify the producer. Return the number of units read.
+ */
+size_t consumer_read_memcpy(struct consumer const *consumer,
+ void *units,
+ size_t count,
+ void *(*memcpy)(void *dest,
+ void const *src,
+ size_t n));
+
+#endif /* INCLUDE_CONSUMER_H */
diff --git a/include/producer.h b/include/producer.h
new file mode 100644
index 0000000000..d42e148ea6
--- /dev/null
+++ b/include/producer.h
@@ -0,0 +1,75 @@
+/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Producer interface
+ *
+ * The producer abstraction allows for code that wants to write into a queue and
+ * be notified when the queue is read from so that it can take action, such as
+ * adding new units to the queue.
+ */
+#ifndef INCLUDE_PRODUCER_H
+#define INCLUDE_PRODUCER_H
+
+#include "queue.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+struct consumer;
+struct producer;
+
+struct producer_ops {
+ /*
+ * Inform the producer that count units were read from the queue. This
+ * gives it the oportunity to write additional units to the queue or to
+ * wake up a task or interrupt to do the same. If a producer has no
+ * need for this information it can set this to NULL.
+ */
+ void (*read)(struct producer const *producer, size_t count);
+};
+
+struct producer {
+ /*
+ * A producer references the consumer at the other end of the queue.
+ * This allows the producer to notify the consumer when new units are
+ * added to the queue.
+ */
+ struct consumer const *consumer;
+
+ /*
+ * A producer also references the queue that it is writing into. This
+ * and the consumer reference above could be more flexibly replaced by
+ * a queue manager object that could handle multiple producer/consumers
+ * or alternate notification mechanisms. But that complexity is not
+ * yet warranted.
+ */
+ struct queue const *queue;
+
+ struct producer_ops const *ops;
+};
+
+/*
+ * Notify the producer by calling its read method directly, as opposed to from
+ * a deferred callback or another task.
+ */
+void producer_notify_directly(struct producer const *producer, size_t count);
+
+/*
+ * Write a single unit to the queue and notify the associated consumer. Return
+ * the number of units written.
+ */
+size_t producer_write_unit(struct producer const *producer, void const *unit);
+
+/*
+ * Write multiple units to the queue, using the provided memcpy like routine
+ * and notify the consumer. Return the number of units written.
+ */
+size_t producer_write_memcpy(struct producer const *producer,
+ void const *units,
+ size_t count,
+ void *(*memcpy)(void *dest,
+ void const *src,
+ size_t n));
+
+#endif /* INCLUDE_PRODUCER_H */
diff --git a/include/stream_adaptor.h b/include/stream_adaptor.h
new file mode 100644
index 0000000000..916ab6e78d
--- /dev/null
+++ b/include/stream_adaptor.h
@@ -0,0 +1,80 @@
+/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef INCLUDE_STREAM_ADAPTOR_H
+#define INCLUDE_STREAM_ADAPTOR_H
+
+/* STM32 USART driver for Chrome EC */
+
+#include "common.h"
+#include "in_stream.h"
+#include "out_stream.h"
+#include "consumer.h"
+#include "producer.h"
+
+/*
+ * +..........+ +..........+------+...........+
+ * . .<------------->. | | .
+ * . Producer . +---------+ . Consumer | ISFP | In Stream .
+ * . .->| Queue |->. | | .
+ * +..........+ +---------+ +..........+------+...........+
+ */
+
+struct in_stream_from_producer {
+ struct consumer consumer;
+ struct in_stream in;
+};
+
+/*
+ *
+ */
+extern struct in_stream_ops const in_stream_from_producer_in_stream_ops;
+extern struct consumer_ops const in_stream_from_producer_consumer_ops;
+
+#define IN_STREAM_FROM_PRODUCER(NAME, PRODUCER, QUEUE, READY) \
+ struct in_stream_from_producer const NAME = { \
+ .consumer = { \
+ .producer = &PRODUCER, \
+ .queue = &QUEUE, \
+ .ops = &in_stream_from_producer_consumer_ops, \
+ }, \
+ .in = { \
+ .ready = READY, \
+ .ops = &in_stream_from_producer_in_stream_ops, \
+ }, \
+ };
+
+/*
+ * +..........+ +..........+------+............+
+ * . .<------------->. | | .
+ * . Consumer . +---------+ . Producer | OSFC | Out Stream .
+ * . .<-| Queue |<-. | | .
+ * +..........+ +---------+ +..........+------+............+
+ */
+
+struct out_stream_from_consumer {
+ struct producer producer;
+ struct out_stream out;
+};
+
+/*
+ *
+ */
+extern struct out_stream_ops const out_stream_from_consumer_out_stream_ops;
+extern struct producer_ops const out_stream_from_consumer_producer_ops;
+
+#define OUT_STREAM_FROM_CONSUMER(NAME, CONSUMER, QUEUE, READY) \
+ struct out_stream_from_consumer const NAME = { \
+ .producer = { \
+ .consumer = &CONSUMER, \
+ .queue = &QUEUE, \
+ .ops = &out_stream_from_consumer_producer_ops, \
+ }, \
+ .out = { \
+ .ready = READY, \
+ .ops = &out_stream_from_consumer_out_stream_ops, \
+ }, \
+ };
+
+#endif /* INCLUDE_STREAM_ADAPTOR_H */