1/*
2 * Copyright 2016, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(D61_BSD)
11 */
12
13/*! @file
14    @brief Ring buffer implementation, operating on the internal RAM dataspace objects.
15
16    A simple <b>MCRingBuffer</b> implementation which operates on the internal RAM dataspaces. This
17    is designed for communication with the clients who share to us our own dataspace. Since reading
18    from a page entry is computationally expensive as it requires mapping the frame, copying the
19    data out and then unmapping the frame, the MCRingBuffer algorithm is used here to minimise the
20    frequency of read / writes to the shared control variables.
21
22    Reference:
23
24    > P.P.C. Lee, T. Bu,  and G.P. Chandranmenon,  A lock-free, cache-efficient shared ring buffer
25    > for multi-core architectures.  ;In Proceedings of ANCS. 2009, 78-79. <br>
26    > http://www.cse.cuhk.edu.hk/~pclee/www/pubs/ancs09poster.pdf
27*/
28
29#ifndef _REFOS_PROCESS_SERVER_SYSTEM_MEMSERV_RING_BUFFER_H_
30#define _REFOS_PROCESS_SERVER_SYSTEM_MEMSERV_RING_BUFFER_H_
31
32#include "../../common.h"
33#include "dataspace.h"
34
35#define RINGBUFFER_MAGIC 0x660149F7
36#define RINGBUFFER_METADATA_SIZE (sizeof(uint32_t) * 2)
37
38/*! @brief Ring buffer modes - read only or write only. */
39enum rb_mode {
40    RB_READONLY,
41    RB_WRITEONLY
42};
43
44/*! @brief Ring buffer structure.
45
46    A structure containing information regarding to a single ring buffer. Does NOT take ownership of
47    the associated dataspace; merely provides a wrapping to use ringbuffers on top of a struct
48    ram_dataspace. Ringbuffers are uni-directional; either read-only or write-only, as described in
49    rb_modes_t.
50
51    The structure also shares ownership of the underlying dataspace object, using a shared
52    reference. This ensures that the ram_dspace structure pointed here is always valid, but also
53    means this rb_buffer must be deleted for the linked ram_dspace to be truly deleted, as this
54    object "hangs onto" its dataspace.
55 */
56struct rb_buffer {
57    enum rb_mode mode;
58    uint32_t magic;
59
60    uint32_t localStart;
61    uint32_t localEnd;
62    uint32_t size;
63
64    struct ram_dspace *dataspace; /* Shared ownership. */
65};
66
67/*! @brief Creates a ring buffer structure operating on the given dataspace.
68
69    Creates a ring buffer structure operating on the given dataspace. This assumes a shared
70    ownership of the given dataspace, and keeps a strong reference to it.
71
72    @param dataspace The dataspace to wrap a ring buffer interface on. (Shared ownership)
73    @param mode Either RB_READONLY or RB_WRITEONLY.
74    @return An empty ring buffer on success (Passes ownership), NULL otherwise.
75 */
76struct rb_buffer *rb_create(struct ram_dspace *dataspace, enum rb_mode mode);
77
78/*! @brief Deletes given ring buffer structure.
79    @param rb The ring buffer to delete. (Takes ownership)
80 */
81void rb_delete(struct rb_buffer *rb);
82
83/*! @brief Writes data to ring buffer. (See code comments for more info).
84    @param buf Destination ring buffer to write to. (No ownership)
85    @param str Source buffer to read from in bytes. (No ownership)
86    @param len Size of source buffer containing data.
87    @return ESUCCESS if success, ENOMEM if ring buffer is full, refos_error otherwise.
88 */
89int rb_write(struct rb_buffer *buf, char *str, size_t len);
90
91/*! @brief Reads data from ring buffer. (See code comments for more info).
92    @param buf Source ring buffer to read from. (No ownership)
93    @param dest Destination buffer to read to. (No ownership)
94    @param len Maximum length of data to read in bytes.
95    @param bytesRead How many bytes were read into the destination buffer. (No ownership)
96    @return ESUCCESS if success, refos_error otherwise.
97 */
98int rb_read(struct rb_buffer *buf, char *dest, size_t len, size_t *bytesRead);
99
100#endif /* _REFOS_PROCESS_SERVER_SYSTEM_MEMSERV_RING_BUFFER_H_ */