FreeNOS
IOBuffer.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <FreeNOS/User.h>
19#include <Assert.h>
20#include <MemoryBlock.h>
21#include <CoreInfo.h>
22#include "IOBuffer.h"
23
25 : m_message(ZERO)
26 , m_directMapped(false)
27 , m_buffer(ZERO)
28 , m_size(0)
29 , m_count(0)
30{
31}
32
34 : m_message(msg)
35 , m_directMapped(false)
36 , m_buffer(ZERO)
37 , m_size(0)
38 , m_count(0)
39{
40 setMessage(msg);
41}
42
44{
45 if (m_buffer)
46 {
48 {
50 if (r != API::Success)
51 {
52 ERROR("failed to unmap remote buffer using VMCtl: result = " << (int) r);
53 return;
54 }
55 }
56 else
57 {
58 delete[] m_buffer;
59 }
60 }
61}
62
64{
66 {
67 // If the remote buffer is page aligned, we can directly map it (unbuffered)
68 if (!isKernel && !((const ulong) msg->buffer & ~PAGEMASK))
69 {
70 // Lookup the physical address
72 const API::Result lookResult = VMCtl(msg->from, LookupVirtual, &m_directMapRange);
73 if (lookResult != API::Success)
74 {
75 ERROR("failed to lookup remote buffer using VMCtl: result = " << (int) lookResult);
76 return;
77 }
81
82 // Map the remote buffer directly into our address space
84 if (mapResult != API::Success)
85 {
86 ERROR("failed to map remote buffer using VMCtl: result = " << (int) mapResult);
87 return;
88 }
89 m_directMapped = true;
91 }
92 else
93 {
94 m_buffer = new u8[msg->size];
96 }
97 }
98 else
99 {
100 assert(m_buffer == NULL);
101 m_buffer = 0;
102 }
103
104 m_message = msg;
105 m_size = msg->size;
106 m_count = 0;
107}
108
110{
111 return m_count;
112}
113
114void IOBuffer::addCount(const Size bytes)
115{
116 m_count += bytes;
118}
119
121{
122 return m_message;
123}
124
126{
127 return m_buffer;
128}
129
131{
132 if (!m_directMapped)
133 {
134 const FileSystem::Result result = read(m_buffer, m_message->size, 0);
135 if (result != FileSystem::Success)
136 {
137 m_count = 0;
138 return result;
139 }
140 }
141
143 return FileSystem::Success;
144}
145
146FileSystem::Result IOBuffer::bufferedWrite(const void *buffer, const Size size)
147{
148 const Size num = m_count + size < m_size ? size : m_size - m_count;
149
150 MemoryBlock::copy(m_buffer + m_count, buffer, num);
151 m_count += num;
152
153 return FileSystem::Success;
154}
155
156FileSystem::Result IOBuffer::read(void *buffer, const Size size, const Size offset)
157{
158 m_count = 0;
159
160 if (m_directMapped)
161 {
162 MemoryBlock::copy(buffer, m_buffer + offset, size);
163 return FileSystem::Success;
164 }
165
166 const API::Result result = VMCopy(m_message->from, API::Read,
167 (Address) buffer,
168 (Address) m_message->buffer + offset, size);
169 if (result == API::Success)
170 {
171 return FileSystem::Success;
172 }
173 else
174 {
175 ERROR("VMCopy failed for PID " << m_message->from << ": result = " << (int) result);
176 return FileSystem::IOError;
177 }
178}
179
180FileSystem::Result IOBuffer::write(const void *buffer, const Size size, const Size offset)
181{
182 m_count = 0;
183
184 if (m_directMapped)
185 {
186 MemoryBlock::copy(m_buffer + offset, buffer, size);
187 return FileSystem::Success;
188 }
189
190 const API::Result result = VMCopy(m_message->from, API::Write,
191 (Address) buffer,
192 (Address) m_message->buffer + offset, size);
193 if (result == API::Success)
194 {
195 return FileSystem::Success;
196 }
197 else
198 {
199 ERROR("VMCopy failed for PID " << m_message->from << ": result = " << (int) result);
200 return FileSystem::IOError;
201 }
202}
203
205{
206 if (m_directMapped)
207 {
208 m_count = 0;
209 return FileSystem::Success;
210 }
211 else
212 {
213 return write(m_buffer, m_count, 0);
214 }
215}
216
218{
219 return index < m_size ? m_buffer[index] : 0;
220}
Result
Enumeration of generic kernel API result codes.
Definition API.h:69
@ Success
Definition API.h:70
@ Read
Definition API.h:98
@ Write
Definition API.h:99
ProcessID from
Source process of the message.
FileSystem::Result flushWrite()
Flush write buffers.
Definition IOBuffer.cpp:204
void addCount(const Size bytes)
Increment byte counter.
Definition IOBuffer.cpp:114
void setMessage(const FileSystemMessage *msg)
Set filesystem message.
Definition IOBuffer.cpp:63
Size m_size
Buffer size.
Definition IOBuffer.h:180
Size getCount() const
Get byte count.
Definition IOBuffer.cpp:109
Memory::Range m_directMapRange
Contains the memory address range of the direct memory mapping.
Definition IOBuffer.h:174
u8 * getBuffer()
Get raw buffer.
Definition IOBuffer.cpp:125
FileSystem::Result bufferedWrite(const void *buffer, const Size size)
Buffered write bytes to the I/O buffer.
Definition IOBuffer.cpp:146
Size m_count
Bytes written to the buffer.
Definition IOBuffer.h:183
const FileSystemMessage * m_message
Current request being processed.
Definition IOBuffer.h:168
virtual ~IOBuffer()
Destructor.
Definition IOBuffer.cpp:43
bool m_directMapped
True if using directly memory-mapped memory (unbuffered)
Definition IOBuffer.h:171
u8 operator[](Size index) const
Byte index operator.
Definition IOBuffer.cpp:217
IOBuffer()
Default empty constructor.
Definition IOBuffer.cpp:24
FileSystem::Result read(void *buffer, const Size size, const Size offset=ZERO)
Read bytes from the I/O buffer.
Definition IOBuffer.cpp:156
FileSystem::Result write(const void *buffer, const Size size, const Size offset=ZERO)
Write bytes to the I/O buffer.
Definition IOBuffer.cpp:180
const FileSystemMessage * getMessage() const
Get filesystem message.
Definition IOBuffer.cpp:120
u8 * m_buffer
Buffer for storing temporary data.
Definition IOBuffer.h:177
FileSystem::Result bufferedRead()
Buffered read bytes from the I/O buffer.
Definition IOBuffer.cpp:130
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
API::Result VMCopy(const ProcessID proc, const API::Operation how, const Address ours, const Address theirs, const Size sz)
Prototype for user applications.
Definition VMCopy.h:42
#define SELF
Definition ProcessID.h:35
API::Result VMCtl(const ProcessID procID, const MemoryOperation op, Memory::Range *range=ZERO)
Prototype for user applications.
Definition VMCtl.h:61
@ LookupVirtual
Definition VMCtl.h:42
@ UnMap
Definition VMCtl.h:39
@ MapContiguous
Definition VMCtl.h:37
#define PAGEMASK
Mask to find the page.
C uint isKernel
Non-zero if this executable is linked as the kernel.
#define assert(exp)
Insert program diagnostics.
Definition assert.h:60
#define NULL
NULL means zero.
Definition Macros.h:39
unsigned long Address
A memory address.
Definition Types.h:131
#define ERROR(msg)
Output an error message.
Definition Log.h:61
unsigned long ulong
Unsigned long number.
Definition Types.h:47
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#define ZERO
Zero value.
Definition Macros.h:43
unsigned char u8
Unsigned 8-bit number.
Definition Types.h:59
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
@ User
Definition Memory.h:44
@ Readable
Definition Memory.h:41
@ Writable
Definition Memory.h:42
FileSystem IPC message.
char * buffer
Points to a buffer for I/O.
FileSystem::Action action
Action to perform.
Size size
Size of the buffer.
Size size
Size in number of bytes.
Definition Memory.h:59
Address virt
Virtual address.
Definition Memory.h:57
Access access
Page access flags.
Definition Memory.h:60