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"
4
5#include <mos/io/io.hpp>
6#include <mos/io/io_types.h>
7#include <mos/mm/mm_types.h>
8#include <mos/mos_global.h>
10#include <mos_stdio.hpp>
11
12struct NullIO final : IO
13{
15 virtual ~NullIO() {};
16 void on_closed() override
17 {
18 mos_panic("null io cannot be closed");
19 }
20
21 size_t on_read(void *, size_t) override
22 {
23 return 0;
24 }
25
26 size_t on_write(const void *, size_t) override
27 {
28 return 0;
29 }
30};
31
34
35IO::IO(IOFlags flags, io_type_t type) : io_flags(flags), io_type(type)
36{
37}
38
40{
41 if (!io_closed)
42 mEmerg << "IO::~IO: " << (void *) (this) << " is not closed at destruction";
43}
44
46{
47 return "<unnamed io " + mos::to_string(this) + ">";
48}
49
50size_t IO::read(void *buf, size_t count)
51{
52 dInfo2<io> << "io_read(" << (void *) this << ", " << buf << ", " << count << ")";
53
55 {
56 mos_warn("%p is already closed", (void *) this);
57 return 0;
58 }
59
60 if (!io_flags.test(IO_READABLE))
61 {
62 mInfo << (void *) this << " is not readable\n";
63 return 0;
64 }
65
66 return on_read(buf, count);
67}
68
69size_t IO::pread(void *buf, size_t count, off_t offset)
70{
71 dInfo2<io> << "io_pread(" << (void *) this << ", " << buf << ", " << count << ", " << offset << ")";
72
74 {
75 mos_warn("%p is already closed", (void *) this);
76 return 0;
77 }
78
79 if (!(io_flags.test(IO_READABLE)))
80 {
81 mInfo << (void *) this << " is not readable\n";
82 return 0;
83 }
84
85 if (!(io_flags.test(IO_SEEKABLE)))
86 {
87 mInfo << (void *) this << " is not seekable\n";
88 return 0;
89 }
90
91 const off_t old_offset = this->tell();
92 this->seek(offset, IO_SEEK_SET);
93 const size_t ret = read(buf, count);
94 this->seek(old_offset, IO_SEEK_SET);
95 return ret;
96}
97
98size_t IO::write(const void *buf, size_t count)
99{
100 dInfo2<io> << "io_write(" << (void *) this << ", " << buf << ", " << count << ")";
101
102 if (unlikely(io_closed))
103 {
104 mos_warn("%p is already closed", (void *) this);
105 return 0;
106 }
107
108 if (!(io_flags.test(IO_WRITABLE)))
109 {
110 mInfo << (void *) this << " is not writable";
111 return 0;
112 }
113
114 return on_write(buf, count);
115}
116
118{
119 dInfo2<io> << "io_seek(" << (void *) this << ", " << offset << ", " << whence << ")";
120
121 if (unlikely(io_closed))
122 {
123 mos_warn("%p is already closed", (void *) this);
124 return 0;
125 }
126
127 if (!io_flags.test(IO_SEEKABLE))
128 {
129 mInfo << (void *) this << " is not seekable";
130 return 0;
131 }
132
133 return on_seek(offset, whence);
134}
135
137{
138 dInfo2<io> << fmt("io_tell({})", (void *) this);
139 return seek(0, IO_SEEK_CURRENT);
140}
141
142bool IO::VerifyMMapPermissions(VMFlags flags, bool is_private)
143{
144 if (unlikely(io_closed))
145 {
146 mos_warn("%p is already closed", (void *) io);
147 return false;
148 }
149
150 if (!(io_flags.test(IO_MMAPABLE)))
151 {
152 mInfo << (void *) io << " is not mmapable";
153 return false;
154 }
155
156 if (!(io_flags.test(IO_READABLE)))
157 return false; // can't mmap if io is not readable
158
159 if (flags & VM_WRITE)
160 {
161 const bool may_mmap_writeable = is_private || io_flags.test(IO_WRITABLE);
162 if (!may_mmap_writeable)
163 return false; // can't mmap writable if io is not writable and not private
164 }
165
166 // if (flags & VM_EXEC && !(io->flags & IO_EXECUTABLE))
167 // return false; // can't mmap executable if io is not executable
168
169 return true;
170}
171
172bool IO::map(vmap_t *vmap, off_t offset)
173{
174 dInfo2<io> << "io_mmap(" << (void *) this << ", " << (void *) vmap << ", " << offset << ")";
176 return false;
177
178 vmap->io = this;
179 vmap->io_offset = offset;
180
181 if (!this->on_mmap(vmap, offset))
182 return false;
183
184 if (unlikely(!vmap->on_fault))
185 mos_panic("vmap->on_fault is NULL, possibly buggy io->ops->mmap() implementation");
186
187 this->ref(); // mmap increases refcount
188 return true;
189}
190
191bool IO::unmap(vmap_t *vmap, bool *unmapped)
192{
193 dInfo2<io> << "io_unmap(" << (void *) this << ", " << (void *) vmap << ", " << (void *) unmapped << ")";
194 if (unlikely(io_closed))
195 {
196 mos_warn("%p is already closed", (void *) this);
197 return false;
198 }
199
200 if (unlikely(!vmap->io))
201 {
202 mos_warn("vmap->io is NULL");
203 return false;
204 }
205
206 if (unlikely(vmap->io != this))
207 {
208 mos_warn("vmap->io != io");
209 return false;
210 }
211
212 if (unlikely(!on_munmap(vmap, unmapped)))
213 {
214 mos_warn("vmap->io->ops->unmap() failed");
215 return false;
216 }
217
218 this->unref(); // unmap decreases refcount
219 return true;
220}
221
222size_t IO::on_read(void *, size_t)
223{
224 MOS_UNREACHABLE_X("IO %p is readable but does not implement on_read", (void *) this);
225 return -ENOTSUP;
226}
227
228size_t IO::on_write(const void *, size_t)
229{
230 MOS_UNREACHABLE_X("IO %p is writable but does not implement on_write", (void *) this);
231 return -ENOTSUP;
232}
233
235{
236 MOS_UNREACHABLE_X("IO %p is mappable but does not implement on_mmap", (void *) this);
237 return false;
238}
239
240bool IO::on_munmap(vmap_t *, bool *)
241{
242 return false;
243}
244
246{
247 MOS_UNREACHABLE_X("IO %p is seekable but does not implement on_seek", (void *) this);
248}
#define MOS_UNREACHABLE_X(msg,...)
Definition assert.hpp:11
#define mos_warn(fmt,...)
Definition assert.hpp:22
@ VMAP_TYPE_PRIVATE
Definition mm.hpp:33
static NullIO io_null_impl
Definition io.cpp:32
IO *const io_null
Definition io.cpp:33
@ IO_MMAPABLE
Definition io.hpp:34
@ IO_READABLE
Definition io.hpp:30
@ IO_SEEKABLE
Definition io.hpp:33
@ IO_WRITABLE
Definition io.hpp:31
io_type_t
Definition io.hpp:18
@ IO_NULL
Definition io.hpp:19
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
@ VM_WRITE
Definition mm_types.hpp:14
#define unlikely(x)
Definition mos_global.h:40
mos::string to_string(const void *value)
Definition string.cpp:9
mos::basic_string< char > string
Definition string.hpp:395
#define mos_panic(fmt,...)
Definition panic.hpp:51
Definition io.hpp:39
virtual size_t pread(void *buf, size_t count, off_t offset) final
Definition io.cpp:69
virtual mos::string name() const
Definition io.cpp:45
virtual size_t read(void *buf, size_t count) final
Definition io.cpp:50
virtual bool VerifyMMapPermissions(VMFlags flags, bool is_private) final
Definition io.cpp:142
bool unmap(vmap_t *vmap, bool *unmapped)
Definition io.cpp:191
IO(IOFlags flags, io_type_t type)
Definition io.cpp:35
virtual bool on_munmap(vmap_t *, bool *)
Definition io.cpp:240
IO * ref()
Definition io.hpp:57
virtual ~IO()=0
Definition io.cpp:39
const io_type_t io_type
Definition io.hpp:41
virtual size_t on_write(const void *, size_t)
Definition io.cpp:228
const IOFlags io_flags
Definition io.hpp:40
virtual off_t tell() final
Definition io.cpp:136
virtual off_t seek(off_t, io_seek_whence_t) final
Definition io.cpp:117
bool map(vmap_t *vmap, off_t offset)
Definition io.cpp:172
virtual size_t on_read(void *, size_t)
Definition io.cpp:222
IO * unref()
Definition io.hpp:69
virtual size_t write(const void *buf, size_t count) final
Definition io.cpp:98
bool io_closed
Definition io.hpp:109
virtual off_t on_seek(off_t, io_seek_whence_t)
Definition io.cpp:245
virtual bool on_mmap(vmap_t *, off_t)
Definition io.cpp:234
Definition io.cpp:13
virtual ~NullIO()
Definition io.cpp:15
size_t on_write(const void *, size_t) override
Definition io.cpp:26
NullIO()
Definition io.cpp:14
void on_closed() override
Definition io.cpp:16
size_t on_read(void *, size_t) override
Definition io.cpp:21
Definition mm.hpp:60
VMFlags vmflags
Definition mm.hpp:66
vmfault_handler_t on_fault
Definition mm.hpp:75
IO * io
Definition mm.hpp:69
off_t io_offset
Definition mm.hpp:70
vmap_type_t type
Definition mm.hpp:73
constexpr auto dInfo2
Definition syslog.hpp:151
constexpr auto mInfo
Definition syslog.hpp:152
#define fmt(_fmt,...)
Definition syslog.hpp:161
constexpr auto mEmerg
Definition syslog.hpp:155
ssize_t off_t
Definition types.h:80