diff options
author | Anton Staaf <robotboy@chromium.org> | 2015-02-18 14:43:52 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-24 00:27:50 +0000 |
commit | 1a0235e69ff197cb1add08ffaa38ba1470db8cbc (patch) | |
tree | 3ec35670076ace67898e9f9cc75fca44ddfd064f /include | |
parent | fc144e940ca89a020880645a823d5c2258aae8c4 (diff) | |
download | chrome-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.h | 81 | ||||
-rw-r--r-- | include/producer.h | 75 | ||||
-rw-r--r-- | include/stream_adaptor.h | 80 |
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 */ |