FreeNOS
MemoryChannel.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 <Assert.h>
19 #include <Log.h>
20 #include <MemoryBlock.h>
21 #include "MemoryChannel.h"
22 
23 MemoryChannel::MemoryChannel(const Channel::Mode mode, const Size messageSize)
24  : Channel(mode, messageSize)
25  , m_maximumMessages((PAGESIZE / messageSize) - 1U)
26 {
27  assert(messageSize >= sizeof(RingHead));
28  assert(messageSize < (PAGESIZE / 2));
29 
30  reset(true);
31 }
32 
34 {
35 }
36 
38 {
39  if (hardReset)
40  {
41  MemoryBlock::set(&m_head, 0, sizeof(m_head));
42  }
43  else if (m_mode == Channel::Producer)
44  {
45  m_data.read(0, sizeof(m_head), &m_head);
46  }
47  else if (m_mode == Channel::Consumer)
48  {
49  m_feedback.read(0, sizeof(m_head), &m_head);
50  }
51  return Success;
52 }
53 
55  const Address feedback,
56  const bool hardReset)
57 {
58  m_data.setBase(data);
59  m_feedback.setBase(feedback);
60 
61  return reset(hardReset);
62 }
63 
65  const Address feedback,
66  const bool hardReset)
67 {
70 
71  switch (m_mode)
72  {
73  case Consumer:
74  feedAccess |= Memory::Writable;
75  break;
76 
77  case Producer:
78  dataAccess |= Memory::Writable;
79  break;
80  }
81 
82  IO::Result result = m_data.map(data, PAGESIZE, dataAccess);
83  if (result != IO::Success)
84  {
85  ERROR("failed to map data physical address " << (void*)data << ": " << (int)result);
86  return IOError;
87  }
88 
89  result = m_feedback.map(feedback, PAGESIZE, feedAccess);
90  if (result != IO::Success)
91  {
92  ERROR("failed to map feedback physical address " << (void*)feedback << ": " << (int)result);
93  return IOError;
94  }
95 
96  return reset(hardReset);
97 }
98 
100 {
101  Result result = Success;
102 
103  if (m_data.unmap() != IO::Success)
104  {
105  result = IOError;
106  }
107 
108  if (m_feedback.unmap() != IO::Success)
109  {
110  result = IOError;
111  }
112 
113  return result;
114 }
115 
117 {
118  RingHead head;
119 
120  // Read the current ring head
121  m_data.read(0, sizeof(head), &head);
122 
123  // Check if a message is present
124  if (head.index == m_head.index)
125  return NotFound;
126 
127  // Read one message
129 
130  // Increment head index
132 
133  // Update read index
134  m_feedback.write(0, sizeof(m_head), &m_head);
135  return Success;
136 }
137 
139 {
140  RingHead reader;
141 
142  // Read current ring head
143  m_feedback.read(0, sizeof(RingHead), &reader);
144 
145  // Check if buffer space is available for the message
146  if (((m_head.index + 1) % m_maximumMessages) == reader.index)
147  return ChannelFull;
148 
149  // write the message
151 
152  // Increment write index
154  m_data.write(0, sizeof(m_head), &m_head);
155  return Success;
156 }
157 
159 {
160 #ifndef INTEL
161  if (m_mode == Producer)
163  else if (m_mode == Consumer)
165 #endif /* INTEL */
166 
167  return Success;
168 }
169 
171 {
172  // Flush caches in usermode via the kernel.
173  if (!isKernel)
174  {
175 #ifndef __HOST__
176  Memory::Range range;
177  range.virt = page;
178 
179  const API::Result result = VMCtl(SELF, CacheClean, &range);
180  if (result != API::Success)
181  {
182  ERROR("failed to clean data cache at " << (void *) page <<
183  ": result = " << (int) result);
184  return IOError;
185  }
186 #endif /* __HOST__ */
187  }
188  // Clean both pages from the cache directly
189  else
190  {
191  Arch::Cache cache;
192  cache.cleanData(page);
193  }
194 
195  return Success;
196 }
Channel
Unidirectional point-to-point messaging channel.
Definition: Channel.h:34
Channel::Success
@ Success
Definition: Channel.h:43
Memory::Range
Memory range.
Definition: Memory.h:55
IO::unmap
Result unmap()
Unmap I/O address space.
Definition: IO.cpp:70
MemoryChannel::m_maximumMessages
const Size m_maximumMessages
Maximum number of messages that can be stored.
Definition: MemoryChannel.h:176
MemoryChannel::RingHead::index
Size index
Index where the ring buffer starts.
Definition: MemoryChannel.h:53
API::Result
Result
Enumeration of generic kernel API result codes.
Definition: API.h:68
CacheClean
@ CacheClean
Definition: VMCtl.h:46
MemoryChannel::setVirtual
Result setVirtual(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by virtual address.
Definition: MemoryChannel.cpp:54
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
MemoryChannel::setPhysical
Result setPhysical(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by physical address.
Definition: MemoryChannel.cpp:64
Memory::Writable
@ Writable
Definition: Memory.h:42
IO::map
Result map(Address phys, Size size=4096, Memory::Access access=Memory::Readable|Memory::Writable|Memory::User)
Map I/O address space.
Definition: IO.cpp:38
Channel::Mode
Mode
Channel modes.
Definition: Channel.h:56
Memory::User
@ User
Definition: Memory.h:44
ARMIO::write
void write(u32 reg, u32 data)
write to memory mapped I/O register
Definition: ARMIO.h:46
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
MemoryChannel::MemoryChannel
MemoryChannel(const Mode mode, const Size messageSize)
Constructor.
Definition: MemoryChannel.cpp:23
Channel::m_messageSize
const Size m_messageSize
Message size.
Definition: Channel.h:117
isKernel
C uint isKernel
Non-zero if this executable is linked as the kernel.
Assert.h
Channel::m_mode
const Mode m_mode
Channel mode.
Definition: Channel.h:114
Address
unsigned long Address
A memory address.
Definition: Types.h:131
MemoryBlock.h
VMCtl
API::Result VMCtl(const ProcessID procID, const MemoryOperation op, Memory::Range *range=ZERO)
Prototype for user applications.
Definition: VMCtl.h:61
MemoryChannel::m_data
Arch::IO m_data
The data page.
Definition: MemoryChannel.h:179
MemoryChannel::RingHead
Defines in-memory ring header.
Definition: MemoryChannel.h:50
Channel::IOError
@ IOError
Definition: Channel.h:47
Memory::Readable
@ Readable
Definition: Memory.h:41
Log.h
SELF
#define SELF
Definition: ProcessID.h:35
IO::setBase
void setBase(const Address base)
Set memory I/O base offset.
Definition: IO.cpp:33
MemoryChannel::~MemoryChannel
virtual ~MemoryChannel()
Destructor.
Definition: MemoryChannel.cpp:33
Channel::NotFound
@ NotFound
Definition: Channel.h:49
ARMCacheV6
ARMv6 cache management implementation.
Definition: ARMCacheV6.h:42
Channel::Consumer
@ Consumer
Definition: Channel.h:59
IO::Result
Result
Result codes.
Definition: IO.h:42
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
MemoryChannel::write
virtual Result write(const void *buffer)
Write a message.
Definition: MemoryChannel.cpp:138
Cache::cleanData
virtual Result cleanData(Address addr)
Clean one data page.
Definition: Cache.cpp:20
Memory::Access
Access
Memory access flags.
Definition: Memory.h:38
ARMIO::read
u32 read(u32 reg) const
read from memory mapped I/O register
Definition: ARMIO.h:62
Channel::Producer
@ Producer
Definition: Channel.h:58
MemoryChannel::flush
virtual Result flush()
Flush message buffers.
Definition: MemoryChannel.cpp:158
MemoryChannel::read
virtual Result read(void *buffer)
Read a message.
Definition: MemoryChannel.cpp:116
MemoryChannel::reset
Result reset(const bool hardReset)
Reset to initial state.
Definition: MemoryChannel.cpp:37
IO::Success
@ Success
Definition: IO.h:44
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
Channel::Result
Result
Result codes.
Definition: Channel.h:41
MemoryChannel::m_feedback
Arch::IO m_feedback
The feedback page.
Definition: MemoryChannel.h:182
API::Success
@ Success
Definition: API.h:70
MemoryChannel::unmap
Result unmap()
Unmap memory pages from virtual address space.
Definition: MemoryChannel.cpp:99
IO::getBase
Address getBase() const
Get memory I/O base offset.
Definition: IO.cpp:28
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
MemoryChannel::flushPage
Result flushPage(const Address page) const
Flush memory page.
Definition: MemoryChannel.cpp:170
MemoryChannel.h
MemoryChannel::m_head
RingHead m_head
Local RingHead.
Definition: MemoryChannel.h:185
Channel::ChannelFull
@ ChannelFull
Definition: Channel.h:48