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 }
ProcessManager::resume
Result resume(Process *proc)
Resume scheduling of the given Process.
Definition: ProcessManager.cpp:250
ProcessInfo
Process information structure, used for Info.
Definition: ProcessCtl.h:63
ProcessManager
Represents a process which may run on the host.
Definition: ProcessManager.h:44
API::Result
Result
Enumeration of generic kernel API result codes.
Definition: API.h:68
Process::getState
State getState() const
Retrieves the current state.
Definition: Process.cpp:80
Process
Represents a process which may run on the host.
Definition: Process.h:44
ProcessManager::reset
Result reset(Process *proc, const Address entry)
Restart execution of a Process at the given entry point.
Definition: ProcessManager.cpp:262
ProcessManager::create
Process * create(const Address entry, const MemoryMap &map, const bool readyToRun=false, const bool privileged=false)
Create a new Process.
Definition: ProcessManager.cpp:45
EnableIRQ
@ EnableIRQ
Definition: ProcessCtl.h:44
WatchIRQ
@ WatchIRQ
Definition: ProcessCtl.h:43
ProcessInfo::parent
ProcessID parent
Parent process id.
Definition: ProcessCtl.h:69
ProcessInfo::id
ProcessID id
Process Identity number.
Definition: ProcessCtl.h:66
WaitTimer
@ WaitTimer
Definition: ProcessCtl.h:50
Process::getID
ProcessID getID() const
Retrieve our ID number.
Definition: Process.cpp:60
SendIRQ
@ SendIRQ
Definition: ProcessCtl.h:46
Resume
@ Resume
Definition: ProcessCtl.h:55
ProcessManager::sleep
Result sleep(const Timer::Info *timer=0, const bool ignoreWakeups=false)
Let current Process sleep until a timer expires or wakeup occurs.
Definition: ProcessManager.cpp:274
Process::getParent
ProcessID getParent() const
Retrieve our parent ID.
Definition: Process.cpp:65
ProcessCtlHandler
API::Result ProcessCtlHandler(const ProcessID procID, const ProcessOperation action, const Address addr, const Address output)
Kernel handler prototype.
Definition: ProcessCtl.cpp:27
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
Wakeup
@ Wakeup
Definition: ProcessCtl.h:53
Address
unsigned long Address
A memory address.
Definition: Types.h:131
ProcessManager::wakeup
Result wakeup(Process *proc)
Take Process out of Sleep state and mark ready for execution.
Definition: ProcessManager.cpp:306
Reset
@ Reset
Definition: ProcessCtl.h:56
ProcessManager::wait
Result wait(Process *proc)
Let current Process wait for another Process to terminate.
Definition: ProcessManager.cpp:219
Timer::Info
Timer information structure.
Definition: Timer.h:42
Timer
Represents a configurable timer device.
Definition: Timer.h:35
Kernel::sendIRQ
virtual Result sendIRQ(const uint coreId, const uint irq)
Send a inter-processor-interrupt (IPI) to another core.
Definition: Kernel.cpp:179
Kernel::getProcessManager
ProcessManager * getProcessManager()
Get process manager.
Definition: Kernel.cpp:143
Log.h
Log
Logging class.
Definition: Log.h:96
API::IOError
@ IOError
Definition: API.h:76
WaitPID
@ WaitPID
Definition: ProcessCtl.h:48
ARMMap
Memory mapping for the kernel and user processes on the ARM architecture.
Definition: ARMMap.h:37
SELF
#define SELF
Definition: ProcessID.h:35
Log::append
void append(const char *str)
Append to buffered output.
Definition: Log.cpp:53
InfoTimer
@ InfoTimer
Definition: ProcessCtl.h:49
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
InfoPID
@ InfoPID
Definition: ProcessCtl.h:47
ProcessManager::Success
@ Success
Definition: ProcessManager.h:53
ProcessManager::stop
Result stop(Process *proc)
Remove given Process from the Scheduler.
Definition: ProcessManager.cpp:230
ProcessInfo::state
Process::State state
Defines the current state of the Process.
Definition: ProcessCtl.h:72
GetPID
@ GetPID
Definition: ProcessCtl.h:41
Kernel::enableIRQ
virtual void enableIRQ(u32 irq, bool enabled)
Enable or disable an hardware interrupt (IRQ).
Definition: Kernel.cpp:168
WeakSingleton< Kernel >::instance
static Kernel * instance()
Retrieve the instance.
Definition: Singleton.h:86
ProcessManager::schedule
Result schedule()
Schedule next process to run.
Definition: ProcessManager.cpp:155
EnterSleep
@ EnterSleep
Definition: ProcessCtl.h:51
ProcessManager::get
Process * get(const ProcessID id)
Retrieve a Process by it's ID.
Definition: ProcessManager.cpp:95
API::NotFound
@ NotFound
Definition: API.h:73
ProcessOperation
ProcessOperation
Available operation to perform using ProcessCtl.
Definition: ProcessCtl.h:37
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
ProcessManager::remove
void remove(Process *proc, const uint exitStatus=0)
Remove a Process.
Definition: ProcessManager.cpp:100
Schedule
@ Schedule
Definition: ProcessCtl.h:52
API::Success
@ Success
Definition: API.h:70
Process::getWaitResult
uint getWaitResult() const
Get wait result.
Definition: Process.cpp:75
Spawn
@ Spawn
Definition: ProcessCtl.h:39
operator<<
Log & operator<<(Log &log, ProcessOperation op)
Operator to print a ProcessOperation to a Log.
Definition: ProcessCtl.cpp:185
ProcessCtl.h
ProcessManager::current
Process * current()
Current process running.
Definition: ProcessManager.cpp:203
Kernel::getTimer
Timer * getTimer()
Get Timer.
Definition: Kernel.cpp:163
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
DisableIRQ
@ DisableIRQ
Definition: ProcessCtl.h:45
Timer::getCurrent
virtual Result getCurrent(Info *info, const Size msecOffset=0)
Get current timer info.
Definition: Timer.cpp:44
KillPID
@ KillPID
Definition: ProcessCtl.h:40
ProcessManager::registerInterruptNotify
Result registerInterruptNotify(Process *proc, const u32 vector)
Register an interrupt notification for a Process.
Definition: ProcessManager.cpp:344
GetParent
@ GetParent
Definition: ProcessCtl.h:42
Stop
@ Stop
Definition: ProcessCtl.h:54