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