mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-02 21:25:03 +00:00
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>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
fc144e940c
commit
1a0235e69f
@@ -7,7 +7,7 @@
|
||||
#
|
||||
|
||||
common-y=util.o
|
||||
common-y+=version.o printf.o queue.o
|
||||
common-y+=version.o printf.o queue.o producer.o consumer.o
|
||||
|
||||
common-$(CONFIG_ADC)+=adc.o
|
||||
common-$(CONFIG_ALS)+=als.o
|
||||
@@ -75,7 +75,7 @@ common-$(CONFIG_SHA256)+=sha256.o
|
||||
common-$(CONFIG_SMBUS)+= smbus.o
|
||||
common-$(CONFIG_SOFTWARE_CLZ)+=clz.o
|
||||
common-$(CONFIG_SPI_FLASH)+=spi_flash.o
|
||||
common-$(CONFIG_STREAM)+=in_stream.o out_stream.o
|
||||
common-$(CONFIG_STREAM)+=in_stream.o out_stream.o stream_adaptor.o
|
||||
common-$(CONFIG_SWITCH)+=switch.o
|
||||
common-$(CONFIG_SW_CRC)+=crc.o
|
||||
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o thermal.o throttle_ap.o
|
||||
|
||||
40
common/consumer.c
Normal file
40
common/consumer.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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 methods
|
||||
*/
|
||||
#include "consumer.h"
|
||||
#include "producer.h"
|
||||
|
||||
void consumer_notify_directly(struct consumer const *consumer, size_t count)
|
||||
{
|
||||
if (count && consumer->ops->written)
|
||||
consumer->ops->written(consumer, count);
|
||||
}
|
||||
|
||||
size_t consumer_read_unit(struct consumer const *consumer, void *unit)
|
||||
{
|
||||
size_t removed = queue_remove_unit(consumer->queue, unit);
|
||||
|
||||
producer_notify_directly(consumer->producer, removed);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
size_t consumer_read_memcpy(struct consumer const *consumer,
|
||||
void *units,
|
||||
size_t count,
|
||||
void *(*memcpy)(void *dest,
|
||||
void const *src,
|
||||
size_t n))
|
||||
{
|
||||
size_t removed = queue_remove_memcpy(consumer->queue,
|
||||
units,
|
||||
count,
|
||||
memcpy);
|
||||
|
||||
producer_notify_directly(consumer->producer, removed);
|
||||
|
||||
return removed;
|
||||
}
|
||||
40
common/producer.c
Normal file
40
common/producer.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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 methods
|
||||
*/
|
||||
#include "consumer.h"
|
||||
#include "producer.h"
|
||||
|
||||
void producer_notify_directly(struct producer const *producer, size_t count)
|
||||
{
|
||||
if (count && producer->ops->read)
|
||||
producer->ops->read(producer, count);
|
||||
}
|
||||
|
||||
size_t producer_write_unit(struct producer const *producer, void const *unit)
|
||||
{
|
||||
size_t added = queue_add_unit(producer->queue, unit);
|
||||
|
||||
consumer_notify_directly(producer->consumer, added);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
size_t added = queue_add_memcpy(producer->queue,
|
||||
units,
|
||||
count,
|
||||
memcpy);
|
||||
|
||||
consumer_notify_directly(producer->consumer, added);
|
||||
|
||||
return added;
|
||||
}
|
||||
65
common/stream_adaptor.c
Normal file
65
common/stream_adaptor.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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.
|
||||
*
|
||||
* Stream adaptor implementation.
|
||||
*/
|
||||
|
||||
#include "producer.h"
|
||||
#include "consumer.h"
|
||||
#include "stream_adaptor.h"
|
||||
#include "util.h"
|
||||
|
||||
static size_t in_stream_from_producer_read(struct in_stream const *stream,
|
||||
uint8_t *buffer,
|
||||
size_t count)
|
||||
{
|
||||
struct in_stream_from_producer const *adaptor =
|
||||
DOWNCAST(stream, struct in_stream_from_producer, in);
|
||||
|
||||
return consumer_read_memcpy(&adaptor->consumer, buffer, count, memcpy);
|
||||
}
|
||||
|
||||
static void in_stream_from_producer_written(struct consumer const *consumer,
|
||||
size_t count)
|
||||
{
|
||||
struct in_stream_from_producer const *adaptor =
|
||||
DOWNCAST(consumer, struct in_stream_from_producer, consumer);
|
||||
|
||||
in_stream_ready(&adaptor->in);
|
||||
}
|
||||
|
||||
struct in_stream_ops const in_stream_from_producer_in_stream_ops = {
|
||||
.read = in_stream_from_producer_read,
|
||||
};
|
||||
|
||||
struct consumer_ops const in_stream_from_producer_consumer_ops = {
|
||||
.written = in_stream_from_producer_written,
|
||||
};
|
||||
|
||||
static size_t out_stream_from_consumer_write(struct out_stream const *stream,
|
||||
uint8_t const *buffer,
|
||||
size_t count)
|
||||
{
|
||||
struct out_stream_from_consumer const *adaptor =
|
||||
DOWNCAST(stream, struct out_stream_from_consumer, out);
|
||||
|
||||
return producer_write_memcpy(&adaptor->producer, buffer, count, memcpy);
|
||||
}
|
||||
|
||||
static void out_stream_from_consumer_read(struct producer const *producer,
|
||||
size_t count)
|
||||
{
|
||||
struct out_stream_from_consumer const *adaptor =
|
||||
DOWNCAST(producer, struct out_stream_from_consumer, producer);
|
||||
|
||||
out_stream_ready(&adaptor->out);
|
||||
}
|
||||
|
||||
struct out_stream_ops const out_stream_from_consumer_out_stream_ops = {
|
||||
.write = out_stream_from_consumer_write,
|
||||
};
|
||||
|
||||
struct producer_ops const out_stream_from_consumer_producer_ops = {
|
||||
.read = out_stream_from_consumer_read,
|
||||
};
|
||||
81
include/consumer.h
Normal file
81
include/consumer.h
Normal file
@@ -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 */
|
||||
75
include/producer.h
Normal file
75
include/producer.h
Normal file
@@ -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 */
|
||||
80
include/stream_adaptor.h
Normal file
80
include/stream_adaptor.h
Normal file
@@ -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 */
|
||||
Reference in New Issue
Block a user