]> git.proxmox.com Git - mirror_ovs.git/blame - lib/byteq.c
vlog: Make VLOG_ONCE thread-safe.
[mirror_ovs.git] / lib / byteq.c
CommitLineData
cb22974d 1/* Copyright (c) 2008, 2009, 2012 Nicira, Inc.
064af421 2 *
a14bc59f
BP
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
064af421 6 *
a14bc59f 7 * http://www.apache.org/licenses/LICENSE-2.0
064af421 8 *
a14bc59f
BP
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
064af421
BP
14 */
15
16#include <config.h>
1c617a49 17#include "byteq.h"
064af421
BP
18#include <errno.h>
19#include <string.h>
20#include <unistd.h>
21#include "util.h"
22
23/* The queue size must be a power of 2. */
24BUILD_ASSERT_DECL(!(BYTEQ_SIZE & (BYTEQ_SIZE - 1)));
25
064af421
BP
26/* Initializes 'q' as empty. */
27void
28byteq_init(struct byteq *q)
29{
30 q->head = q->tail = 0;
31}
32
33/* Returns the number of bytes current queued in 'q'. */
34int
35byteq_used(const struct byteq *q)
36{
37 return q->head - q->tail;
38}
39
40/* Returns the number of bytes that can be added to 'q' without overflow. */
41int
42byteq_avail(const struct byteq *q)
43{
44 return BYTEQ_SIZE - byteq_used(q);
45}
46
47/* Returns true if no bytes are queued in 'q',
48 * false if at least one byte is queued. */
49bool
50byteq_is_empty(const struct byteq *q)
51{
52 return !byteq_used(q);
53}
54
55/* Returns true if 'q' has no room to queue additional bytes,
56 * false if 'q' has room for at least one more byte. */
57bool
58byteq_is_full(const struct byteq *q)
59{
60 return !byteq_avail(q);
61}
62
63/* Adds 'c' at the head of 'q', which must not be full. */
64void
65byteq_put(struct byteq *q, uint8_t c)
66{
cb22974d 67 ovs_assert(!byteq_is_full(q));
1c617a49 68 *byteq_head(q) = c;
064af421
BP
69 q->head++;
70}
71
72/* Adds the 'n' bytes in 'p' at the head of 'q', which must have at least 'n'
73 * bytes of free space. */
74void
75byteq_putn(struct byteq *q, const void *p_, size_t n)
76{
77 const uint8_t *p = p_;
cb22974d 78 ovs_assert(byteq_avail(q) >= n);
064af421 79 while (n > 0) {
1c617a49
BP
80 size_t chunk = MIN(n, byteq_headroom(q));
81 memcpy(byteq_head(q), p, chunk);
82 byteq_advance_head(q, chunk);
064af421
BP
83 p += chunk;
84 n -= chunk;
85 }
86}
87
88/* Appends null-terminated string 's' to the head of 'q', which must have
89 * enough space. The null terminator is not added to 'q'. */
90void
91byteq_put_string(struct byteq *q, const char *s)
92{
93 byteq_putn(q, s, strlen(s));
94}
95
96/* Removes a byte from the tail of 'q' and returns it. 'q' must not be
97 * empty. */
98uint8_t
99byteq_get(struct byteq *q)
100{
101 uint8_t c;
cb22974d 102 ovs_assert(!byteq_is_empty(q));
1c617a49 103 c = *byteq_tail(q);
064af421
BP
104 q->tail++;
105 return c;
106}
107
108/* Writes as much of 'q' as possible to 'fd'. Returns 0 if 'q' is fully
109 * drained by the write, otherwise a positive errno value (e.g. EAGAIN if a
110 * socket or tty buffer filled up). */
111int
112byteq_write(struct byteq *q, int fd)
113{
114 while (!byteq_is_empty(q)) {
1c617a49 115 ssize_t n = write(fd, byteq_tail(q), byteq_tailroom(q));
064af421 116 if (n > 0) {
1c617a49 117 byteq_advance_tail(q, n);
064af421 118 } else {
cb22974d 119 ovs_assert(n < 0);
064af421
BP
120 return errno;
121 }
122 }
123 return 0;
124}
125
126/* Reads as much possible from 'fd' into 'q'. Returns 0 if 'q' is completely
127 * filled up by the read, EOF if end-of-file was reached before 'q' was filled,
128 * and otherwise a positive errno value (e.g. EAGAIN if a socket or tty buffer
129 * was drained). */
130int
131byteq_read(struct byteq *q, int fd)
132{
133 while (!byteq_is_full(q)) {
1c617a49 134 ssize_t n = read(fd, byteq_head(q), byteq_headroom(q));
064af421 135 if (n > 0) {
1c617a49 136 byteq_advance_head(q, n);
064af421
BP
137 } else {
138 return !n ? EOF : errno;
139 }
140 }
141 return 0;
142}
1c617a49 143
064af421
BP
144/* Returns the number of contiguous bytes of in-use space starting at the tail
145 * of 'q'. */
1c617a49
BP
146int
147byteq_tailroom(const struct byteq *q)
064af421
BP
148{
149 int used = byteq_used(q);
150 int tail_to_end = BYTEQ_SIZE - (q->tail & (BYTEQ_SIZE - 1));
151 return MIN(used, tail_to_end);
152}
153
154/* Returns the first in-use byte of 'q', the point at which data is removed
155 * from 'q'. */
1c617a49
BP
156const uint8_t *
157byteq_tail(const struct byteq *q)
064af421
BP
158{
159 return &q->buffer[q->tail & (BYTEQ_SIZE - 1)];
160}
161
162/* Removes 'n' bytes from the tail of 'q', which must have at least 'n' bytes
163 * of tailroom. */
1c617a49
BP
164void
165byteq_advance_tail(struct byteq *q, unsigned int n)
064af421 166{
cb22974d 167 ovs_assert(byteq_tailroom(q) >= n);
064af421
BP
168 q->tail += n;
169}
170
171/* Returns the byte after the last in-use byte of 'q', the point at which new
172 * data will be added to 'q'. */
1c617a49
BP
173uint8_t *
174byteq_head(struct byteq *q)
064af421
BP
175{
176 return &q->buffer[q->head & (BYTEQ_SIZE - 1)];
177}
178
179/* Returns the number of contiguous bytes of free space starting at the head
180 * of 'q'. */
1c617a49
BP
181int
182byteq_headroom(const struct byteq *q)
064af421
BP
183{
184 int avail = byteq_avail(q);
185 int head_to_end = BYTEQ_SIZE - (q->head & (BYTEQ_SIZE - 1));
186 return MIN(avail, head_to_end);
187}
188
189/* Adds to 'q' the 'n' bytes after the last currently in-use byte of 'q'. 'q'
190 * must have at least 'n' bytes of headroom. */
1c617a49
BP
191void
192byteq_advance_head(struct byteq *q, unsigned int n)
064af421 193{
cb22974d 194 ovs_assert(byteq_headroom(q) >= n);
064af421
BP
195 q->head += n;
196}