mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 21:38:57 +02:00
starting list object implementation
This commit is contained in:
parent
fdfaf07c51
commit
7bda3ba03f
136
bootstrap/init.ccp
Normal file
136
bootstrap/init.ccp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#pypp 0
|
||||||
|
// Iris: micro-kernel for a capability-based operating system.
|
||||||
|
// bootstrap/init.ccp: Bootstrapping code.
|
||||||
|
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "devices.hh"
|
||||||
|
#include "iris.hh"
|
||||||
|
|
||||||
|
struct file:
|
||||||
|
unsigned size
|
||||||
|
// Only the first 16 characters of the name are used, because that's much easier.
|
||||||
|
// This means that file names must be different in the first 16 characters if sort order matters.
|
||||||
|
char name[16]
|
||||||
|
String string
|
||||||
|
|
||||||
|
static unsigned num_files
|
||||||
|
static file *files
|
||||||
|
static unsigned index
|
||||||
|
static Kernel::Memory top_memory
|
||||||
|
static unsigned max_pages
|
||||||
|
static char *mapping
|
||||||
|
|
||||||
|
// Get the initial block device and filesystem.
|
||||||
|
static Directory receive_devices ():
|
||||||
|
String dev
|
||||||
|
Filesystem fs
|
||||||
|
for unsigned i = 0; i < 2; ++i:
|
||||||
|
Kernel::wait ()
|
||||||
|
if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
|
||||||
|
kdebug ("Invalid bootstrap request.\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
switch Kernel::recv.data[1].l:
|
||||||
|
case String::ID:
|
||||||
|
if dev:
|
||||||
|
kdebug ("duplicate device.\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
dev = Kernel::get_arg ()
|
||||||
|
Kernel::recv.reply.invoke ()
|
||||||
|
break
|
||||||
|
case Filesystem::ID:
|
||||||
|
if fs:
|
||||||
|
kdebug ("duplicate filesystem.\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
fs = Kernel::get_arg ()
|
||||||
|
Kernel::recv.reply.invoke ()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
kdebug ("unexpected device: ")
|
||||||
|
kdebug_num (Kernel::recv.data[1].l)
|
||||||
|
kdebug_char ('\n')
|
||||||
|
Kernel::panic (0)
|
||||||
|
// Initialize the root file system.
|
||||||
|
Directory root = fs.use_device (dev.copy ())
|
||||||
|
Kernel::free_cap (dev)
|
||||||
|
Kernel::free_cap (fs)
|
||||||
|
return root
|
||||||
|
|
||||||
|
// Make a list of all files.
|
||||||
|
static void list_files (Directory root):
|
||||||
|
Kernel::Num fullsize = root.get_size ()
|
||||||
|
if fullsize.h != 0:
|
||||||
|
kdebug ("Too many files in bootstrap directory.\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
num_files = fullsize.l
|
||||||
|
files = new file[num_files]
|
||||||
|
Kernel::Caps caps = Kernel::my_memory.create_caps (num_files * 2)
|
||||||
|
unsigned slot = Kernel::alloc_slot ()
|
||||||
|
caps.use (slot)
|
||||||
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
|
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2))
|
||||||
|
String n = root.get_name (i)
|
||||||
|
n.get_chars (0, files[i].name)
|
||||||
|
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2 + 1))
|
||||||
|
files[i].string = root.get_file_ro (i)
|
||||||
|
Kernel::Num fullsize = files[i].string.get_size ()
|
||||||
|
if fullsize.h != 0:
|
||||||
|
kdebug ("initial file size too large.\n")
|
||||||
|
Kernel::panic (0)
|
||||||
|
files[i].size = fullsize.l
|
||||||
|
if max_pages < (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK:
|
||||||
|
max_pages = (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK
|
||||||
|
|
||||||
|
// Sort the list of files.
|
||||||
|
static bool is_less (file *f1, file *f2):
|
||||||
|
return
|
||||||
|
|
||||||
|
// Bubble sort.
|
||||||
|
static void sort ():
|
||||||
|
index = new unsigned[num_files]
|
||||||
|
index[0] = 0
|
||||||
|
// Invariant: index[0...f-1] is sorted.
|
||||||
|
for unsigned f = 1; f < num_files; ++f:
|
||||||
|
// Bubble up until top. Test for less-than, because it wraps to maxunsigned.
|
||||||
|
unsigned i
|
||||||
|
// Invariant: index[0...f] \ index[i+1] is sorted and index[i+1...f] is sorted.
|
||||||
|
for i = f - 1; i < f; --i:
|
||||||
|
if is_less (&files[index[i]], &files[f]):
|
||||||
|
break
|
||||||
|
index[i + 1] = index[i]
|
||||||
|
index[i + 1] = f
|
||||||
|
|
||||||
|
static void run (file *f):
|
||||||
|
Kernel::Memory mem = top_memory.create_memory ()
|
||||||
|
unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK
|
||||||
|
for unsigned p = 0; p < num_pages; ++p:
|
||||||
|
pages[p] = f->string.get_page (p << PAGE_BITS, mem.create_page ())
|
||||||
|
Kernel::my_memory.map (pages[p], (unsigned)&mapping[p << PAGE_BITS])
|
||||||
|
// TODO: parse elf file.
|
||||||
|
|
||||||
|
Kernel::Num start ():
|
||||||
|
top_memory = Kernel::get_top_memory ()
|
||||||
|
// Wait for the debugging device to be active, in case there is one.
|
||||||
|
Kernel::schedule ()
|
||||||
|
Directory root = receive_devices ()
|
||||||
|
root.lock_ro ()
|
||||||
|
list_files (root)
|
||||||
|
sort ()
|
||||||
|
pages = new Kernel::Page[max_pages]
|
||||||
|
mapping = alloc_space (max_pages)
|
||||||
|
for unsigned i = 0; i < num_files; ++i:
|
||||||
|
run (files[i])
|
||||||
|
root.unlock_ro ()
|
||||||
|
return 0
|
@ -226,7 +226,7 @@ struct Directory : public Kernel::Cap:
|
|||||||
// Get the number of entries in this directory.
|
// Get the number of entries in this directory.
|
||||||
Kernel::Num get_size ():
|
Kernel::Num get_size ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||||
// Get the filename. The return value is the size of the string, the page is filled with the string itself.
|
// Get the filename.
|
||||||
String get_name (Kernel::Num idx):
|
String get_name (Kernel::Num idx):
|
||||||
icall (CAP_MASTER_DIRECT | GET_NAME, idx)
|
icall (CAP_MASTER_DIRECT | GET_NAME, idx)
|
||||||
return Kernel::get_arg ()
|
return Kernel::get_arg ()
|
||||||
|
53
iris.hhp
53
iris.hhp
@ -42,8 +42,8 @@
|
|||||||
#define CAPTYPE_THREAD 0x600
|
#define CAPTYPE_THREAD 0x600
|
||||||
#define CAPTYPE_PAGE 0x800
|
#define CAPTYPE_PAGE 0x800
|
||||||
#define CAPTYPE_CAPS 0xa00
|
#define CAPTYPE_CAPS 0xa00
|
||||||
//#define CAPTYPE_??? 0xc00
|
#define CAPTYPE_LIST 0xc00
|
||||||
//#define CAPTYPE_??? 0xe00
|
#define CAPTYPE_LISTITEM 0xe00
|
||||||
|
|
||||||
// All kernel capabilities have a master capability, which can create others.
|
// All kernel capabilities have a master capability, which can create others.
|
||||||
#define CAP_MASTER 0
|
#define CAP_MASTER 0
|
||||||
@ -130,6 +130,7 @@ namespace Kernel:
|
|||||||
struct Thread
|
struct Thread
|
||||||
struct Page
|
struct Page
|
||||||
struct Memory
|
struct Memory
|
||||||
|
struct List
|
||||||
|
|
||||||
void print_caps ()
|
void print_caps ()
|
||||||
unsigned alloc_slot ()
|
unsigned alloc_slot ()
|
||||||
@ -428,6 +429,46 @@ namespace Kernel:
|
|||||||
void alloc_physical (unsigned address, bool cachable, bool freeable):
|
void alloc_physical (unsigned address, bool cachable, bool freeable):
|
||||||
my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0) | (freeable ? 2 : 0))
|
my_thread.ocall (*this, CAP_MASTER_DIRECT | Thread::PRIV_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0) | (freeable ? 2 : 0))
|
||||||
|
|
||||||
|
struct Listitem : public Cap:
|
||||||
|
Listitem (Cap c = Cap ()) : Cap (c):
|
||||||
|
enum request:
|
||||||
|
REMOVE = CAPTYPE_LISTITEM + 1
|
||||||
|
CLEAR
|
||||||
|
SET_CAP
|
||||||
|
ADD
|
||||||
|
void remove ():
|
||||||
|
call (CAP_MASTER_DIRECT | REMOVE)
|
||||||
|
void clear ():
|
||||||
|
call (CAP_MASTER_DIRECT | CLEAR)
|
||||||
|
void set_cap (Cap c):
|
||||||
|
call (CAP_MASTER_DIRECT | SET_CAP, c.code)
|
||||||
|
// ADD is called by the kernel on non-listitem objects which are added to a list, to allow virtualization.
|
||||||
|
// Also, to add a listitem to a list, the listitem capability must be of type ADD or MASTER.
|
||||||
|
|
||||||
|
struct List : public Cap:
|
||||||
|
List (Cap c = Cap ()) : Cap (c):
|
||||||
|
enum request:
|
||||||
|
GET_NEXT = CAPTYPE_LIST + 1
|
||||||
|
SET_EMPTY_CB
|
||||||
|
ADD_ITEM
|
||||||
|
GET_INFO
|
||||||
|
SET_INFO
|
||||||
|
GET_CAP
|
||||||
|
Listitem get_next (Listitem current = Listitem ()):
|
||||||
|
icall (current, CAP_MASTER_DIRECT | GET_NEXT)
|
||||||
|
return get_arg ()
|
||||||
|
void set_empty_cb (Cap cb):
|
||||||
|
ocall (cb, CAP_MASTER_DIRECT | SET_EMPTY_CB)
|
||||||
|
void add_item (Listitem item):
|
||||||
|
ocall (item, CAP_MASTER_DIRECT | ADD_ITEM)
|
||||||
|
Num get_info (Listitem item):
|
||||||
|
return ocall (item, CAP_MASTER_DIRECT | GET_INFO)
|
||||||
|
void set_info (Listitem item, Num info):
|
||||||
|
ocall (item, CAP_MASTER_DIRECT | SET_INFO, info)
|
||||||
|
Cap get_cap (Listitem item):
|
||||||
|
iocall (item, CAP_MASTER_DIRECT | GET_CAP)
|
||||||
|
return get_arg ()
|
||||||
|
|
||||||
struct Memory : public Cap:
|
struct Memory : public Cap:
|
||||||
Memory (unsigned slot, unsigned idx) : Cap (slot, idx):
|
Memory (unsigned slot, unsigned idx) : Cap (slot, idx):
|
||||||
Memory (Cap c = Cap ()) : Cap (c):
|
Memory (Cap c = Cap ()) : Cap (c):
|
||||||
@ -454,6 +495,12 @@ namespace Kernel:
|
|||||||
Caps create_caps (unsigned size):
|
Caps create_caps (unsigned size):
|
||||||
icall (Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_CAPS), size)
|
icall (Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_CAPS), size)
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
|
List create_list ():
|
||||||
|
icall (Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_LIST))
|
||||||
|
return get_arg ()
|
||||||
|
Listitem create_listitem ():
|
||||||
|
icall (Num (CAP_MASTER_DIRECT | CREATE, CAPTYPE_LISTITEM))
|
||||||
|
return get_arg ()
|
||||||
void destroy (Cap target):
|
void destroy (Cap target):
|
||||||
ocall (target, CAP_MASTER_DIRECT | DESTROY)
|
ocall (target, CAP_MASTER_DIRECT | DESTROY)
|
||||||
// TODO: LIST
|
// TODO: LIST
|
||||||
@ -464,7 +511,7 @@ namespace Kernel:
|
|||||||
Page mapping (void *address):
|
Page mapping (void *address):
|
||||||
icall (CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address))
|
icall (CAP_MASTER_DIRECT | MAPPING, Num ((unsigned)address))
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
unsigned get_limit (unsigned limit):
|
unsigned get_limit ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_LIMIT).l
|
return call (CAP_MASTER_DIRECT | GET_LIMIT).l
|
||||||
void set_limit (unsigned limit):
|
void set_limit (unsigned limit):
|
||||||
call (CAP_MASTER_DIRECT | SET_LIMIT, limit)
|
call (CAP_MASTER_DIRECT | SET_LIMIT, limit)
|
||||||
|
17
kernel.hhp
17
kernel.hhp
@ -36,6 +36,8 @@ struct kReceiver
|
|||||||
struct kCapability
|
struct kCapability
|
||||||
struct kCaps
|
struct kCaps
|
||||||
struct kMemory
|
struct kMemory
|
||||||
|
struct kList
|
||||||
|
struct kListitem
|
||||||
|
|
||||||
// Some functions which must be defined early.
|
// Some functions which must be defined early.
|
||||||
extern "C":
|
extern "C":
|
||||||
@ -58,6 +60,8 @@ typedef kReceiver *kReceiverP
|
|||||||
typedef kCapability *kCapabilityP
|
typedef kCapability *kCapabilityP
|
||||||
typedef kCaps *kCapsP
|
typedef kCaps *kCapsP
|
||||||
typedef kMemory *kMemoryP
|
typedef kMemory *kMemoryP
|
||||||
|
typedef kList *kListP
|
||||||
|
typedef kListitem *kListitemP
|
||||||
typedef void *kPointer
|
typedef void *kPointer
|
||||||
|
|
||||||
struct kCapRef:
|
struct kCapRef:
|
||||||
@ -183,12 +187,25 @@ struct kMessage : public kObject:
|
|||||||
// This is a real Caps of two elements, not a link.
|
// This is a real Caps of two elements, not a link.
|
||||||
kCaps caps
|
kCaps caps
|
||||||
|
|
||||||
|
struct kListitem : public kObject:
|
||||||
|
kListitemP prev_item, next_item
|
||||||
|
kThreadP owner
|
||||||
|
unsigned cap
|
||||||
|
Kernel::Num info
|
||||||
|
|
||||||
|
struct kList : public kObject:
|
||||||
|
kListitemP first_item
|
||||||
|
kThreadP owner
|
||||||
|
unsigned cb
|
||||||
|
|
||||||
struct kMemory : public kObject:
|
struct kMemory : public kObject:
|
||||||
kFree *frees
|
kFree *frees
|
||||||
kPageP pages
|
kPageP pages
|
||||||
kThreadP threads
|
kThreadP threads
|
||||||
kReceiverP receivers
|
kReceiverP receivers
|
||||||
kCapsP capses
|
kCapsP capses
|
||||||
|
kListP lists
|
||||||
|
kListitemP listitems
|
||||||
kMemoryP memories
|
kMemoryP memories
|
||||||
unsigned limit, used
|
unsigned limit, used
|
||||||
kMemory_arch arch
|
kMemory_arch arch
|
||||||
|
Loading…
Reference in New Issue
Block a user