MOS Source Code
Loading...
Searching...
No Matches
io.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/mm/mm.hpp"
5
6#include <mos/io/io.hpp>
7#include <mos/io/io_types.h>
8#include <mos/mm/mm_types.h>
9#include <mos/mos_global.h>
10#include <mos/syslog/printk.hpp>
11#include <mos_stdio.hpp>
12
13static size_t _null_read(io_t *io, void *buffer, size_t size)
14{
15 (void) io;
16 (void) buffer;
17 (void) size;
18 return 0;
19}
20
21static size_t _null_write(io_t *io, const void *buffer, size_t size)
22{
23 (void) io;
24 (void) buffer;
25 (void) size;
26 return 0;
27}
28
29static const io_op_t ops{
30 .read = _null_read,
31 .write = _null_write,
32 .close = NULL,
33 .seek = NULL,
34};
35
37 .refcount = 1, // never gets closed
38 .flags = IO_READABLE | IO_WRITABLE,
39 .type = IO_NULL,
40 .ops = &ops,
41};
42
44
45void io_init(io_t *io, io_type_t type, io_flags_t flags, const io_op_t *ops)
46{
47 pr_dinfo2(io, "io_init(%p, %d, %d, %p)", (void *) io, type, flags, (void *) ops);
48
49 if (unlikely(!io))
50 mos_warn("io is NULL");
51
52 if (unlikely(!ops))
53 mos_warn("io->ops is NULL");
54
55 if (flags & IO_READABLE)
56 if (unlikely(!ops->read))
57 mos_warn("ops->read is NULL for readable io");
58
59 if (flags & IO_WRITABLE)
60 if (unlikely(!ops->write))
61 mos_warn("ops->write is NULL for writable io");
62
63 if (flags & IO_SEEKABLE)
64 if (unlikely(!ops->seek))
65 mos_warn("io->ops->seek is NULL for seekable io");
66
67 io->flags = flags;
68 io->type = type;
69 io->ops = ops;
70 io->closed = false;
71 io->refcount = 0;
72}
73
75{
76 pr_dinfo2(io, "io_ref(%p)", (void *) io);
77 if (unlikely(!io))
78 {
79 mos_warn("io is NULL");
80 return NULL;
81 }
82
83 if (unlikely(io->closed))
84 {
85 mos_warn("%p is already closed", (void *) io);
86 return 0;
87 }
88
89 io->refcount++;
90 return io;
91}
92
94{
95 pr_dinfo2(io, "io_unref(%p)", (void *) io);
96 if (unlikely(io->closed))
97 {
98 mos_warn("%p is already closed", (void *) io);
99 return NULL;
100 }
101
102 if (unlikely(io->refcount == 0))
103 {
104 mos_warn("%p has refcount 0", (void *) io);
105 return NULL;
106 }
107
108 io->refcount--;
109
110 if (io->refcount == 0)
111 {
112 if (io->ops->close)
113 {
114 pr_dinfo2(io, "closing %p", (void *) io);
115 io->closed = true;
116 io->ops->close(io);
117 }
118 else
119 {
120 pr_dinfo2(io, "%p is not closeable", (void *) io);
121 }
122 return NULL;
123 }
124
125 return io;
126}
127
128bool io_valid(const io_t *io)
129{
130 return io && !io->closed && io->refcount > 0 && io->ops;
131}
132
133size_t io_read(io_t *io, void *buf, size_t count)
134{
135 pr_dinfo2(io, "io_read(%p, %p, %zu)", (void *) io, buf, count);
136
137 if (unlikely(io->closed))
138 {
139 mos_warn("%p is already closed", (void *) io);
140 return 0;
141 }
142
143 if (!(io->flags & IO_READABLE))
144 {
145 pr_info2("%p is not readable\n", (void *) io);
146 return 0;
147 }
148
149 return io->ops->read(io, buf, count);
150}
151
152size_t io_pread(io_t *io, void *buf, size_t count, off_t offset)
153{
154 pr_dinfo2(io, "io_pread(%p, %p, %zu, %lu)", (void *) io, buf, count, offset);
155
156 if (unlikely(io->closed))
157 {
158 mos_warn("%p is already closed", (void *) io);
159 return 0;
160 }
161
162 if (!(io->flags & IO_READABLE))
163 {
164 pr_info2("%p is not readable\n", (void *) io);
165 return 0;
166 }
167
168 if (!(io->flags & IO_SEEKABLE))
169 {
170 pr_info2("%p is not seekable\n", (void *) io);
171 return 0;
172 }
173
174 const off_t old_offset = io_tell(io);
175 io_seek(io, offset, IO_SEEK_SET);
176 const size_t ret = io_read(io, buf, count);
177 io_seek(io, old_offset, IO_SEEK_SET);
178 return ret;
179}
180
181size_t io_write(io_t *io, const void *buf, size_t count)
182{
183 pr_dinfo2(io, "io_write(%p, %p, %zu)", (void *) io, buf, count);
184
185 if (unlikely(io->closed))
186 {
187 mos_warn("%p is already closed", (void *) io);
188 return 0;
189 }
190
191 if (!(io->flags & IO_WRITABLE))
192 {
193 pr_info2("%p is not writable", (void *) io);
194 return 0;
195 }
196
197 return io->ops->write(io, buf, count);
198}
199
201{
202 pr_dinfo2(io, "io_seek(%p, %lu, %d)", (void *) io, offset, whence);
203
204 if (unlikely(io->closed))
205 {
206 mos_warn("%p is already closed", (void *) io);
207 return 0;
208 }
209
210 if (!(io->flags & IO_SEEKABLE))
211 {
212 pr_info2("%p is not seekable", (void *) io);
213 return 0;
214 }
215
216 return io->ops->seek(io, offset, whence);
217}
218
220{
221 pr_dinfo2(io, "io_tell(%p)", (void *) io);
222 return io_seek(io, 0, IO_SEEK_CURRENT);
223}
224
225bool io_mmap_perm_check(io_t *io, vm_flags flags, bool is_private)
226{
227 if (unlikely(io->closed))
228 {
229 mos_warn("%p is already closed", (void *) io);
230 return false;
231 }
232
233 if (!(io->flags & IO_MMAPABLE))
234 {
235 pr_info2("%p is not mmapable", (void *) io);
236 return false;
237 }
238
239 if (!(io->flags & IO_READABLE))
240 return false; // can't mmap if io is not readable
241
242 if (flags & VM_WRITE)
243 {
244 const bool may_mmap_writeable = is_private || io->flags & IO_WRITABLE;
245 if (!may_mmap_writeable)
246 return false; // can't mmap writable if io is not writable and not private
247 }
248
249 // if (flags & VM_EXEC && !(io->flags & IO_EXECUTABLE))
250 // return false; // can't mmap executable if io is not executable
251
252 return true;
253}
254
255bool io_mmap(io_t *io, vmap_t *vmap, off_t offset)
256{
257 pr_dinfo2(io, "io_mmap(%p, %p, %lu)", (void *) io, (void *) vmap, offset);
258 if (!io_mmap_perm_check(io, vmap->vmflags, vmap->type == VMAP_TYPE_PRIVATE))
259 return false;
260
261 vmap->io = io;
262 vmap->io_offset = offset;
263
264 if (!io->ops->mmap(io, vmap, offset))
265 return false;
266
267 if (unlikely(!vmap->on_fault))
268 mos_panic("vmap->on_fault is NULL, possibly buggy io->ops->mmap() implementation");
269
270 io_ref(io); // mmap increases refcount
271 return true;
272}
273
274bool io_munmap(io_t *io, vmap_t *vmap, bool *unmapped)
275{
276 pr_dinfo2(io, "io_unmap(%p, %p, %p)", (void *) io, (void *) vmap, (void *) unmapped);
277 if (unlikely(io->closed))
278 {
279 mos_warn("%p is already closed", (void *) io);
280 return false;
281 }
282
283 if (unlikely(!vmap->io))
284 {
285 mos_warn("vmap->io is NULL");
286 return false;
287 }
288
289 if (unlikely(vmap->io != io))
290 {
291 mos_warn("vmap->io != io");
292 return false;
293 }
294
295 if (vmap->io->ops->munmap)
296 {
297 if (unlikely(!vmap->io->ops->munmap(vmap->io, vmap, unmapped)))
298 {
299 mos_warn("vmap->io->ops->unmap() failed");
300 return false;
301 }
302 }
303
304 io_unref(io); // unmap decreases refcount
305 return true;
306}
307
308void io_get_name(const io_t *io, char *buf, size_t size)
309{
310 if (io == NULL || io->ops == NULL || io->ops->get_name == NULL)
311 {
312 snprintf(buf, size, "<invalid io %p>", (void *) io);
313 return;
314 }
315
316 if (io->ops->get_name)
317 io->ops->get_name(io, buf, size);
318 else
319 snprintf(buf, size, "<unnamed io %p>", (void *) io);
320}
#define mos_warn(fmt,...)
Definition assert.hpp:23
MOSAPI void(1, 2) fatal_abort(const char *fmt
@ VMAP_TYPE_PRIVATE
Definition mm.hpp:32
bool io_mmap_perm_check(io_t *io, vm_flags flags, bool is_private)
Definition io.cpp:225
off_t io_tell(io_t *io)
Definition io.cpp:219
size_t io_pread(io_t *io, void *buf, size_t count, off_t offset)
Definition io.cpp:152
bool io_munmap(io_t *io, vmap_t *vmap, bool *unmapped)
Definition io.cpp:274
static size_t _null_read(io_t *io, void *buffer, size_t size)
Definition io.cpp:13
void io_init(io_t *io, io_type_t type, io_flags_t flags, const io_op_t *ops)
Definition io.cpp:45
io_t * io_ref(io_t *io)
Definition io.cpp:74
bool io_mmap(io_t *io, vmap_t *vmap, off_t offset)
Definition io.cpp:255
off_t io_seek(io_t *io, off_t offset, io_seek_whence_t whence)
Definition io.cpp:200
static io_t io_null_impl
Definition io.cpp:36
static const io_op_t ops
Definition io.cpp:29
io_t * io_unref(io_t *io)
Definition io.cpp:93
size_t io_write(io_t *io, const void *buf, size_t count)
Definition io.cpp:181
bool io_valid(const io_t *io)
Definition io.cpp:128
size_t io_read(io_t *io, void *buf, size_t count)
Definition io.cpp:133
static size_t _null_write(io_t *io, const void *buffer, size_t size)
Definition io.cpp:21
void io_get_name(const io_t *io, char *buf, size_t size)
Definition io.cpp:308
io_flags_t
Definition io.hpp:25
@ IO_MMAPABLE
Definition io.hpp:31
@ IO_READABLE
Definition io.hpp:27
@ IO_SEEKABLE
Definition io.hpp:30
@ IO_WRITABLE
Definition io.hpp:28
io_type_t
Definition io.hpp:15
@ IO_NULL
Definition io.hpp:16
io_t *const io_null
Definition io.cpp:43
io_seek_whence_t
Definition io_types.h:6
@ IO_SEEK_SET
Definition io_types.h:9
@ IO_SEEK_CURRENT
Definition io_types.h:7
#define unlikely(x)
Definition mos_global.h:40
int snprintf(char *__restrict str, size_t size, const char *__restrict format,...)
Definition mos_stdio.cpp:16
#define mos_panic(fmt,...)
Definition panic.hpp:51
#define NULL
Definition pb_syshdr.h:46
vm_flags
Definition platform.hpp:42
@ VM_WRITE
Definition platform.hpp:45
#define pr_info2(fmt,...)
Definition printk.hpp:36
#define pr_dinfo2(feat, fmt,...)
Definition printk.hpp:27
size_t size
Definition slab.cpp:34
Definition io.hpp:37
size_t(* read)(io_t *io, void *buf, size_t count)
Definition io.hpp:38
off_t(* seek)(io_t *io, off_t offset, io_seek_whence_t whence)
Definition io.hpp:41
void(* close)(io_t *io)
Definition io.hpp:40
bool(* mmap)(io_t *io, vmap_t *vmap, off_t offset)
Definition io.hpp:42
bool(* munmap)(io_t *io, vmap_t *vmap, bool *unmapped)
Definition io.hpp:43
void(* get_name)(const io_t *io, char *buf, size_t size)
Definition io.hpp:44
size_t(* write)(io_t *io, const void *buf, size_t count)
Definition io.hpp:39
Definition io.hpp:48
io_type_t type
Definition io.hpp:52
io_flags_t flags
Definition io.hpp:51
bool closed
Definition io.hpp:49
atomic_t refcount
Definition io.hpp:50
const io_op_t * ops
Definition io.hpp:53
Definition mm.hpp:59
vmfault_handler_t on_fault
Definition mm.hpp:74
vm_flags vmflags
Definition mm.hpp:65
io_t * io
Definition mm.hpp:68
off_t io_offset
Definition mm.hpp:69
vmap_type_t type
Definition mm.hpp:72
static char buffer[2048]
ssize_t off_t
Definition types.h:80