1 /*
2  * Copyright (c) 2009-2013 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #pragma once
9 
10 #include <lk/compiler.h>
11 #include <sys/types.h>
12 #include <kernel/event.h>
13 #include <kernel/spinlock.h>
14 #include <iovec.h>
15 
16 __BEGIN_CDECLS
17 
18 typedef struct cbuf {
19     uint head;
20     uint tail;
21     uint len_pow2;
22     char *buf;
23     event_t event;
24     spin_lock_t lock;
25 } cbuf_t;
26 
27 /**
28  * cbuf_initialize
29  *
30  * Initialize a cbuf structure, mallocing the underlying data buffer in the
31  * process.  Make sure that the buffer has enough space for at least len bytes.
32  *
33  * @param[in] cbuf A pointer to the cbuf structure to allocate.
34  * @param[in] len The minimum number of bytes for the underlying data buffer.
35  * Must be a power of two.
36  */
37 void cbuf_initialize(cbuf_t *cbuf, size_t len);
38 
39 /**
40  * cbuf_initalize_etc
41  *
42  * Initialize a cbuf structure using the supplied buffer for internal storage.
43  *
44  * @param[in] cbuf A pointer to the cbuf structure to allocate.
45  * @param[in] len The size of the supplied buffer, in bytes.  Must be a power
46  * of two.
47  * @param[in] buf A pointer to the memory to be used for internal storage.
48  */
49 void cbuf_initialize_etc(cbuf_t *cbuf, size_t len, void *buf);
50 
51 /**
52  * cbuf_read
53  *
54  * Read up to buflen bytes in to the supplied buffer.
55  *
56  * @param[in] cbuf The cbuf instance to read from.
57  * @param[in] buf A pointer to a buffer to read data into.  If NULL, cbuf_read
58  * will skip up to the next buflen bytes from the cbuf.
59  * @param[in] buflen The maximum number of bytes to read from the cbuf.
60  * @param[in] block When true, will cause the caller to block until there is at
61  * least one byte available to read from the cbuf.
62  *
63  * @return The actual number of bytes which were read (or skipped).
64  */
65 size_t cbuf_read(cbuf_t *cbuf, void *buf, size_t buflen, bool block);
66 
67 /**
68  * cbuf_peek
69  *
70  * Peek at the data available for read in the cbuf right now.  Does not actually
71  * consume the data, it just fills out a pair of iovec structures describing the
72  * (up to) two contiguous regions currently available for read.
73  *
74  * @param[in] cbuf The cbuf instance to write to.
75  * @param[out] A pointer to two iovec structures to hold the contiguous regions
76  * for read.  NOTE: regions must point to a chunk of memory which is at least
77  * sizeof(iovec_t) * 2 bytes long.
78  *
79  * @return The number of bytes which were written (or skipped).
80  */
81 size_t cbuf_peek(cbuf_t *cbuf, iovec_t *regions);
82 
83 /**
84  * cbuf_write
85  *
86  * Write up to len bytes from the the supplied buffer into the cbuf.
87  *
88  * @param[in] cbuf The cbuf instance to write to.
89  * @param[in] buf A pointer to a buffer to read data from.  If NULL, cbuf_write
90  * will skip up to the next len bytes in the cbuf, filling with zeros instead of
91  * supplied data.
92  * @param[in] len The maximum number of bytes to write to the cbuf.
93  * @param[in] canreschedule Rescheduling policy passed through to the internal
94  * event when signaling the event to indicate that there is now data in the
95  * buffer to be read.
96  *
97  * @return The number of bytes which were written (or skipped).
98  */
99 size_t cbuf_write(cbuf_t *cbuf, const void *buf, size_t len, bool canreschedule);
100 
101 /**
102  * cbuf_space_avail
103  *
104  * @param[in] cbuf The cbuf instance to query
105  *
106  * @return The number of free space available in the cbuf (IOW - the maximum
107  * number of bytes which can currently be written)
108  */
109 size_t cbuf_space_avail(cbuf_t *cbuf);
110 
111 /**
112  * cbuf_space_used
113  *
114  * @param[in] cbuf The cbuf instance to query
115  *
116  * @return The number of used bytes in the cbuf (IOW - the maximum number of
117  * bytes which can currently be read).
118  */
119 size_t cbuf_space_used(cbuf_t *cbuf);
120 
121 /**
122  * cbuf_size
123  *
124  * @param[in] cbuf The cbuf instance to query
125  *
126  * @return The size of the cbuf's underlying data buffer.
127  */
cbuf_size(cbuf_t * cbuf)128 static inline size_t cbuf_size(cbuf_t *cbuf) {
129     return (1UL << cbuf->len_pow2);
130 }
131 
132 /**
133  * cbuf_reset
134  *
135  * Reset the cbuf instance, discarding any data which may be in the buffer at
136  * the moment.
137  *
138  * @param[in] cbuf The cbuf instance to reset.
139  */
cbuf_reset(cbuf_t * cbuf)140 static inline void cbuf_reset(cbuf_t *cbuf) {
141     cbuf_read(cbuf, NULL, cbuf_size(cbuf), false);
142 }
143 
144 /* special cases for dealing with a single char of data */
145 size_t cbuf_read_char(cbuf_t *cbuf, char *c, bool block);
146 size_t cbuf_write_char(cbuf_t *cbuf, char c, bool canreschedule);
147 
148 __END_CDECLS
149 
150