1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 00:44:31 +03:00

starting list object implementation

This commit is contained in:
Bas Wijnen 2009-12-28 07:53:29 +01:00
parent fdfaf07c51
commit 7bda3ba03f
4 changed files with 204 additions and 4 deletions

136
bootstrap/init.ccp Normal file
View 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

View File

@ -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 ()

View File

@ -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)

View File

@ -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