Max OS 0.3
Loading...
Searching...
No Matches
scheduler_resources.cpp
1
11#include <processes/scheduler.h>
12
13using namespace MaxOS;
14using namespace MaxOS::processes;
15using namespace MaxOS::processes::resources;
16using namespace MaxOS::memory;
17using namespace MaxOS::common;
18using namespace MaxOS::KPI::processes;
19
20ProcessResource::ProcessResource(string const& name, size_t flags, resource_type_t type)
21: Resource(name, flags, type)
22{
23
24}
25
36
46int ProcessResource::read(void* buffer, size_t size, size_t flags) {
47
48 // Process not found (allow reading stats only to get exit code)
49 if(!process && flags != (size_t)ProcessFlags::READ_STATS)
50 return -1;
51
52 switch ((ProcessFlags)flags) {
53
54 case ProcessFlags::READ_STATS: {
55
56 // Check bounds
57 if(size < sizeof(process_stats_t))
58 return -1;
59
60 // Get the info
61 process_stats_t stats = {};
62 if(process) {
63 stats.pid = process->pid();
64 stats.parent_pid = 0; //TODO: store parent pid
65 stats.thread_count = process->threads().size();
66 stats.total_ticks = process->total_ticks();
67 stats.memory_usage = 0; //process->memory_manager->memory_used(); TODO: boken?
68 stats.handle_count = process->resource_manager.resources().size();
69 }
70 stats.exit_code = exit_code;
71
72 // Copy across
73 memcpy(buffer, &stats, sizeof(process_stats_t));
74 return sizeof(process_stats_t);
75
76 }
77
78 case ProcessFlags::READ_ENVIRONMENT: {
79
80 // Check bounds
81 if(size < sizeof(process_environment_t))
82 return -1;
83
84 // Get the info
85 process_environment_t info;
86 info.args = 0;
87 info.arg_count = 0; //TODO: store
88 info.env_vars = 0; //TODO: implement
89 info.env_var_count = 0;
90 info.working_directory = (const char*)MemoryManager::malloc(process->working_directory.length() + 1);
91 info.executable_path = 0;// TODO: store
92
93 // Copy the info
94 // .. args
95 // .. env vars
96 memcpy((void*)info.working_directory, process->working_directory.c_str(), process->working_directory.length() + 1);
97 // .. executable path
98
99 // Copy across
100 memcpy(buffer, &info, sizeof(process_environment_t));
101 return sizeof(process_environment_t);
102
103 }
104
105
106 case ProcessFlags::READ_HANDLES: {
107
108 // Check bounds
109 size_t size_needed = sizeof(handle_info_t) * process->resource_manager.resources().size();
110 if(size < size_needed)
111 return -1;
112
113 for(const auto& resource : process->resource_manager.resources()) {
114
115 // Get the info
116 handle_info_t handle_info;
117 handle_info.handle = resource.first;
118 handle_info.type = resource.second->type();
119 handle_info.name = (const char*)MemoryManager::malloc(resource.second->name().length() + 1);
120 memcpy((void*)handle_info.name, resource.second->name().c_str(), resource.second->name().length() + 1);
121
122 // Copy across
123 memcpy(buffer, &handle_info, sizeof(handle_info_t));
124 buffer = (void*)((uintptr_t)buffer + sizeof(handle_info_t));
125 }
126
127 return (int)size_needed;
128
129 }
130
131 default:
132 return -1;
133 }
134}
135
145int ProcessResource::write(const void* buffer, size_t size, size_t flags) {
146
147 // Process not found
148 if(!process)
149 return -1;
150
151 switch ((ProcessFlags)flags) {
152
153 case ProcessFlags::WRITE_CHANGE_DIRECTORY: {
154
155 // Change the working directory
156 string new_directory = string((const char*)buffer);
157 process->working_directory = new_directory;
158 return size;
159 }
160
161 case ProcessFlags::WRITE_KILL: {
162
163 // Kill the process
164 exit_code = *((uint64_t*)buffer);
166 process->threads()[0]->yield();
167
168 return size;
169 }
170
171 default:
172 return -1;
173 }
174}
175
176ProcessResource::~ProcessResource() = default;
177
178
179ThreadResource::ThreadResource(string const& name, size_t flags, resource_type_t type)
180: Resource(name, flags, type)
181{
182
183}
184
190void ThreadResource::close(size_t flags) {
191
192 thread->thread_state = ThreadState::STOPPED;
193}
194
204int ThreadResource::read(void* buffer, size_t size, size_t flags) {
205
206 // Thread not found
207 if(!thread && flags != (size_t)ThreadFlags::READ_STATS)
208 return -1;
209
210 switch ((ThreadFlags)flags) {
211
212 case ThreadFlags::READ_STATS: {
213
214 // Check bounds
215 if(size < sizeof(thread_stats_t))
216 return -1;
217
218 // Get the info
219 thread_stats_t stats = {};
220
221 if(thread) {
222 stats.tid = thread->tid;
223 stats.pid = thread->parent_pid;
224 stats.ticks = thread->ticks;
225 stats.state = (size_t)thread->thread_state;
226 stats.wakeup_time_ms = thread->wakeup_time;
227 }
228 stats.exit_code = exit_code;
229
230 // Copy across
231 memcpy(buffer, &stats, sizeof(thread_stats_t));
232 return sizeof(thread_stats_t);
233
234 }
235
236 default:
237 return -1;
238
239 }
240
241}
242
252int ThreadResource::write(const void* buffer, size_t size, size_t flags) {
253
254 // Thread not found
255 if(!thread)
256 return -1;
257
258 switch ((ThreadFlags)flags) {
259
260 case ThreadFlags::WRITE_SLEEP_TIME: {
261
262 // Set the sleep time
263 uint64_t sleep_time = *((uint64_t*)buffer);
264 thread->sleep(sleep_time);
265 return size;
266 }
267
268 case ThreadFlags::WRITE_KILL: {
269
270 // Kill the thread
271 exit_code = *((uint64_t*)buffer);
272 thread->thread_state = ThreadState::STOPPED;
273 thread->yield();
274 return size;
275 }
276
277 case ThreadFlags::WRITE_YIELD: {
278 thread->yield();
279 return size;
280 }
281
282 case ThreadFlags::WRITE_ENABLE_PORT_IO: {
283 uint64_t port = *((uint64_t*)buffer);
284 thread->enable_port(port);
285 return size;
286 }
287
288 case ThreadFlags::WRITE_DISABLE_PORT_IO: {
289 uint64_t port = *((uint64_t*)buffer);
290 thread->disable_port(port);
291 return size;
292 }
293
294 default:
295 return -1;
296 }
297
298}
299
300ThreadResource::~ThreadResource() = default;
301
302ThreadResourceRegistry::ThreadResourceRegistry()
304{
305
306}
307
316Resource* ThreadResourceRegistry::create_resource(string const& name, size_t flags, uintptr_t data) {
317
318 return ResourceRegistry::create_resource(name, flags, data);
319}
320
322
323 // Resource already opened
324 auto resource = BaseResourceRegistry::get_resource(name);
325 if(resource != nullptr)
326 return resource;
327
328 // Get the thread
329 uint64_t tid = name.to_int();
330 auto thread = name == "this" ? GlobalScheduler::current_thread() : GlobalScheduler::get_thread(tid);
331
332 // Self refrence may already be open
333 resource = BaseResourceRegistry::get_resource(string(thread -> tid));
334 if(resource != nullptr)
335 return resource;
336
337 // Create the resource
338 auto thread_resource = new ThreadResource(string(thread -> tid), 0, resource_type_t::PROCESS);
339 thread_resource->thread = thread;
340
341 register_resource(thread_resource);
342 return thread_resource;
343}
344
345ThreadResourceRegistry::~ThreadResourceRegistry() = default;
346
347ProcessResourceRegistry::ProcessResourceRegistry()
349{
350
351}
352
362Resource* ProcessResourceRegistry::create_resource(string const& name, size_t flags, uintptr_t data) {
363
364 // Get the command
365 auto command = (execute_command_t*)data;
366 if (!command)
367 return nullptr;
368
369 // Kernel copy (@todo copy the data page into the new process so dont get unmapped error and also thus dont need a copy)
370 auto exec_buffer = buffer_t(command->file_data_size);
371 exec_buffer.copy_from(command->file_data, command->file_data_size);
372
373 // Copy the args into userspace (@todo bad, two copies)
374 uint64_t argc = command->args_count;
375 size_t arg_size = argc * sizeof(void*);
376 void* argv = MemoryManager::kmalloc(arg_size);
377 for (int i = 0; i < argc; i++) {
378
379 // Copy each argument
380 size_t len = strlen(((char**)command->args)[i]) + 1;
381 ((char**)argv)[i] = (char*) MemoryManager::kmalloc(len);
382 memcpy((void*) ((char**)argv)[i], (void*) ((char**)command->args)[i], len);
383 }
384
385 // Load the elf
386 auto elf = new ELF64((uintptr_t)exec_buffer.raw());
387 if (!elf->is_valid())
388 return nullptr;
389
390 // Create the processs
391 auto process = new Process(name, argv, argc, elf);
392 GlobalScheduler::system_scheduler() -> add_process(process);
393
394 // Create the resource
395 auto resource = new ProcessResource(name, flags, resource_type_t::PROCESS);
396 resource->process = process;
397
398 // Clean up
399 // for (int i = 0; i < argc; i++)
400 // delete ((char**)argv)[i];
401 // delete argv;
402
403
404 // Switch back to the caller proc
405 MemoryManager::switch_active_memory_manager(GlobalScheduler::current_process()->memory_manager);
406 return resource;
407}
408
418
419 // Resource already opened
420 auto resource = BaseResourceRegistry::get_resource(name);
421 if(resource != nullptr)
422 return resource;
423
424 // Get the process
425 uint64_t pid = name.to_int();
426 auto process = name == "this" ? GlobalScheduler::current_process() : GlobalScheduler::get_process(pid);
427
428 // Self refrence may already be open
429 resource = BaseResourceRegistry::get_resource(string(process -> pid()));
430 if(resource != nullptr)
431 return resource;
432
433 // Create the resource
434 auto process_resource = new ProcessResource(string(process -> pid()), 0, resource_type_t::PROCESS);
435 process_resource->process = process;
436
437 register_resource(process_resource);
438 return process_resource;
439}
440
441ProcessResourceRegistry::~ProcessResourceRegistry() = default;
static void * malloc(size_t size)
Allocates a block of memory in the current USERSPACE heap.
static void * kmalloc(size_t size)
Allocates a block of memory in the KERNEL space.
Handles the loading and parsing of 64-bit ELF files.
Definition elf.h:217
static Process * get_process(uint64_t pid)
Gets a process on the currently executing core by its PID.
static uint64_t remove_process(Process *process)
Removes a process from the scheduler if the process has no threads, if it does then the threads are s...
static GlobalScheduler * system_scheduler()
Gets the system scheduler.
Definition scheduler.cpp:55
static Process * current_process()
Gets the process on the currently executing core.
static Thread * get_thread(uint64_t tid)
Gets a thread on the currently executing core by its TID.
static Thread * current_thread()
Gets the thread on the currently executing core.
A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address ...
Definition process.h:94
uint64_t pid() const
Gets the pid of the process.
Definition process.cpp:429
uint64_t total_ticks()
Gets the total ticks of the threads in the process (not this does not include any past killed threads...
Definition process.cpp:439
resources::ResourceManager resource_manager
The manger for resources used by this process.
Definition process.h:122
common::Vector< Thread * > threads()
Gets the threads of the process.
Definition process.cpp:419
string working_directory
The working directory of the process.
Definition process.h:119
void enable_port(uint64_t port)
Sets bits in the threads TSS to allow a port for I/O.
Definition process.cpp:247
uint64_t parent_pid
The parent process ID.
Definition process.h:69
uint64_t tid
The thread ID.
Definition process.h:68
void yield()
Pass execution to the next ready thread.
Definition process.cpp:103
volatile size_t ticks
The number of ticks the thread has run for.
Definition process.h:74
void disable_port(uint64_t port)
Sets bits in the threads TSS to disallow a port for I/O.
Definition process.cpp:258
volatile thread_state_t thread_state
The current state of the thread.
Definition process.h:72
volatile size_t wakeup_time
The time at which the thread should wake up (if sleeping)
Definition process.h:75
void sleep(size_t milliseconds)
Sleeps the thread for a certain amount of time.
Definition process.cpp:92
virtual Resource * get_resource(const string &name)
Gets a resource from the registry by name.
Definition resource.cpp:52
bool register_resource(Resource *resource)
Registers a resource in the registry.
Definition resource.cpp:76
Resource * get_resource(const string &name) final
The.
Resource * create_resource(const string &name, size_t flags, uintptr_t data) final
Opens an executable.
A wrapper for a Process which exposes Process operations as Resource operations.
int write(const void *buffer, size_t size, size_t flags) final
Writes data to the process resource.
Process * process
The process that this resource handles & exposes.
uint64_t exit_code
The exit code of the process once it has exited.
void close(size_t flags) final
Closes the process resource, killing the process and removing it from the scheduler.
int read(void *buffer, size_t size, size_t flags) final
Reads data from the process resource.
common::Map< uint64_t, Resource * > resources()
Get the resources currently open.
Definition resource.cpp:223
A resource registry for a specific resource type.
Definition resource.h:61
Resource * create_resource(const string &name, size_t flags, uintptr_t data) override
Create a new resource of the specific type.
Definition resource.h:74
Resource * create_resource(const string &name, size_t flags, uintptr_t data) final
td
Resource * get_resource(const string &name) final
Gets a resource from the registry by name.
A wrapper for a Thread which exposes Thread operations as Resource operations.
void close(size_t flags) final
Closes the thread resource, marking the thread to be removed by the scheduler.
uint64_t exit_code
The exit code of the thread once it has exited.
int read(void *buffer, size_t size, size_t flags) final
Reads data from the thread resource.
int write(const void *buffer, size_t size, size_t flags) final
Writes data to the thread resource.
Thread * thread
The thread that this resource handles & exposes.
KPI::Resource Resource
Alias to make the libsyscore Resource accessible here.
Definition resource.h:26
KPI::ResourceType resource_type_t
Alias to make the libsyscore ResourceType accessible here.
Definition resource.h:25
Defines a GlobalScheduler and Scheduler for managing processes and threads.
Defines scheduler resource classes for wrapping Processe and Thread objects as Resources in the Globa...