FreeNOS
ProcessCtl.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009 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/Kernel.h>
20#include <FreeNOS/Config.h>
21#include <FreeNOS/Process.h>
22#include <FreeNOS/ProcessEvent.h>
23#include <FreeNOS/ProcessManager.h>
24#include <Log.h>
25#include "ProcessCtl.h"
26
28 const ProcessOperation action,
29 const Address addr,
30 const Address output)
31{
32 const Arch::MemoryMap map;
33 Process *proc = ZERO;
34 ProcessInfo *info = (ProcessInfo *) addr;
36 Timer *timer;
37
38 DEBUG("#" << procs->current()->getID() << " " << action << " -> " << procID << " (" << addr << ")");
39
40 // Does the target process exist?
41 if(action != GetPID && action != Spawn)
42 {
43 if (procID == SELF)
44 proc = procs->current();
45 else if (!(proc = procs->get(procID)))
46 return API::NotFound;
47 }
48 // Handle request
49 switch (action)
50 {
51 case Spawn:
52 proc = procs->create(addr, map);
53 if (!proc)
54 {
55 ERROR("failed to create process");
56 return API::IOError;
57 }
58 return (API::Result) (API::Success | (proc->getID() << 16));
59
60 case KillPID:
61 procs->remove(proc, addr); // Addr contains the exit status
62
63 if (procID == SELF)
64 procs->schedule();
65 break;
66
67 case GetPID:
68 return (API::Result) procs->current()->getID();
69
70 case GetParent:
71 return (API::Result) procs->current()->getParent();
72
73 case Schedule:
74 procs->schedule();
75 break;
76
77 case Stop:
78 if (procs->stop(proc) != ProcessManager::Success)
79 {
80 ERROR("failed to stop PID " << proc->getID());
81 return API::IOError;
82 }
83 if (procID == SELF)
84 {
85 procs->schedule();
86 }
87 break;
88
89 case Resume:
90 if (procs->resume(proc) != ProcessManager::Success)
91 {
92 ERROR("failed to resume PID " << proc->getID());
93 return API::IOError;
94 }
95 break;
96
97 case Reset:
98 if (procs->reset(proc, addr) != ProcessManager::Success)
99 {
100 ERROR("failed to reset PID " << proc->getID());
101 return API::IOError;
102 }
103 break;
104
105 case Wakeup:
106 // increment wakeup counter and set process ready
107 if (procs->wakeup(proc) != ProcessManager::Success)
108 {
109 ERROR("failed to wakeup process ID " << proc->getID());
110 return API::IOError;
111 }
112 break;
113
114 case WatchIRQ:
115 if (procs->registerInterruptNotify(proc, addr) != ProcessManager::Success)
116 {
117 ERROR("failed to register IRQ #" << addr << " to process ID " << proc->getID());
118 return API::IOError;
119 }
120 break;
121
122 case EnableIRQ:
123 Kernel::instance()->enableIRQ(addr, true);
124 break;
125
126 case DisableIRQ:
127 Kernel::instance()->enableIRQ(addr, false);
128 break;
129
130 case SendIRQ:
131 Kernel::instance()->sendIRQ(addr >> 16, addr & 0xffff);
132 break;
133
134 case InfoPID:
135 info->id = proc->getID();
136 info->state = proc->getState();
137 info->parent = proc->getParent();
138 break;
139
140 case WaitPID:
141 if (procs->wait(proc) != ProcessManager::Success)
142 {
143 ERROR("failed to wait for Process ID " << proc->getID());
144 return API::IOError;
145 }
146 procs->schedule();
147
148 // contains the exit status of the other process.
149 // Note that only the Intel code has kernel stacks.
150 // For ARM, the kernel continues executing here even after
151 // the schedule() is done. For ARM, the actual wait result is
152 // injected directly in the saved CPU registers.
153 //
154 // Note that the API::Result is stored in the lower 16-bit of the
155 // return value and the process exit status is stored in the upper 16 bits.
156 return (API::Result) ((API::Success) | (procs->current()->getWaitResult() << 16));
157
158 case InfoTimer:
159 if (!(timer = Kernel::instance()->getTimer()))
160 return API::NotFound;
161
162 timer->getCurrent((Timer::Info *) addr);
163 break;
164
165 case WaitTimer:
166 // Process is only allowed to continue execution after the sleep timer expires
167 if (procs->sleep((const Timer::Info *)addr, true) != ProcessManager::Success)
168 {
169 ERROR("sleep failed on process ID " << procs->current()->getID());
170 return API::IOError;
171 }
172 procs->schedule();
173 break;
174
175 case EnterSleep:
176 // Only sleeps the process if no pending wakeups
177 if (procs->sleep((const Timer::Info *)addr) == ProcessManager::Success)
178 procs->schedule();
179 break;
180 }
181
182 return API::Success;
183}
184
186{
187 switch (op)
188 {
189 case Spawn: log.append("Spawn"); break;
190 case KillPID: log.append("KillPID"); break;
191 case GetPID: log.append("GetPID"); break;
192 case GetParent: log.append("GetParent"); break;
193 case WatchIRQ: log.append("WatchIRQ"); break;
194 case EnableIRQ: log.append("EnableIRQ"); break;
195 case DisableIRQ:log.append("DisableIRQ"); break;
196 case InfoPID: log.append("InfoPID"); break;
197 case WaitPID: log.append("WaitPID"); break;
198 case InfoTimer: log.append("InfoTimer"); break;
199 case EnterSleep: log.append("EnterSleep"); break;
200 case Schedule: log.append("Schedule"); break;
201 case Wakeup: log.append("Wakeup"); break;
202 default: log.append("???"); break;
203 }
204 return log;
205}
Result
Enumeration of generic kernel API result codes.
Definition API.h:69
@ NotFound
Definition API.h:73
@ IOError
Definition API.h:76
@ Success
Definition API.h:70
Memory mapping for the kernel and user processes on the ARM architecture.
Definition ARMMap.h:38
virtual Result sendIRQ(const uint coreId, const uint irq)
Send a inter-processor-interrupt (IPI) to another core.
Definition Kernel.cpp:179
Timer * getTimer()
Get Timer.
Definition Kernel.cpp:163
virtual void enableIRQ(u32 irq, bool enabled)
Enable or disable an hardware interrupt (IRQ).
Definition Kernel.cpp:168
ProcessManager * getProcessManager()
Get process manager.
Definition Kernel.cpp:143
Logging class.
Definition Log.h:97
void append(const char *str)
Append to buffered output.
Definition Log.cpp:53
Represents a process which may run on the host.
Result reset(Process *proc, const Address entry)
Restart execution of a Process at the given entry point.
Result registerInterruptNotify(Process *proc, const u32 vector)
Register an interrupt notification for a Process.
Result resume(Process *proc)
Resume scheduling of the given Process.
Result sleep(const Timer::Info *timer=0, const bool ignoreWakeups=false)
Let current Process sleep until a timer expires or wakeup occurs.
Result wait(Process *proc)
Let current Process wait for another Process to terminate.
Process * create(const Address entry, const MemoryMap &map, const bool readyToRun=false, const bool privileged=false)
Create a new Process.
Result wakeup(Process *proc)
Take Process out of Sleep state and mark ready for execution.
void remove(Process *proc, const uint exitStatus=0)
Remove a Process.
Result stop(Process *proc)
Remove given Process from the Scheduler.
Result schedule()
Schedule next process to run.
Process * get(const ProcessID id)
Retrieve a Process by it's ID.
Process * current()
Current process running.
Represents a process which may run on the host.
Definition Process.h:45
uint getWaitResult() const
Get wait result.
Definition Process.cpp:75
State getState() const
Retrieves the current state.
Definition Process.cpp:80
ProcessID getID() const
Retrieve our ID number.
Definition Process.cpp:60
ProcessID getParent() const
Retrieve our parent ID.
Definition Process.cpp:65
Represents a configurable timer device.
Definition Timer.h:36
virtual Result getCurrent(Info *info, const Size msecOffset=0)
Get current timer info.
Definition Timer.cpp:44
static Kernel * instance()
Retrieve the instance.
Definition Singleton.h:86
API::Result ProcessCtlHandler(const ProcessID procID, const ProcessOperation action, const Address addr, const Address output)
Kernel handler prototype.
#define SELF
Definition ProcessID.h:35
ProcessOperation
Available operation to perform using ProcessCtl.
Definition ProcessCtl.h:38
Log & operator<<(Log &log, ProcessOperation op)
Operator to print a ProcessOperation to a Log.
@ Resume
Definition ProcessCtl.h:55
@ WatchIRQ
Definition ProcessCtl.h:43
@ GetParent
Definition ProcessCtl.h:42
@ EnterSleep
Definition ProcessCtl.h:51
@ WaitTimer
Definition ProcessCtl.h:50
@ WaitPID
Definition ProcessCtl.h:48
@ SendIRQ
Definition ProcessCtl.h:46
@ InfoPID
Definition ProcessCtl.h:47
@ Reset
Definition ProcessCtl.h:56
@ Spawn
Definition ProcessCtl.h:39
@ KillPID
Definition ProcessCtl.h:40
@ InfoTimer
Definition ProcessCtl.h:49
@ DisableIRQ
Definition ProcessCtl.h:45
@ GetPID
Definition ProcessCtl.h:41
@ Schedule
Definition ProcessCtl.h:52
@ EnableIRQ
Definition ProcessCtl.h:44
@ Stop
Definition ProcessCtl.h:54
@ Wakeup
Definition ProcessCtl.h:53
u32 ProcessID
Process Identification Number.
Definition Types.h:140
unsigned long Address
A memory address.
Definition Types.h:131
#define ERROR(msg)
Output an error message.
Definition Log.h:61
#define ZERO
Zero value.
Definition Macros.h:43
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
Process information structure, used for Info.
Definition ProcessCtl.h:64
Process::State state
Defines the current state of the Process.
Definition ProcessCtl.h:72
ProcessID id
Process Identity number.
Definition ProcessCtl.h:66
ProcessID parent
Parent process id.
Definition ProcessCtl.h:69
Timer information structure.
Definition Timer.h:43