FreeNOS
Process.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/System.h>
19 #include <FreeNOS/API.h>
20 #include <MemoryBlock.h>
21 #include <MemoryChannel.h>
22 #include <SplitAllocator.h>
23 #include "Process.h"
24 #include "ProcessEvent.h"
25 
26 Process::Process(ProcessID id, Address entry, bool privileged, const MemoryMap &map)
27  : m_id(id), m_map(map), m_shares(id)
28 {
29  m_state = Stopped;
30  m_parent = 0;
31  m_waitId = 0;
32  m_waitResult = 0;
33  m_wakeups = 0;
34  m_entry = entry;
35  m_privileged = privileged;
39 }
40 
42 {
43  if (m_kernelChannel)
44  {
45  delete m_kernelChannel;
46  }
47 
48  if (m_memoryContext)
49  {
56  delete m_memoryContext;
57  }
58 }
59 
61 {
62  return m_id;
63 }
64 
66 {
67  return m_parent;
68 }
69 
71 {
72  return m_waitId;
73 }
74 
76 {
77  return m_waitResult;
78 }
79 
81 {
82  return m_state;
83 }
84 
86 {
87  return m_shares;
88 }
89 
91 {
92  return m_sleepTimer;
93 }
94 
96 {
97  return m_memoryContext;
98 }
99 
101 {
102  return m_privileged;
103 }
104 
106 {
107  m_parent = id;
108 }
109 
111 {
112  if (m_state != Ready)
113  {
114  ERROR("Process ID " << m_id << " has invalid state: " << (uint) m_state);
115  return InvalidArgument;
116  }
117 
118  m_state = Waiting;
119  m_waitId = id;
120 
121  return Success;
122 }
123 
125 {
126  if (m_state != Waiting)
127  {
128  ERROR("PID " << m_id << " has invalid state: " << (uint) m_state);
129  return InvalidArgument;
130  }
131 
132  m_waitResult = result;
133  m_state = Ready;
134  return Success;
135 }
136 
138 {
139  if (m_state != Ready && m_state != Sleeping && m_state != Stopped)
140  {
141  ERROR("PID " << m_id << " has invalid state: " << (uint) m_state);
142  return InvalidArgument;
143  }
144 
145  m_state = Stopped;
146  return Success;
147 }
148 
150 {
151  if (m_state != Stopped)
152  {
153  ERROR("PID " << m_id << " has invalid state: " << (uint) m_state);
154  return InvalidArgument;
155  }
156 
157  m_state = Ready;
158  return Success;
159 }
160 
162 {
163  // Write the message. Be sure to flush the caches because
164  // the kernel has mapped the channel pages separately in low memory.
165  m_kernelChannel->write(event);
167 
168  // Wakeup the Process, if needed
169  return wakeup();
170 }
171 
173 {
174  Memory::Range range;
175  Arch::Cache cache;
176  Allocator::Range allocPhys, allocVirt;
177 
178  // Create new kernel event channel object
180  if (!m_kernelChannel)
181  {
182  ERROR("failed to allocate kernel event channel object");
183  return OutOfMemory;
184  }
185 
186  // Allocate two pages for the kernel event channel
187  allocPhys.address = 0;
188  allocPhys.size = PAGESIZE * 2;
189  allocPhys.alignment = PAGESIZE;
190 
191  if (Kernel::instance()->getAllocator()->allocate(allocPhys, allocVirt) != Allocator::Success)
192  {
193  ERROR("failed to allocate kernel event channel pages");
194  return OutOfMemory;
195  }
196 
197  // Initialize pages with zeroes
198  MemoryBlock::set((void *)allocVirt.address, 0, PAGESIZE*2);
199  cache.cleanData(allocVirt.address);
200  cache.cleanData(allocVirt.address + PAGESIZE);
201 
202  // Map data and feedback pages in userspace
203  range.phys = allocPhys.address;
205  range.size = PAGESIZE * 2;
208 
209  // Remap the feedback page with write permissions
211  m_memoryContext->map(range.virt + PAGESIZE,
213 
214  // Create shares entry
216  m_shares.createShare(KERNEL_PID, Kernel::instance()->getCoreInfo()->coreId, 0, range.virt, range.size);
217 
218  // Setup the kernel event channel
219  m_kernelChannel->setVirtual(allocVirt.address, allocVirt.address + PAGESIZE);
220 
221  return Success;
222 }
223 
225 {
226  // This process might be just about to call sleep().
227  // When another process is asking to wakeup this Process
228  // such that it can receive an IPC message, we must guarantee
229  // that the next sleep will be skipped.
230  m_wakeups++;
231 
232  if (m_state == Sleeping)
233  {
234  m_state = Ready;
236  return Success;
237  }
238  else
239  {
240  return WakeupPending;
241  }
242 }
243 
244 Process::Result Process::sleep(const Timer::Info *timer, bool ignoreWakeups)
245 {
246  if (m_state != Ready)
247  {
248  ERROR("PID " << m_id << " has invalid state: " << (uint) m_state);
249  return InvalidArgument;
250  }
251 
252  if (!m_wakeups || ignoreWakeups)
253  {
254  m_state = Sleeping;
255 
256  if (timer)
257  MemoryBlock::copy(&m_sleepTimer, timer, sizeof(m_sleepTimer));
258 
259  return Success;
260  }
261  m_wakeups = 0;
262  return WakeupPending;
263 }
264 
266 {
267  return proc->getID() == m_id;
268 }
Process::m_waitId
ProcessID m_waitId
Waits for exit of this Process.
Definition: Process.h:256
Process::m_memoryContext
MemoryContext * m_memoryContext
MMU memory context.
Definition: Process.h:271
MemoryBlock::copy
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Definition: MemoryBlock.cpp:36
Memory::Range
Memory range.
Definition: Memory.h:55
SplitAllocator.h
MemoryContext
Virtual memory abstract interface.
Definition: MemoryContext.h:42
Process::getState
State getState() const
Retrieves the current state.
Definition: Process.cpp:80
MemoryChannel::setVirtual
Result setVirtual(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by virtual address.
Definition: MemoryChannel.cpp:54
Process
Represents a process which may run on the host.
Definition: Process.h:44
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
Process::WakeupPending
@ WakeupPending
Definition: Process.h:60
Process::raiseEvent
Result raiseEvent(const struct ProcessEvent *event)
Raise kernel event.
Definition: Process.cpp:161
MemoryMap::UserStack
@ UserStack
< User stack
Definition: MemoryMap.h:58
Memory::Writable
@ Writable
Definition: Memory.h:42
Memory::User
@ User
Definition: Memory.h:44
Process::Ready
@ Ready
Definition: Process.h:68
Process::getID
ProcessID getID() const
Retrieve our ID number.
Definition: Process.cpp:60
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
MemoryContext::map
virtual Result map(Address virt, Address phys, Memory::Access access)=0
Map a physical page to a virtual address.
Process::~Process
virtual ~Process()
Destructor function.
Definition: Process.cpp:41
Process::isPrivileged
bool isPrivileged() const
Get privilege.
Definition: Process.cpp:100
Process::m_map
MemoryMap m_map
Virtual memory layout.
Definition: Process.h:268
Process::getParent
ProcessID getParent() const
Retrieve our parent ID.
Definition: Process.cpp:65
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
Process::m_waitResult
uint m_waitResult
Wait exit result of the other Process.
Definition: Process.h:259
MemoryMap::UserShare
@ UserShare
< User shared dynamic memory mappings
Definition: MemoryMap.h:60
Address
unsigned long Address
A memory address.
Definition: Types.h:131
Process.h
Process::m_sleepTimer
Timer::Info m_sleepTimer
Sleep timer value.
Definition: Process.h:281
Allocator::Range::address
Address address
Starting address of the memory range.
Definition: Allocator.h:67
MemoryBlock.h
Process::Success
@ Success
Definition: Process.h:56
Process::Process
Process(ProcessID id, Address entry, bool privileged, const MemoryMap &map)
Constructor function.
Definition: Process.cpp:26
MemoryContext::unmap
virtual Result unmap(Address virt)=0
Unmap a virtual address.
KERNEL_PID
#define KERNEL_PID
Definition: ProcessID.h:36
MemoryMap::UserData
@ UserData
< User program data from libexec, e.g.
Definition: MemoryMap.h:56
Allocator::Range::alignment
Size alignment
Alignment in bytes or ZERO for default alignment.
Definition: Allocator.h:69
Timer::Info
Timer information structure.
Definition: Timer.h:42
Process::wakeup
Result wakeup()
Prevent process from sleeping.
Definition: Process.cpp:224
Memory::Readable
@ Readable
Definition: Memory.h:41
uint
unsigned int uint
Unsigned integer number.
Definition: Types.h:44
Process::m_state
State m_state
Current process status.
Definition: Process.h:253
Process::getShares
ProcessShares & getShares()
Get process shares.
Definition: Process.cpp:85
Allocator::Range::size
Size size
Amount of memory in bytes.
Definition: Allocator.h:68
Process::stop
Result stop()
Stop execution of this process.
Definition: Process.cpp:137
Process::getMemoryContext
MemoryContext * getMemoryContext()
Get MMU memory context.
Definition: Process.cpp:95
Process::Result
Result
Result codes.
Definition: Process.h:54
Process::resume
Result resume()
Resume execution when this process is stopped.
Definition: Process.cpp:149
Process::OutOfMemory
@ OutOfMemory
Definition: Process.h:59
ProcessEvent
Represents a process which may run on the host.
Definition: ProcessEvent.h:40
Allocator::Success
@ Success
Definition: Allocator.h:55
Memory::Range::phys
Address phys
Physical address.
Definition: Memory.h:58
ARMCacheV6
ARMv6 cache management implementation.
Definition: ARMCacheV6.h:42
Process::m_wakeups
Size m_wakeups
Number of wakeups received.
Definition: Process.h:274
MemoryMap::range
Memory::Range range(Region region) const
Get memory range for the given region.
Definition: MemoryMap.cpp:36
Process::m_shares
ProcessShares m_shares
Contains virtual memory shares between this process and others.
Definition: Process.h:284
Process::InvalidArgument
@ InvalidArgument
Definition: Process.h:57
ProcessEvent.h
MemoryContext::findFree
virtual Result findFree(Size size, MemoryMap::Region region, Address *virt) const
Find unused memory.
Definition: MemoryContext.cpp:117
MemoryMap
Describes virtual memory map layout.
Definition: MemoryMap.h:38
Process::Stopped
@ Stopped
Definition: Process.h:71
WeakSingleton< Kernel >::instance
static Kernel * instance()
Retrieve the instance.
Definition: Singleton.h:86
Process::m_entry
Address m_entry
Entry point of the program.
Definition: Process.h:265
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
MemoryChannel
Unidirectional point-to-point channel using shared memory.
Definition: MemoryChannel.h:43
MemoryMap::UserPrivate
@ UserPrivate
< User private dynamic memory mappings
Definition: MemoryMap.h:59
Process::m_id
const ProcessID m_id
Process Identifier.
Definition: Process.h:247
Process::setParent
void setParent(ProcessID id)
Set parent process ID.
Definition: Process.cpp:105
Process::Waiting
@ Waiting
Definition: Process.h:70
Channel::Producer
@ Producer
Definition: Channel.h:58
MemoryChannel::flush
virtual Result flush()
Flush message buffers.
Definition: MemoryChannel.cpp:158
ProcessShares::createShare
Result createShare(ProcessShares &instance, MemoryShare *share)
Definition: ProcessShares.cpp:142
Process::Sleeping
@ Sleeping
Definition: Process.h:69
Allocator::Range
Describes a range of memory.
Definition: Allocator.h:65
Process::join
virtual Result join(const uint result)
Complete waiting for another Process.
Definition: Process.cpp:124
Process::initialize
virtual Result initialize()
Initialize the Process.
Definition: Process.cpp:172
Process::State
State
Represents the execution state of the Process.
Definition: Process.h:66
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
entry
u32 entry[]
Definition: IntelACPI.h:64
Process::sleep
Result sleep(const Timer::Info *timer, bool ignoreWakeups)
Stops the process for executing until woken up.
Definition: Process.cpp:244
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
MemoryChannel.h
MemoryMap::UserArgs
@ UserArgs
< Used for copying program arguments and file descriptors
Definition: MemoryMap.h:61
MemoryMap::UserHeap
@ UserHeap
< User heap
Definition: MemoryMap.h:57
Process::getWaitResult
uint getWaitResult() const
Get wait result.
Definition: Process.cpp:75
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
Process::operator==
bool operator==(Process *proc)
Compare two processes.
Definition: Process.cpp:265
MemoryContext::releaseSection
virtual Result releaseSection(const Memory::Range &range, const bool tablesOnly=false)=0
Release memory sections.
Process::getSleepTimer
const Timer::Info & getSleepTimer() const
Get sleep timer.
Definition: Process.cpp:90
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
Process::m_kernelChannel
MemoryChannel * m_kernelChannel
Channel for sending kernel events to the Process.
Definition: Process.h:287
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
coreId
u8 coreId
Definition: IntelACPI.h:64
Process::wait
Result wait(ProcessID id)
Let Process wait for other Process to terminate.
Definition: Process.cpp:110
MemoryContext::mapRangeContiguous
virtual Result mapRangeContiguous(Memory::Range *range)
Map a range of contiguous physical pages to virtual addresses.
Definition: MemoryContext.cpp:46
ProcessShares::setMemoryContext
Result setMemoryContext(MemoryContext *context)
Set MemoryContext.
Definition: ProcessShares.cpp:78
Process::getWait
ProcessID getWait() const
Get Wait ID.
Definition: Process.cpp:70
Process::m_privileged
bool m_privileged
Privilege level.
Definition: Process.h:262
ProcessShares
Manages memory shares for a Process.
Definition: ProcessShares.h:39
Process::m_parent
ProcessID m_parent
Parent process.
Definition: Process.h:250