summaryrefslogtreecommitdiff
path: root/kern/mbuf.h
blob: 1c36afb50454e9e627e1e08c9f54418090b81917 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 * Copyright (c) 2018-2019 Richard Braun.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Upstream site with license notes :
 * http://git.sceen.net/rbraun/librbraun.git/
 *
 *
 * FIFO message buffer.
 */

#ifndef KERN_MBUF_H
#define KERN_MBUF_H

#include <stdbool.h>
#include <stddef.h>

#include <kern/cbuf.h>

/*
 * Message buffer.
 *
 * Message buffers are built on top of circular byte buffers. They provide
 * discrete message transfer from a producer to a consumer.
 *
 * The order is computed from the maximum message size, and is used to
 * determine a header size that can represent up to 2^order - 1 bytes.
 */
struct mbuf {
    struct cbuf cbuf;
    size_t max_msg_size;
    unsigned int order;
};

static inline size_t
mbuf_start(const struct mbuf *mbuf)
{
    return cbuf_start(&mbuf->cbuf);
}

static inline size_t
mbuf_end(const struct mbuf *mbuf)
{
    return cbuf_end(&mbuf->cbuf);
}

/*
 * Initialize a message buffer.
 *
 * The descriptor is set to use the given buffer for storage. Capacity
 * must be a power-of-two.
 */
void mbuf_init(struct mbuf *mbuf, void *buf, size_t capacity,
               size_t max_msg_size);

/*
 * Clear a message buffer.
 */
void mbuf_clear(struct mbuf *mbuf);

/*
 * Push a message to a message buffer.
 *
 * If the message doesn't fit in the message buffer, either because it is
 * larger than the capacity, or because the function isn't allowed to erase
 * old messages and the message buffer doesn't have enough available memory
 * for the new message, EMSGSIZE is returned. If the message is larger than
 * the maximum message size, EINVAL is returned.
 */
int mbuf_push(struct mbuf *mbuf, const void *buf, size_t size, bool erase);

/*
 * Pop a message from a message buffer.
 *
 * On entry, the sizep argument points to the size of the output buffer.
 * On return, it is updated to the size of the message. If the message
 * doesn't fit in the output buffer, it is not popped, EMSGSIZE is
 * returned, but the sizep argument is updated nonetheless to let the
 * user know the message size, to potentially retry with a larger buffer.
 *
 * If the buffer is empty, EAGAIN is returned, and the size of the output
 * buffer is unmodified.
 *
 * The output buffer may be NULL, in which case this function acts as if
 * it wasn't, but without writing output data.
 */
int mbuf_pop(struct mbuf *mbuf, void *buf, size_t *sizep);

/*
 * Read a message from a message buffer.
 *
 * On entry, the indexp argument points to the index of the message to
 * read in the message buffer, and the sizep argument points to the size
 * of the output buffer. On return, if successful, indexp is updated
 * to the index of the next message, and sizep to the size of the
 * message read.
 *
 * If the message doesn't fit in the output buffer, it is not read,
 * EMSGSIZE is returned, and the sizep argument is updated nonetheless
 * to let the user know the message size, to potentially retry with a
 * larger buffer.
 *
 * If the given index refers to the end of the buffer, then EAGAIN is
 * returned. If it's outside buffer boundaries, EINVAL is returned.
 * Otherwise, if it doesn't point to the beginning of a message, the
 * behavior is undefined.
 *
 * The message buffer isn't changed by this operation.
 */
int mbuf_read(const struct mbuf *mbuf, size_t *indexp,
              void *buf, size_t *sizep);

#endif /* KERN_MBUF_H */