Commit d7aa43cf12f9172a743c37c4b30fd48522eb006d

Implement virtual address space class and much multitasking
infrastructure
  
104104 fs_root = initrd::initialise(initrd_address);
105105
106106 // Start multitasking
107 multitasking::initialise();
107 //multitasking::initialise();
108108 }
109109
110110 void start_error()
  
1/*
2 * Copyright (c) 2008 Stephen Gentle
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16
17#include "virtual_address_space.h"
18#include "common.h"
19
20virtual_address_space::virtual_address_space()
21{
22}
23
24virtual_address_space::virtual_address_space(paging::page_directory_t * dir, heap::heap * addr_heap)
25 : m_page_directory(dir), m_heap(addr_heap)
26{
27}
28
29virtual_address_space::~virtual_address_space()
30{
31}
  
1/*
2 * Copyright (c) 2008 Stephen Gentle
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16
17#ifndef ADDRESS_SPACE_H
18#define ADDRESS_SPACE_H
19
20#include "common.h"
21#include "paging.h"
22
23#include "mm/kheap.h"
24
25class virtual_address_space
26{
27public:
28 // Default constructor
29 virtual_address_space();
30
31 // Constructor that sets page directory and heap
32 virtual_address_space(paging::page_directory_t * dir, heap::heap * addr_heap);
33
34 // Deconstructor
35 ~virtual_address_space();
36
37 // Set the page directory of this address space to an existing one
38 void set_page_directory(paging::page_directory_t * directory)
39 {
40 m_page_directory = directory;
41 }
42
43 paging::page_directory * get_page_directory()
44 {
45 return m_page_directory;
46 }
47
48private:
49 // This address space's page directory
50 paging::page_directory_t * m_page_directory;
51
52 // This address space's heap
53 heap::heap * m_heap;
54};
55
56
57#endif
  
1717#include "process/process.h"
1818#include "process/scheduler.h"
1919
20Process::Process()
20process::process()
2121 : m_id(0), m_threads(), m_desc()
2222{
2323 m_id = scheduler::add_process(this);
2424}
2525
26Process::Process(Process * parent)
26process::process(process * parent)
2727 : m_id(0), m_threads(), m_desc()
2828{
2929 m_id = scheduler::add_process(this);
3232 m_desc = parent->m_desc;// + "[F]";
3333}
3434
35Process::~Process()
35process::~process()
3636{
3737 scheduler::remove_process(this);
3838}
3939
40size_t Process::add_thread(Thread * t)
40size_t process::add_thread(thread * t)
4141{
4242 // Add the thread onto the thread vector
4343 m_threads.push_back(t);
4444
45 // Add the thread to the scheduler's queue
46 scheduler::add_thread(t);
47
4548 // Return the thread's ID
4649 return t->get_id();
4750}
4851
49void Process::remove_thread(Thread * t)
52void process::remove_thread(thread * t)
5053{
51 if(t != NULL)
54 // Check that t is not null
55 if(t == NULL)
56 {
5257 return;
58 }
59
60 // Remove the thread from the scheduler
61 scheduler::remove_thread(t);
5362}
  
2020#include "common.h"
2121#include "string.h"
2222#include "vector.h"
23
2324#include "process/thread.h"
25#include "mm/virtual_address_space.h"
2426
2527using namespace std;
2628
27class Process
29class process
2830{
2931public:
3032 // Create a normal process
31 Process();
33 process();
3234
3335 // Fork a process from another
34 Process(Process * parent);
36 process(process * parent);
3537
3638 // Destroy this process and remove it from the scheduler
37 ~Process();
39 ~process();
3840
3941 // Add a thread to this process. Returns ID assigned to thread
40 size_t add_thread(Thread * t);
42 size_t add_thread(thread * t);
4143
4244 // Remove a thread from this process
43 void remove_thread(Thread * t);
45 void remove_thread(thread * t);
4446
4547 // Kill the process
4648 void kill();
5151 size_t get_id() { return m_id; };
5252
5353 // Get this thread's parent
54 Process * get_parent() { return m_parent; };
54 process * get_parent() { return m_parent; };
5555
56 // Return this process' virtual address space
57 virtual_address_space * get_address_space()
58 {
59 return m_address_space;
60 }
61
62 void set_address_space(virtual_address_space * addr)
63 {
64 m_address_space = addr;
65 }
66
5667private:
5768 // The process ID
5869 size_t m_id;
5970
71 // This process' address space
72 virtual_address_space * m_address_space;
73
6074 // The threads that this process contains
61 vector<Thread *> m_threads;
75 vector<thread *> m_threads;
6276
6377 // The parent of this process
64 Process * m_parent;
78 process * m_parent;
6579
6680 // Description of this process
6781 std::string m_desc;
  
1515 */
1616
1717#include "scheduler.h"
18#include "task.h"
1819#include "timer.h"
1920
21// The current thread.
22thread * current_thread = NULL;
23
2024namespace scheduler
2125{
22 vector<Process *> m_processes;
23 vector<Thread *> m_threads;
26 // Vectors for storing the threads and processes the scheduler will use
27 vector<process *> m_processes;
28 vector<thread *> m_threads;
2429
30 // Keep track of process IDs
31 size_t process_id = 0;
32
2533 void schedule()
2634 {
27 // TODO: Implement
35 // If we haven't set up multitasking yet, just exit early
36 if(current_thread == NULL)
37 {
38 return;
39 }
40
41 // Read the esp, ebp registers
42 uintptr esp, ebp, eip;
43
44 esp = multitasking::read_esp();
45 ebp = multitasking::read_ebp();
46
47 // Get the current instruction pointer.
48 eip = read_eip();
49
50 // If we just executed read_eip, then eip will contain the correct value. We may
51 // have just switched tasks though, and jumped to this address, and in that case
52 // we would have just executed switch_task. We'll set the value to 0x12345 later
53 // on so we know what is happenning now
54 if(eip == 0x12345)
55 {
56 return;
57 }
58
59 // Save the registers
60 current_thread->set_eip(eip);
61 current_thread->set_stack_ptr(esp, ebp);
62
63 // TODO: Get next task in vector
64
65 // Switch tasks
66 multitasking::switch_tasks(eip, esp, ebp, current_thread->get_parent()->get_address_space());
2867 }
2968
30 size_t add_process(Process * p)
69 size_t add_process(process * p)
3170 {
3271 // Make sure [p] is not null
3372 if(p == NULL)
7777 // Add the process to the scheduler's vector
7878 m_processes.push_back(p);
7979
80 // TODO: Assign thread ID?
81
82 return p->get_id();
80 return ++process_id;
8381 }
8482
85 void remove_process(Process * p)
83 void remove_process(process * p)
8684 {
8785 // Make sure [p] is not null
8886 if(p == NULL)
9191 // TODO: Implement
9292 }
9393
94 void add_thread(Thread * t)
94 void add_thread(thread * t)
9595 {
9696 // Check that [t] is not null
9797 if(t == NULL)
103103 m_threads.push_back(t);
104104 }
105105
106 void remove_thread(Thread * t)
106 void remove_thread(thread * t)
107107 {
108108 // Check [t] is not null
109109 if(t == NULL)
  
2626 void schedule();
2727
2828 // Add a process to the scheduler and return its pid
29 size_t add_process(Process * p);
29 size_t add_process(process * p);
3030
3131 // Remove a process from the scheduler
32 void remove_process(Process * p);
32 void remove_process(process * p);
3333
3434 // Add a thread to the scheduler
35 void add_thread(Thread * t);
35 void add_thread(thread * t);
3636
3737 // Remove a thread from the scheduler
38 void remove_thread(Thread * t);
38 void remove_thread(thread * t);
3939
4040 // Sleep the current task for a certian amount of time
4141 void sleep(size_t t);
  
2222
2323extern uintptr initial_esp;
2424extern paging::page_directory_t * current_directory;
25extern heap::heap * kheap;
26extern thread * current_thread;
2527
2628namespace multitasking
27{
29{
2830 void move_stack(void * new_stack_start, size_t size);
2931
3032 void initialise()
3133 {
32 debug::startup_message("Starting Multitasking");
34 debug::startup_message("Starting Scheduler");
3335
34 // Relocate the stack to a known location
36 // Disable interrupts while we start multitasking
37 disable();
38
39 // Relocate the stack to a known location
3540 move_stack((void *)0xE0000000, 0x2000);
3641
37 debug::startup_status(false);
42 // Make a new process for the kernel
43 process * kernel_process = new process();
44
45 // Make a virtual address space object that points to the kernel's virtual memory
46 virtual_address_space * addr = new virtual_address_space(current_directory, kheap);
47 kernel_process->set_address_space(addr);
48
49 current_thread = new thread(kernel_process);
50
51 // Re-enable interrupts, starting the scheduler
52 enable();
53
54 debug::startup_status(true);
3855 }
3956
57 // Move the initial kernel stack that Grub leaves us with to [new_stack_start]
4058 void move_stack(void * new_stack_start, size_t size)
4159 {
4260 // Allocate space for the new stack
7575 // Retrieve the old stack and base pointers
7676 asm volatile("mov %%esp, %0" : "=r" (old_stack_pointer));
7777 asm volatile("mov %%ebp, %0" : "=r" (old_base_pointer));
78
78
7979 // Calculate offset and stack and base pointers to our new stack
8080 uintptr offset = (uintptr)new_stack_start - initial_esp;
8181 uintptr new_stack_pointer = old_stack_pointer + offset;
8888 for(uintptr i = (uintptr)new_stack_start; i < (uintptr)new_stack_start - size; i -= 4)
8989 {
9090 uintptr temp = *(uintptr *)i;
91
91
9292 // Assume that temp is a base pointer if it is in the range of the old stack, and
9393 // translate it to our new stack location.
9494 // This will also remap any other pointers that coincidentally fall in this range.
9999 *temp2 = temp;
100100 }
101101 };
102
102
103103 // Switch to the new stack
104104 asm volatile("mov %0, %%esp" : : "r" (new_stack_pointer));
105105 asm volatile("mov %0, %%ebp" : : "r" (new_base_pointer));
106106 }
107
107108}
  
2020#include "common.h"
2121#include "scheduler.h"
2222
23extern "C" uintptr read_eip();
24
2325namespace multitasking
2426{
2527 void initialise();
28
29 // Defined in platform specific task.cc
30 uintptr read_esp();
31 uintptr read_ebp();
32
33 void switch_tasks(uintptr eip, uintptr esp, uintptr ebp, virtual_address_space * addr);
2634}
2735
2836#endif
  
1717#include "process/process.h"
1818#include "process/thread.h"
1919
20
21Thread::Thread(Process * parent) :
22 m_parent(parent)
20thread::thread(process * parent)
21 : m_parent(parent), m_eip(0), m_esp(0), m_ebp(0)
2322{
24
25 // TODO: Implement
23 parent->add_thread(this);
2624}
2725
28Thread::~Thread()
26thread::~thread()
2927{
3028 m_parent->remove_thread(this);
3129}
  
2020
2121#include "common.h"
2222
23// Forward declaration of process class so this will compile
24class Process;
23// Forward declarations of process class
24class process;
2525
26class Thread
26class thread
2727{
2828public:
29 enum Status
29 enum status
3030 {
3131 Ready,
3232 Running,
3737 typedef int (* ThreadStart)(void *);
3838
3939 // Make a normal thread
40 Thread(Process * parent, ThreadStart start_function, void * param);
40 thread(process * parent, ThreadStart start_function, void * param);
4141
42 Thread(Process * parent);
42 thread(process * parent);
4343
4444 // Remove this thread
45 ~Thread();
45 ~thread();
4646
4747 // Accessor functions to get and set information about the thread
4848 size_t get_id() { return m_id; };
4949 size_t get_errno() { return m_errno; };
50 Process * get_parent() { return m_parent; };
51 Status get_status() { return m_status; };
50 process * get_parent() { return m_parent; };
51 status get_status() { return m_status; };
5252
53 void set_status(Status s) { m_status = s; };
54 void set_errno(size_t n) { m_errno = n; };
53 void set_status(status s) { m_status = s; };
54 void set_errno(size_t n) { m_errno = n; };
55 void set_eip(uintptr eip) { m_eip = eip; };
5556
57 void set_stack_ptr(uintptr esp, uintptr ebp) { m_esp = esp; m_ebp = ebp; };
58
5659private:
5760 // This thread's parent process
58 Process * m_parent;
61 process * m_parent;
5962
63 // This thread's instruction pointer
64 uintptr m_eip;
65
66 // This thread's stack
67 //stack * m_stack;
68 uintptr m_esp, m_ebp;
69
6070 // The status of this thread
61 Status m_status;
71 status m_status;
6272
6373 // The thread's last error
6474 size_t m_errno;