#include <util/list.h>
#include <util/rbtree.h>
+#include <util/radix.h>
+#include <util/bmaptree.h>
+
#include <System/Objects.h>
namespace Mem {
struct ObjectHdr;
struct Object;
-
typedef u32 ID;
- typedef Util::RadixTree<ObjectHdr, ID> IDRMap;
struct ObjectHdr {
ID id;
struct ObjectPtr : public ObjectHdr {
Object *object;
};
+
+ union ObjTableEntry {
+ ObjectHdr hdr;
+ Object obj;
+ ObjectPtr ptr;
+ };
+
+ typedef Util::RadixTree<ObjTableEntry, ID, 6> IDTable;
+ typedef Util::RadixTree<ObjectHdr *, ID, 4> IDRMap;
+ typedef Util::BitmapTree<ID> IDAlloc;
class IDSpace {
// Reverse mapping of object pointers to local IDs
- IDRMap idrmap;
+ IDTable table;
+ IDRMap rmap;
+ IDAlloc alloc;
public:
Object *lookup(u32 id);
ObjectHdr *get_local_hdr(Object *obj);
+ Object *newobj(Mem::ProcAddrSpace *aspace, uintptr_t entry);
};
}
-// Generic radix tree implementation. It's only kernel-specific because
-// it uses the kernel page allocator; each node takes up one page. The
-// depth of the tree is dynamically growable (but not currently
-// shrinkable).
+// This is like RadixTree, but it uses the kernel page allocator; each
+// node takes up one page. The depth of the tree is dynamically growable
+// (but not currently shrinkable). It also auto-guesses radix_bits based
+// on the size of T, so as to fit a page.
#ifndef _KERN_RADIX_H
#define _KERN_RADIX_H
namespace Util {
// Key must be an integer.
template <typename T, typename Key>
- class RadixTree {
+ class PageRadixTree {
void *toplevel;
uint depth; // in bits
node = new_node;
}
- assert(shift == RADIX_final_shift - dir_shift);
- return static_cast<T *>(node) + key_to_offset(key);
+ assert(shift == 0 || shift == RADIX_final_shift - dir_shift);
+ return (T *)((unsigned long)node +
+ (key_to_offset(key) << RADIX_data_bits));
}
- RadixTree()
+ PageRadixTree()
{
toplevel = Mem::alloc_pages(1);
bzero(toplevel, Arch::page_size);
#include <kern/mem.h>
#include <kern/radix.h>
+#include <util/radix.h>
namespace Mem {
struct RMapNode {
class Page;
class RMapTable {
- Util::RadixTree<RMapNode, u64> tree;
+ Util::PageRadixTree<RMapNode, u64> tree;
+
+ RMapNode *lookup(u64 vaddr, bool add = false)
+ {
+ return tree.lookup(vaddr >> Arch::page_shift, add);
+ }
public:
// rmap_lock must be held.
void *malloc(size_t len)
{
+ assert(len <= Arch::page_size - sizeof(size_t));
+
len = (len + sizeof(size_t) + Arch::page_size - 1) / Arch::page_size;
Mem::Page *page = Mem::PageAlloc::alloc(len);
void free(void *addr)
{
if (addr) {
- size_t *ptr = (size_t *)addr;
- ptr--;
+ size_t *ptr = (size_t *)addr - 1;
size_t len = *ptr;
Mem::Page *page = Mem::kvirt_to_page(addr);
Mem::PageAlloc::free(page, len);
priv = NULL;
}
- void *ORBMM::alloc(size_t size, AllocGroup *group)
+ void *ORBMM::alloc(size_t size, int refs)
{
return reinterpret_cast<void *>(new u8[size]);
}
- void ORBMM::retain(Region region)
+ void ORBMM::retain(void *ptr, int refs)
{
// FIXME
}
- void ORBMM::release(Region region)
+ void ORBMM::release(void *ptr, int refs)
+ {
+ // FIXME
+ }
+
+ void ORBMM::add_region(Region rgn, bool unmap, int refs)
{
// FIXME
}
u64 dsvaddr, u64 usvaddr)
{
RMapNode *dsrmap = dsva->aspace->page_table->
- rmap_table.tree.lookup(dsvaddr, true);
+ rmap_table.lookup(dsvaddr, true);
assert(!dsrmap->va);
dsrmap->va = dsva;
dsrmap->tail.init();
if (usptbl) {
- RMapNode *usrmap = usptbl->rmap_table.tree.lookup(usvaddr);
+ RMapNode *usrmap = usptbl->rmap_table.lookup(usvaddr);
assert(usrmap);
assert(usrmap->va->aspace->page_table == usptbl);
void RMapTable::unmap(u64 virtaddr)
{
Lock::AutoLock autolock(rmap_lock);
- RMapNode *head = tree.lookup(virtaddr);
+ RMapNode *head = lookup(virtaddr);
if (!head || !head->va)
return;
void RMapTable::break_copy_on_write(u64 virtaddr, Page *new_page)
{
assert(rmap_lock.held_by_curthread());
- RMapNode *head = tree.lookup(virtaddr);
+ RMapNode *head = lookup(virtaddr);
RMapNode *still_cow = NULL;
assert(head && head->va);
return &hdr->frames[++thread->orbstack_top];
}
-
+
ObjectHdr *IDSpace::get_local_hdr(Object *obj)
{
- ObjectHdr *hdr = idrmap.lookup(obj->id);
+ ObjectHdr *hdr = *rmap.lookup(obj->id);
+ if (hdr)
+ return hdr;
- if (!hdr)
- return 0;
+ int id = alloc.alloc();
+ ObjectPtr *ptr = &table.lookup(id, true)->ptr;
+
+ ptr->id = id;
+ ptr->flags = 0;
+ ptr->Pointer = 1;
+ ptr->object = obj;
+
+ *rmap.lookup(id, true) = ptr;
+ return ptr;
+ }
+
+ Object *IDSpace::newobj(Mem::ProcAddrSpace *aspace, uintptr_t entry)
+ {
+ int id = alloc.alloc();
+ Object *obj = &table.lookup(id, true)->obj;
+
+ obj->id = id;
+ obj->flags = 0;
+ obj->aspace = aspace;
+ obj->entry = entry;
- return hdr->id;
+ return obj;
}
}
-extern "C" void invoke_method(u32 objid, u32 methid, ParamInfoBlock *user_pib,
- ulong ret_pc)
+extern "C" void invoke_method(ParamInfoBlock *user_pib, ulong ret_pc)
{
ParamInfoBlock pib = Arch::copyin(user_pib);
CallFrame *frame = new_frame(curthread);
- frame->object = objid;
- frame->method = methid;
+// frame->object = objid;
frame->caller_user_pib = user_pib;
frame->ret_pc = ret_pc;
- printf("invoke_method: frame %p object %x method %x pib %p ret %lx\n",
- frame, frame->object, frame->method, frame->caller_user_pib,
+ printf("invoke_method: frame %p pib %p ret %lx\n",
+ frame, frame->caller_user_pib,
frame->ret_pc);
(void *)stacked[0], (void *)stacked[1],
(void *)mappables[0], (void *)mappables[1]);
- char *buf = new char[100000];
+// char *buf = new char[100000];
+ char *buf = (char *)alloc_pages(25);
printf("buf %p\n", buf);
char *abuf = (char *)((((ulong)buf) + 4095) & ~4095);