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  {
47  if (m_directMapped)
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  }
78  m_directMapRange.size = msg->size;
81 
82  // Map the remote buffer directly into our address space
83  const API::Result mapResult = VMCtl(SELF, MapContiguous, &m_directMapRange);
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];
95  assert(m_buffer != NULL);
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 
114 void IOBuffer::addCount(const Size bytes)
115 {
116  m_count += bytes;
117  assert(m_count <= m_size);
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 
146 FileSystem::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 
156 FileSystem::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 
180 FileSystem::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 }
MemoryBlock::copy
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Definition: MemoryBlock.cpp:36
IOBuffer::flushWrite
FileSystem::Result flushWrite()
Flush write buffers.
Definition: IOBuffer.cpp:204
API::Result
Result
Enumeration of generic kernel API result codes.
Definition: API.h:68
ulong
unsigned long ulong
Unsigned long number.
Definition: Types.h:47
IOBuffer::m_directMapRange
Memory::Range m_directMapRange
Contains the memory address range of the direct memory mapping.
Definition: IOBuffer.h:174
IOBuffer::getCount
Size getCount() const
Get byte count.
Definition: IOBuffer.cpp:109
IOBuffer::addCount
void addCount(const Size bytes)
Increment byte counter.
Definition: IOBuffer.cpp:114
FileSystemMessage::buffer
char * buffer
Points to a buffer for I/O.
Definition: FileSystemMessage.h:41
IOBuffer::getMessage
const FileSystemMessage * getMessage() const
Get filesystem message.
Definition: IOBuffer.cpp:120
Memory::Writable
@ Writable
Definition: Memory.h:42
PAGEMASK
#define PAGEMASK
Mask to find the page.
Definition: ARMConstant.h:121
Memory::User
@ User
Definition: Memory.h:44
FileSystem::WriteFile
@ WriteFile
Definition: FileSystem.h:40
API::Write
@ Write
Definition: API.h:99
IOBuffer::bufferedWrite
FileSystem::Result bufferedWrite(const void *buffer, const Size size)
Buffered write bytes to the I/O buffer.
Definition: IOBuffer.cpp:146
isKernel
C uint isKernel
Non-zero if this executable is linked as the kernel.
IOBuffer::m_directMapped
bool m_directMapped
True if using directly memory-mapped memory (unbuffered)
Definition: IOBuffer.h:171
Assert.h
Address
unsigned long Address
A memory address.
Definition: Types.h:131
IOBuffer::~IOBuffer
virtual ~IOBuffer()
Destructor.
Definition: IOBuffer.cpp:43
FileSystemMessage
FileSystem IPC message.
Definition: FileSystemMessage.h:37
FileSystem::IOError
@ IOError
Definition: FileSystem.h:58
MemoryBlock.h
VMCtl
API::Result VMCtl(const ProcessID procID, const MemoryOperation op, Memory::Range *range=ZERO)
Prototype for user applications.
Definition: VMCtl.h:61
UnMap
@ UnMap
Definition: VMCtl.h:39
FileSystem::Success
@ Success
Definition: FileSystem.h:54
IOBuffer.h
IOBuffer::IOBuffer
IOBuffer()
Default empty constructor.
Definition: IOBuffer.cpp:24
Memory::Readable
@ Readable
Definition: Memory.h:41
API::Read
@ Read
Definition: API.h:98
SELF
#define SELF
Definition: ProcessID.h:35
IOBuffer::setMessage
void setMessage(const FileSystemMessage *msg)
Set filesystem message.
Definition: IOBuffer.cpp:63
IOBuffer::m_message
const FileSystemMessage * m_message
Current request being processed.
Definition: IOBuffer.h:168
IOBuffer::m_buffer
u8 * m_buffer
Buffer for storing temporary data.
Definition: IOBuffer.h:177
NULL
#define NULL
NULL means zero.
Definition: Macros.h:39
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
LookupVirtual
@ LookupVirtual
Definition: VMCtl.h:42
IOBuffer::getBuffer
u8 * getBuffer()
Get raw buffer.
Definition: IOBuffer.cpp:125
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
IOBuffer::m_count
Size m_count
Bytes written to the buffer.
Definition: IOBuffer.h:183
IOBuffer::m_size
Size m_size
Buffer size.
Definition: IOBuffer.h:180
API::Success
@ Success
Definition: API.h:70
FileSystem::ReadFile
@ ReadFile
Definition: FileSystem.h:39
ChannelMessage::from
ProcessID from
Source process of the message.
Definition: ChannelMessage.h:54
IOBuffer::operator[]
u8 operator[](Size index) const
Byte index operator.
Definition: IOBuffer.cpp:217
IOBuffer::bufferedRead
FileSystem::Result bufferedRead()
Buffered read bytes from the I/O buffer.
Definition: IOBuffer.cpp:130
FileSystemMessage::action
FileSystem::Action action
Action to perform.
Definition: FileSystemMessage.h:39
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
IOBuffer::read
FileSystem::Result read(void *buffer, const Size size, const Size offset=ZERO)
Read bytes from the I/O buffer.
Definition: IOBuffer.cpp:156
CoreInfo.h
IOBuffer::write
FileSystem::Result write(const void *buffer, const Size size, const Size offset=ZERO)
Write bytes to the I/O buffer.
Definition: IOBuffer.cpp:180
VMCopy
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
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
MapContiguous
@ MapContiguous
Definition: VMCtl.h:37
FileSystemMessage::size
Size size
Size of the buffer.
Definition: FileSystemMessage.h:42