Adding some initializations
[barrelfish] / lib / barrelfish / msgbuf.c
1 /**
2  * \file
3  * \brief Generic bag-o-bytes message format
4  */
5
6 /*
7  * Copyright (c) 2009, 2010, ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/msgbuf.h>
19
20 void msgbuf_init_static(struct msgbuf *msgbuf, void *buf, size_t buflen,
21                         struct capref *capbuf, size_t capbuflen)
22 {
23     assert(msgbuf != NULL);
24     msgbuf->pos = 0;
25     msgbuf->len = buflen;
26     msgbuf->buf = buf;
27     msgbuf->cap_pos = 0;
28     msgbuf->ncaps = capbuflen;
29     msgbuf->caps = capbuf;
30     msgbuf->dynamic = false;
31 }
32
33 void msgbuf_init_dynamic(struct msgbuf *msgbuf, size_t hintlen, size_t hintcaps)
34 {
35     void *buf;
36     if (hintlen > 0) {
37         buf = malloc(hintlen);
38         if (buf == NULL) { // XXX: malloc failed, but it will be reported later
39             hintlen = 0;
40         }
41     } else {
42         buf = NULL;
43     }
44
45     struct capref *capbuf;
46     if (hintcaps > 0) {
47         capbuf = malloc(sizeof(struct capref) * hintcaps);
48         if (capbuf == NULL) {
49             hintcaps = 0;
50         }
51     } else {
52         capbuf = NULL;
53     }
54
55     msgbuf_init_static(msgbuf, buf, hintlen, capbuf, hintcaps);
56     msgbuf->dynamic = true;
57 }
58
59 void msgbuf_destroy(struct msgbuf *msgbuf)
60 {
61     if (msgbuf->dynamic) {
62         if (msgbuf->buf != NULL) {
63             free(msgbuf->buf);
64             msgbuf->buf = NULL;
65         }
66         if (msgbuf->caps != NULL) {
67             free(msgbuf->caps);
68             msgbuf->caps = NULL;
69         }
70         msgbuf->dynamic = false;
71     }
72 }
73
74 static void *msgbuf_ensure(struct msgbuf *msgbuf, size_t extralen)
75 {
76     void *ret = &msgbuf->buf[msgbuf->pos];
77     size_t newpos = msgbuf->pos + extralen;
78     if (newpos <= msgbuf->len) {
79         msgbuf->pos = newpos;
80         return ret;
81     } else {
82         return NULL;
83     }
84 }
85
86 static void *msgbuf_grow(struct msgbuf *msgbuf, size_t extralen)
87 {
88     void *ret = &msgbuf->buf[msgbuf->pos];
89     size_t newpos = msgbuf->pos + extralen ;
90     if (newpos <= msgbuf->len) {
91         msgbuf->pos = newpos;
92         return ret;
93     } else if (msgbuf->dynamic) {
94         // try to grow buffer using realloc
95         void *newbuf = realloc(msgbuf->buf, msgbuf->pos + extralen);
96         if (newbuf == NULL) {
97             return NULL;
98         } else {
99             msgbuf->buf = newbuf;
100             msgbuf->pos = newpos;
101             return ret;
102         }
103     } else {
104         return NULL; // can't grow a static buffer
105     }
106 }
107
108 errval_t msgbuf_marshall_buffer(struct msgbuf *msgbuf, const void *src_buf,
109                                 size_t len)
110 {
111     // copy the argument into the memory region
112     // the size of the buffer
113     errval_t err = msgbuf_marshall_size(msgbuf, len);
114     if (err_is_fail(err)) {
115         return err;
116     }
117
118     // the buffer itself
119     void *dest = msgbuf_grow(msgbuf, len);
120     if (dest == NULL) {
121         // XXX: reach around grow/marshall API and remove size from buffer
122         msgbuf->pos -= sizeof(size_t);
123         return LIB_ERR_MSGBUF_CANNOT_GROW;
124     }
125
126     memcpy(dest, src_buf, len);
127     return SYS_ERR_OK;
128 }
129
130 errval_t msgbuf_unmarshall_buffer(struct msgbuf *msgbuf, size_t *retlen,
131                                   void **retbuf)
132 {
133     errval_t err;
134
135     // the size of the buffer
136     size_t len = 0;
137     err = msgbuf_unmarshall_size(msgbuf, &len);
138     if (err_is_fail(err)) {
139         return err;
140     }
141
142     // the buffer payload
143     void *src = msgbuf_ensure(msgbuf, len);
144     if (src == NULL) {
145         return LIB_ERR_MSGBUF_OVERFLOW;
146     }
147
148     assert(retbuf != NULL);
149     *retbuf = malloc(len);
150     assert(*retbuf != NULL);
151
152     memcpy(*retbuf, src, len);
153
154     if (retlen != NULL) {
155         *retlen = len;
156     }
157
158     return SYS_ERR_OK;
159 }
160
161 errval_t msgbuf_unmarshall_buffer_to_buf(struct msgbuf *msgbuf, void *dest_buf,
162                                          size_t buflen, size_t *retlen)
163 {
164     errval_t err;
165
166     // the size of the buffer
167     size_t len = 0;
168     err = msgbuf_unmarshall_size(msgbuf, &len);
169     if (err_is_fail(err)) {
170         return err;
171     }
172
173     // the buffer payload
174     void *src = msgbuf_ensure(msgbuf, len);
175     if (src == NULL) {
176         return LIB_ERR_MSGBUF_OVERFLOW;
177     }
178
179     memcpy(dest_buf, src, len < buflen ? len : buflen);
180
181     if (retlen != NULL) {
182         *retlen = len;
183     }
184
185     return SYS_ERR_OK;
186 }
187
188 errval_t msgbuf_marshall_string(struct msgbuf *msgbuf, const char *string)
189 {
190     return msgbuf_marshall_buffer(msgbuf, string, strlen(string) + 1);
191 }
192
193 errval_t msgbuf_unmarshall_string(struct msgbuf *msgbuf, char **ret)
194 {
195     return msgbuf_unmarshall_buffer(msgbuf, NULL, (void **)ret);
196 }
197
198 errval_t msgbuf_unmarshall_string_to_buf(struct msgbuf *msgbuf, char *buf,
199                                           size_t buflen, size_t *retlen)
200 {
201     // unpack to provided buffer
202     size_t len;
203     errval_t err = msgbuf_unmarshall_buffer_to_buf(msgbuf, buf, buflen, &len);
204
205     if (err_is_ok(err)) {
206         // ensure string termination
207         if (len >= buflen) {
208             buf[buflen - 1] = '\0';
209         }
210
211         if (retlen != NULL) {
212             *retlen = len;
213         }
214     }
215
216     return err;
217 }
218
219 errval_t msgbuf_marshall_cap(struct msgbuf *msgbuf, struct capref cap)
220 {
221     if (msgbuf->cap_pos >= msgbuf->ncaps) {
222         if (!msgbuf->dynamic) {
223             return LIB_ERR_MSGBUF_OVERFLOW;
224         }
225
226         void *newbuf = realloc(msgbuf->caps,
227                                (msgbuf->ncaps + 1) * sizeof(struct capref));
228         if (newbuf == NULL) {
229             return LIB_ERR_MSGBUF_CANNOT_GROW;
230         } else {
231             msgbuf->caps = newbuf;
232             msgbuf->ncaps++;
233         }
234     }
235
236     msgbuf->caps[msgbuf->cap_pos++] = cap;
237     return SYS_ERR_OK;
238 }
239
240 errval_t msgbuf_unmarshall_cap(struct msgbuf *msgbuf, struct capref *retcap)
241 {
242     if (msgbuf->cap_pos < msgbuf->ncaps) {
243         *retcap = msgbuf->caps[msgbuf->cap_pos++];
244         return SYS_ERR_OK;
245     } else {
246         return LIB_ERR_MSGBUF_OVERFLOW;
247     }
248 }
249
250 #define DEFINE_PRIM_MARSHALL(NAME, TYPE) \
251 errval_t msgbuf_marshall_##NAME(struct msgbuf *msgbuf, TYPE val) \
252 { \
253     void *buf = msgbuf_grow(msgbuf, sizeof(TYPE)); \
254     if (buf == NULL) { \
255         return LIB_ERR_MSGBUF_CANNOT_GROW; \
256     } \
257     TYPE *dest = buf; \
258     *dest = val; \
259     return SYS_ERR_OK; \
260 }
261
262 #define DEFINE_PRIM_UNMARSHALL(NAME, TYPE) \
263 errval_t msgbuf_unmarshall_##NAME(struct msgbuf *msgbuf, TYPE *ret) \
264 { \
265     void *buf = msgbuf_ensure(msgbuf, sizeof(TYPE)); \
266     if (buf == NULL) { \
267         return LIB_ERR_MSGBUF_OVERFLOW; \
268     } \
269     TYPE *src = buf; \
270     *ret = *src; \
271     return SYS_ERR_OK; \
272 }
273
274 #define DEFINE_PRIM_MARSHALLING(NAME, TYPE) \
275     DEFINE_PRIM_MARSHALL(NAME, TYPE) \
276     DEFINE_PRIM_UNMARSHALL(NAME, TYPE)
277
278 DEFINE_PRIM_MARSHALLING(uintptr, uintptr_t)
279 DEFINE_PRIM_MARSHALLING(intptr, intptr_t)
280 DEFINE_PRIM_MARSHALLING(uint64, uint64_t)
281 DEFINE_PRIM_MARSHALLING(int64, int64_t)
282 DEFINE_PRIM_MARSHALLING(uint32, uint32_t)
283 DEFINE_PRIM_MARSHALLING(int32, int32_t)
284 DEFINE_PRIM_MARSHALLING(uint16, uint16_t)
285 DEFINE_PRIM_MARSHALLING(int16, int16_t)
286 DEFINE_PRIM_MARSHALLING(uint8, uint8_t)
287 DEFINE_PRIM_MARSHALLING(int8, int8_t)
288 DEFINE_PRIM_MARSHALLING(int, int)
289 DEFINE_PRIM_MARSHALLING(float, float)
290 DEFINE_PRIM_MARSHALLING(double, double)
291 DEFINE_PRIM_MARSHALLING(size, size_t)
292 DEFINE_PRIM_MARSHALLING(iref, iref_t)
293
294 #undef DEFINE_PRIM_MARSHALLING
295 #undef DEFINE_PRIM_MARSHALL
296 #undef DEFINE_PRIM_UNMARSHALL