mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 19:32:25 +02:00
lcd working
This commit is contained in:
parent
cc1dc267d5
commit
bee84d53ec
42
alloc.ccp
42
alloc.ccp
@ -22,20 +22,20 @@
|
||||
#define NEXT(x) (((Object_base **)(x))[-1])
|
||||
#define SIZE (2 * sizeof (Object_base *))
|
||||
|
||||
bool Memory::use ():
|
||||
bool Memory::use (unsigned num):
|
||||
// Go up to parents, incrementing used.
|
||||
for Memory *m = this; m; m = m->address_space:
|
||||
if used >= limit:
|
||||
if used + num > limit:
|
||||
// Not allowed. Restore used for all children.
|
||||
for Memory *r = this; r != m; r = r->address_space:
|
||||
--r->used
|
||||
r->used -= num
|
||||
return false
|
||||
++m->used
|
||||
m->used += num
|
||||
return true
|
||||
|
||||
void Memory::unuse ():
|
||||
void Memory::unuse (unsigned num):
|
||||
for Memory *m = this; m; m = m->address_space:
|
||||
--m->used
|
||||
m->used -= num
|
||||
|
||||
void *Memory::search_free (unsigned size, void **first):
|
||||
Free *f
|
||||
@ -50,6 +50,7 @@ void *Memory::search_free (unsigned size, void **first):
|
||||
if !f:
|
||||
unsigned p = palloc ()
|
||||
if !p:
|
||||
assert (false)
|
||||
return NULL
|
||||
f = (Free *)(p + SIZE)
|
||||
f->marker = ~0
|
||||
@ -134,21 +135,18 @@ Thread *Memory::alloc_thread ():
|
||||
ret->pc = 0
|
||||
ret->sp = 0
|
||||
Thread_arch_init (ret)
|
||||
ret->sleep_count = ~0
|
||||
ret->flags = 0
|
||||
ret->schedule_prev = NULL
|
||||
ret->schedule_next = NULL
|
||||
ret->receivers = NULL
|
||||
return ret
|
||||
|
||||
Message *Memory::alloc_message (Receiver *target, unsigned protected_data):
|
||||
Message *Memory::alloc_message (Receiver *target):
|
||||
Message *ret = (Message *)search_free (sizeof (Message), (void **)&target->messages)
|
||||
if !ret:
|
||||
return NULL
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
ret->capabilities[i] = NULL
|
||||
ret->data[i] = 0
|
||||
ret->protected_data = protected_data
|
||||
if !ret->next:
|
||||
target->last_message = ret
|
||||
return ret
|
||||
|
||||
Receiver *Memory::alloc_receiver ():
|
||||
@ -158,8 +156,10 @@ Receiver *Memory::alloc_receiver ():
|
||||
ret->owner = NULL
|
||||
ret->prev_owned = NULL
|
||||
ret->next_owned = NULL
|
||||
ret->alarm_count = ~0
|
||||
ret->capabilities = NULL
|
||||
ret->messages = NULL
|
||||
ret->last_message = NULL
|
||||
ret->reply_protected_data = ~0
|
||||
ret->protected_only = false
|
||||
return ret
|
||||
@ -251,9 +251,18 @@ void Memory::free_thread (Thread *thread):
|
||||
thread->receivers->orphan ()
|
||||
free_obj (thread)
|
||||
|
||||
void Memory::free_message (Message *message):
|
||||
void Memory::free_message (Receiver *owner, Message *message):
|
||||
if message->prev:
|
||||
message->prev->next = message->next
|
||||
else:
|
||||
owner->messages = message->next
|
||||
if message->next:
|
||||
message->next->prev = message->prev
|
||||
else:
|
||||
owner->last_message = message->prev
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
free_capability (message->capabilities[i])
|
||||
if message->capabilities[i]:
|
||||
free_capability (message->capabilities[i])
|
||||
free_obj (message)
|
||||
|
||||
void Memory::free_receiver (Receiver *receiver):
|
||||
@ -261,7 +270,7 @@ void Memory::free_receiver (Receiver *receiver):
|
||||
while receiver->capabilities:
|
||||
receiver->capabilities->invalidate ()
|
||||
while receiver->messages:
|
||||
free_message (receiver->messages)
|
||||
free_message (receiver, receiver->messages)
|
||||
free_obj (receiver)
|
||||
|
||||
void Receiver::orphan ():
|
||||
@ -346,7 +355,8 @@ void Page::forget ():
|
||||
data.share_prev = NULL
|
||||
data.share_next = NULL
|
||||
else:
|
||||
if ~data.flags & PAGE_FLAG_PHYSICAL:
|
||||
// If the page has a frame and should be freed, free it.
|
||||
if !((data.flags ^ PAGE_FLAG_FRAME) & (PAGE_FLAG_PHYSICAL | PAGE_FLAG_FRAME)):
|
||||
raw_pfree (data.frame)
|
||||
data.frame = 0
|
||||
data.flags &= ~(PAGE_FLAG_FRAME | PAGE_FLAG_SHARED | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED)
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
__start:
|
||||
bal 1f
|
||||
__hack_label:
|
||||
nop
|
||||
.word _gp
|
||||
1:
|
||||
|
@ -26,7 +26,6 @@
|
||||
// For some reason, it only works if the rows are input and the columns are output.
|
||||
|
||||
static void event (bool release, unsigned row, unsigned col):
|
||||
kdebug ((release ? 0x10000 : 0) | (row << 8) | col)
|
||||
|
||||
#define COL_MASK 0x2000ffff
|
||||
#define ROW_MASK 0x000000ff
|
||||
|
@ -20,6 +20,13 @@
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
#define assert(x) do { while (!(x)) kdebug (0, 0); } while (0)
|
||||
|
||||
// For now, support only 16 bpp.
|
||||
// Screen is 800x480 tft.
|
||||
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
||||
#define frame_size (v * h * Bpp)
|
||||
|
||||
// Pin definitions, all in port 2.
|
||||
#define PWM_ENABLE (1 << 30)
|
||||
#define SPEN (1 << 0) //LCD_SPL
|
||||
@ -37,22 +44,25 @@ static void set_backlight (bool state):
|
||||
PWM_CTR (0) = 0x3f
|
||||
GPIO_GPDR (2) &= ~PWM_ENABLE
|
||||
|
||||
static void reset ():
|
||||
struct Descriptor:
|
||||
unsigned next
|
||||
unsigned frame
|
||||
unsigned id
|
||||
unsigned cmd
|
||||
|
||||
static void reset (unsigned physical_descriptor):
|
||||
PWM_PER (0) = 300
|
||||
set_backlight (false)
|
||||
set_backlight (true)
|
||||
|
||||
// initialize things.
|
||||
GPIO_GPIER (2) &= ~(PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA)
|
||||
GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA
|
||||
GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET
|
||||
udelay (50)
|
||||
GPIO_GPDR (2) &= ~LCD_RET
|
||||
ddelay (2)
|
||||
GPIO_GPDR (2) |= LCD_RET
|
||||
ddelay (1)
|
||||
|
||||
// For now, support only 16 bpp.
|
||||
// Screen is 800x480 tft.
|
||||
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
|
||||
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
|
||||
LCD_VSYNC = vs
|
||||
LCD_HSYNC = hs
|
||||
@ -60,55 +70,99 @@ static void reset ():
|
||||
LCD_DAH = (hs << 16) | (hs + h)
|
||||
LCD_VAT = ((hs + h) << 16) | (vs + v)
|
||||
#define MODE_TFT_GEN 0
|
||||
#define PCLK_N (1 << 10)
|
||||
#define VSYNC_N (1 << 8)
|
||||
LCD_CFG = MODE_TFT_GEN | PCLK_N | VSYNC_N
|
||||
LCD_CFG = MODE_TFT_GEN | VSYNC_N
|
||||
|
||||
cpm_stop_lcd ()
|
||||
|
||||
unsigned pllout = cpm_get_pllout ()
|
||||
unsigned pixclock = fps * (hs + h) * (vs + v)
|
||||
unsigned pllout = cpm_get_pllout ()
|
||||
CPM_CFCR2 = pllout / pixclock - 1
|
||||
|
||||
unsigned val = pllout / (pixclock * 4) - 1
|
||||
while val < 0xf && pllout / (val + 1) > 150000000:
|
||||
++val
|
||||
assert (pllout / (val + 1) <= 150000000)
|
||||
assert (val <= 0xf)
|
||||
cpm_set_lcdclk_div (val)
|
||||
CPM_CFCR |= CPM_CFCR_UPE
|
||||
|
||||
cpm_start_lcd ()
|
||||
|
||||
udelay (1000)
|
||||
//LCD_DA0 = framebuffer
|
||||
unsigned frame_size = v * h * Bpp
|
||||
LCD_CMD0 = LCD_CMD_SOFINT | LCD_CMD_EOFINT | (frame_size << LCD_CMD_LEN_BIT)
|
||||
LCD_DA0 = physical_descriptor
|
||||
lcd_set_ena ()
|
||||
lcd_enable_eof_intr ()
|
||||
|
||||
int main ():
|
||||
// TODO: The descriptor takes an entire uncached page, because I don't know how to force a cache write-back. It's much better to do that instead.
|
||||
map_gpio ()
|
||||
map_pwm0 ()
|
||||
map_lcd ()
|
||||
map_cpm ()
|
||||
|
||||
reset ()
|
||||
unsigned pages = (frame_size + 16 + ~PAGE_MASK) >> PAGE_BITS
|
||||
assert (pages > CAPPAGE_SIZE && pages <= 2 * CAPPAGE_SIZE)
|
||||
unsigned physical = alloc_range (__my_memory, pages)
|
||||
assert (physical)
|
||||
//Capability cappage[2]
|
||||
//unsigned base[2]
|
||||
//cappage[0] = memory_create_cappage (__my_memory, &base[0])
|
||||
//cappage[1] = memory_create_cappage (__my_memory, &base[1])
|
||||
for unsigned i = 0; i < CAPPAGE_SIZE; ++i:
|
||||
Capability page = memory_create_page (__my_memory)
|
||||
//cappage_set (cappage[0], page, i)
|
||||
alloc_physical (page, physical + i * PAGE_SIZE, 0, 1)
|
||||
memory_map (__my_memory, page, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE, 1)
|
||||
drop (page)
|
||||
for unsigned i = 0; i < pages - CAPPAGE_SIZE; ++i:
|
||||
Capability page = memory_create_page (__my_memory)
|
||||
//cappage_set (cappage[1], page, i)
|
||||
alloc_physical (page, physical + (i + CAPPAGE_SIZE) * PAGE_SIZE, 0, 1)
|
||||
memory_map (__my_memory, page, (unsigned)LCD_FRAMEBUFFER_BASE + (i + CAPPAGE_SIZE) * PAGE_SIZE, 1)
|
||||
drop (page)
|
||||
unsigned og = 0
|
||||
for unsigned y = 0; y < 480; ++y:
|
||||
unsigned g = (y << 6) / 480
|
||||
if g != og:
|
||||
og = g
|
||||
g = 0x3f
|
||||
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||
for unsigned x = 0; x < 800; ++x:
|
||||
unsigned r = (x << 5) / 800
|
||||
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||
if r != olr:
|
||||
olr = r
|
||||
r = 0x1f
|
||||
unsigned oyb = b
|
||||
if y > 0:
|
||||
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
|
||||
if b != ob || b != oyb:
|
||||
ob = b
|
||||
b = 0x1f
|
||||
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
|
||||
Descriptor *descriptor = (Descriptor *)((unsigned)LCD_FRAMEBUFFER_BASE + frame_size)
|
||||
unsigned physical_descriptor = physical + frame_size
|
||||
descriptor->next = physical_descriptor
|
||||
descriptor->frame = physical
|
||||
descriptor->id = 0xdeadbeef
|
||||
descriptor->cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
|
||||
reset (physical_descriptor)
|
||||
register_interrupt (IRQ_LCD)
|
||||
set_backlight (true)
|
||||
|
||||
while true:
|
||||
Message msg
|
||||
if !wait (&msg):
|
||||
continue
|
||||
wait (&msg)
|
||||
switch msg.protected_data:
|
||||
case IRQ_LCD:
|
||||
kdebug (0)
|
||||
LCD_STATE &= ~LCD_STATE_EOF
|
||||
lcd_clr_eof ()
|
||||
register_interrupt (IRQ_LCD)
|
||||
// TODO: allow callback
|
||||
break
|
||||
#if 0
|
||||
case LCD_BACKLIGHT:
|
||||
set_backlight (msg.data[0])
|
||||
break
|
||||
case LCD_RESET:
|
||||
reset ()
|
||||
//reset (physical_descriptor)
|
||||
break
|
||||
#endif
|
||||
|
197
invoke.ccp
197
invoke.ccp
@ -20,46 +20,59 @@
|
||||
|
||||
// From user-provided, thus untrusted, data, find a capability.
|
||||
Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||
if !code:
|
||||
return NULL
|
||||
*copy = code & 2 ? true : false
|
||||
if !(code & ~3):
|
||||
return NULL
|
||||
if code & 1:
|
||||
// Cappage capability
|
||||
unsigned num = (code & ~PAGE_MASK) >> 2
|
||||
if num >= CAPPAGE_SIZE:
|
||||
panic (0x15544551, "invalid cappage index")
|
||||
return NULL
|
||||
Capability *page = (Capability *)(code & PAGE_MASK)
|
||||
unsigned page = code & PAGE_MASK
|
||||
for Cappage *p = cappages; p; p = p->next:
|
||||
if p->data.frame == (unsigned)page:
|
||||
return &page[num]
|
||||
if p->data.frame == page:
|
||||
return p->cap (num)
|
||||
else:
|
||||
// Normal capability
|
||||
code &= ~3
|
||||
Capability *target = (Capability *)(code & ~3)
|
||||
for Capability *c = capabilities; c; c = c->next:
|
||||
if c == (Capability *)code:
|
||||
if c == target:
|
||||
return c
|
||||
dbg_send (code)
|
||||
panic (0xfffeee00, "invalid capability")
|
||||
return NULL
|
||||
|
||||
// Try to deliver a message.
|
||||
bool Receiver::try_deliver ():
|
||||
if !messages || !owner || !owner->is_waiting ():
|
||||
if !messages:
|
||||
return false
|
||||
Message *m = messages
|
||||
if !owner || !owner->is_waiting ():
|
||||
dbg_send (3, 3)
|
||||
return false
|
||||
Message *m = last_message
|
||||
if protected_only:
|
||||
for ; m; m = m->next:
|
||||
for ; m; m = m->prev:
|
||||
if m->protected_data == reply_protected_data:
|
||||
protected_only = false
|
||||
break
|
||||
if !m:
|
||||
return false
|
||||
if !m:
|
||||
panic (0x32547688, "protected only")
|
||||
return false
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.data[i] = m->data[i]
|
||||
if m->capabilities[i]:
|
||||
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
||||
if !c.cap[i]:
|
||||
panic (0xffaaaaaa, "out of memory")
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
owner->address_space->free_capability (c.cap[i])
|
||||
return false
|
||||
else:
|
||||
c.cap[i] = NULL
|
||||
Thread_arch_receive (owner, m->protected_data, &c)
|
||||
address_space->free_message (this, m)
|
||||
owner->unwait ()
|
||||
return true
|
||||
|
||||
@ -67,22 +80,41 @@ bool Receiver::try_deliver ():
|
||||
bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
||||
bool tried_direct = false
|
||||
if owner && owner->is_waiting () && (protected_data == reply_protected_data || !protected_only):
|
||||
Capability *orig[4]
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
if c->cap[i]:
|
||||
c->cap[i] = owner->address_space->clone_capability (c->cap[i], c->copy[i])
|
||||
orig[i] = c->cap[i]
|
||||
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
||||
if !c->cap[i]:
|
||||
panic (0xdddddddd, "out of memory")
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
owner->address_space->free_capability (c->cap[i])
|
||||
owner->address_space->free_capability (c->cap[j])
|
||||
c->cap[j] = orig[j]
|
||||
c->cap[i] = orig[i]
|
||||
tried_direct = true
|
||||
break
|
||||
if !tried_direct:
|
||||
if protected_data == reply_protected_data:
|
||||
protected_only = false
|
||||
Thread_arch_receive (owner, protected_data, c)
|
||||
owner->unwait ()
|
||||
return true
|
||||
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
||||
Message *msg = address_space->alloc_message (this, protected_data)
|
||||
Message *msg = address_space->alloc_message (this)
|
||||
if !msg:
|
||||
panic (0xbbbbbbbb, "out of memory")
|
||||
return false
|
||||
msg->protected_data = protected_data
|
||||
if protected_data == reply_protected_data:
|
||||
// Put this message in the end (where it will be first seen). Clear the protected_only flag.
|
||||
protected_only = false
|
||||
if msg->next:
|
||||
msg->next->prev = NULL
|
||||
messages = msg->next
|
||||
msg->next = NULL
|
||||
msg->prev = last_message
|
||||
msg->prev->next = msg
|
||||
last_message = msg
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
msg->data[i] = c->data[i]
|
||||
if !c->cap[i]:
|
||||
@ -90,9 +122,10 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
||||
else:
|
||||
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
||||
if !msg->capabilities[i]:
|
||||
panic (0xcccccccc, "out of memory")
|
||||
for unsigned j = 0; j < i; ++j:
|
||||
address_space->free_capability (msg->capabilities[j])
|
||||
address_space->free_message (msg)
|
||||
address_space->free_message (this, msg)
|
||||
return false
|
||||
if tried_direct:
|
||||
Thread_arch_receive_fail (owner)
|
||||
@ -144,6 +177,22 @@ static void reply_cap (Capability *cap, bool copy):
|
||||
else if reply_receiver:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||
|
||||
static void reply_cappage (Cappage *cap, unsigned target):
|
||||
Capability r
|
||||
fill_cap (&r, target, (unsigned)cap)
|
||||
Capability::Context c
|
||||
for unsigned i = 1; i < 4; ++i:
|
||||
c.data[i] = 0
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
c.data[0] = cap->data.frame
|
||||
c.cap[0] = &r
|
||||
c.copy[0] = true
|
||||
if reply:
|
||||
reply->invoke (&c)
|
||||
else if reply_receiver:
|
||||
reply_receiver->send_message (reply_receiver->reply_protected_data, &c)
|
||||
|
||||
static void reply_num (unsigned num):
|
||||
Capability::Context c
|
||||
c.data[0] = num
|
||||
@ -186,12 +235,35 @@ static void receiver_invoke (unsigned target, unsigned protected_data, Capabilit
|
||||
case CAP_RECEIVER_CREATE_CALL_CAPABILITY:
|
||||
reply_cap (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_CALL) | (c->data[1] ? 1 << CAP_RECEIVER_CALL_ASYNC : 0), protected_data)
|
||||
break
|
||||
case CAP_RECEIVER_GET_REPLY_PROTECTED_DATA:
|
||||
case CAP_RECEIVER_REPLY_PROTECTED_DATA:
|
||||
reply_nums (receiver->reply_protected_data, receiver->protected_only ? 1 : 0)
|
||||
if c->data[1]:
|
||||
receiver->reply_protected_data = c->data[2]
|
||||
break
|
||||
case CAP_RECEIVER_SET_REPLY_PROTECTED_DATA:
|
||||
receiver->reply_protected_data = c->data[1]
|
||||
receiver->protected_only = c->data[2]
|
||||
case CAP_RECEIVER_ALARM:
|
||||
unsigned old = receiver->alarm_count
|
||||
reply_num (old)
|
||||
if c->data[1]:
|
||||
receiver->alarm_count = c->data[2]
|
||||
else:
|
||||
receiver->alarm_count += c->data[2]
|
||||
if (old == ~0) ^ (receiver->alarm_count == ~0):
|
||||
// The alarm stopped or started.
|
||||
if old == ~0:
|
||||
// It started.
|
||||
receiver->prev_alarm = NULL
|
||||
receiver->next_alarm = first_alarm
|
||||
if receiver->next_alarm:
|
||||
receiver->next_alarm->prev_alarm = receiver
|
||||
first_alarm = receiver
|
||||
else:
|
||||
// It stopped.
|
||||
if receiver->prev_alarm:
|
||||
receiver->prev_alarm->next_alarm = receiver->next_alarm
|
||||
else:
|
||||
first_alarm = receiver->next_alarm
|
||||
if receiver->next_alarm:
|
||||
receiver->next_alarm->prev_alarm = receiver->prev_alarm
|
||||
break
|
||||
default:
|
||||
break
|
||||
@ -234,7 +306,7 @@ static void memory_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
case CAPTYPE_CAPPAGE:
|
||||
Cappage *ret = mem->alloc_cappage ()
|
||||
if ret:
|
||||
reply_cap (CAPTYPE_CAPPAGE | (rights & CAP_CAPPAGE_ALL_RIGHTS), (unsigned)ret)
|
||||
reply_cappage (ret, CAPTYPE_CAPPAGE | (rights & CAP_CAPPAGE_ALL_RIGHTS))
|
||||
else:
|
||||
reply_num (0)
|
||||
break
|
||||
@ -320,24 +392,17 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
unsigned v = (*value & c->data[3]) | (c->data[2] & c->data[3])
|
||||
if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING):
|
||||
if v & THREAD_FLAG_WAITING:
|
||||
thread->wait ()
|
||||
if !(thread->is_waiting ()):
|
||||
thread->wait ()
|
||||
else
|
||||
thread->unwait ()
|
||||
if thread->is_waiting ():
|
||||
thread->unwait ()
|
||||
if (v & THREAD_FLAG_RUNNING) != (*value & THREAD_FLAG_RUNNING):
|
||||
if v & THREAD_FLAG_RUNNING:
|
||||
thread->run ()
|
||||
else
|
||||
thread->unrun ()
|
||||
break
|
||||
case CAP_THREAD_INFO_SLEEP:
|
||||
value = &thread->sleep_count
|
||||
if thread->flags & THREAD_FLAG_WAITING:
|
||||
unsigned newval = (*value & ~c->data[3]) | (c->data[2] & c->data[3])
|
||||
if *value == ~0 && newval != ~0:
|
||||
thread->sleep ()
|
||||
else if *value != ~0 && newval == ~0:
|
||||
thread->unsleep ()
|
||||
break
|
||||
default:
|
||||
value = Thread_arch_info (thread, c->data[1])
|
||||
break
|
||||
@ -349,13 +414,7 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
break
|
||||
case CAP_THREAD_SCHEDULE:
|
||||
schedule ()
|
||||
break
|
||||
case CAP_THREAD_DEBUG:
|
||||
dbg_led (true, true, true)
|
||||
dbg_sleep (100)
|
||||
dbg_led (false, false, false)
|
||||
dbg_sleep (100)
|
||||
//dbg_send (c->data[1], 5)
|
||||
do_schedule = true
|
||||
break
|
||||
case CAP_THREAD_REGISTER_INTERRUPT:
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
@ -371,18 +430,45 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
((Thread *)c->cap[0]->protected_data)->flags |= THREAD_FLAG_PRIV
|
||||
reply_cap (CAPTYPE_THREAD | (c->data[1] & CAP_THREAD_ALL_PRIV_RIGHTS), c->cap[0]->protected_data)
|
||||
break
|
||||
case CAP_THREAD_ALLOC_RANGE:
|
||||
// Threads with access to this call are trusted, so not much sanity checking is done.
|
||||
Memory *mem = (Memory *)c->cap[1]->protected_data
|
||||
if !mem->use (c->data[1]):
|
||||
reply_num (0)
|
||||
break
|
||||
unsigned data = phys_alloc (c->data[1])
|
||||
if !data:
|
||||
mem->unuse (c->data[1])
|
||||
reply_num (0)
|
||||
break
|
||||
reply_num (data - 0x80000000)
|
||||
break
|
||||
case CAP_THREAD_ALLOC_PHYSICAL:
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
Page *page = (Page *)c->cap[0]->protected_data
|
||||
page->forget ()
|
||||
if page->data.flags & PAGE_FLAG_PAYING:
|
||||
page->data.flags &= ~PAGE_FLAG_PAYING
|
||||
page->address_space->unuse ()
|
||||
page->data.frame = c->data[1] & PAGE_MASK
|
||||
if c->data[1] & 1:
|
||||
page->data.flags |= PAGE_FLAG_FRAME | PAGE_FLAG_PHYSICAL
|
||||
if !(c->data[2] & 2):
|
||||
if page->data.flags & PAGE_FLAG_PAYING:
|
||||
page->data.flags &= ~PAGE_FLAG_PAYING
|
||||
page->address_space->unuse ()
|
||||
else:
|
||||
page->data.flags |= PAGE_FLAG_FRAME | PAGE_FLAG_PHYSICAL | PAGE_FLAG_UNCACHED
|
||||
// This is for mapping allocated ranges. They are already paid for. Record that.
|
||||
if page->data.flags & PAGE_FLAG_PAYING:
|
||||
page->address_space->unuse ()
|
||||
else:
|
||||
page->data.flags |= PAGE_FLAG_PAYING
|
||||
page->data.frame = c->data[1]
|
||||
page->data.flags |= PAGE_FLAG_FRAME
|
||||
if !(c->data[2] & 1):
|
||||
page->data.flags |= PAGE_FLAG_UNCACHED
|
||||
if !(c->data[2] & 2):
|
||||
page->data.flags |= PAGE_FLAG_PHYSICAL
|
||||
Page_arch_update_mapping (page)
|
||||
break
|
||||
case CAP_THREAD_PHYSICAL_ADDRESS:
|
||||
// Threads with access to this call are trusted, so no sanity checking is done.
|
||||
Page *page = (Page *)c->cap[1]->protected_data
|
||||
reply_num (page->data.frame & ~0xc0000000)
|
||||
break
|
||||
default:
|
||||
break
|
||||
@ -652,7 +738,7 @@ static void capability_invoke (unsigned target, unsigned protected_data, Capabil
|
||||
default:
|
||||
break
|
||||
|
||||
static bool kernel_invoke (unsigned target, unsigned protected_data, Capability::Context *c, Capability *self):
|
||||
static void kernel_invoke (unsigned target, unsigned protected_data, Capability::Context *c, Capability *self):
|
||||
// Kernel calling convention:
|
||||
// data[0] is the request.
|
||||
// cap[0] is the reply capability
|
||||
@ -674,7 +760,7 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
// Kernel call: don't create actual capablities.
|
||||
c->cap[0] = NULL
|
||||
kernel_invoke ((unsigned)c0->target, c0->protected_data, c, c0)
|
||||
return true
|
||||
return
|
||||
if (target & (CAPTYPE_MASK | (1 << CAP_RECEIVER_REPLY))) == (CAPTYPE_RECEIVER | (1 << CAP_RECEIVER_REPLY)):
|
||||
// This is a reply capability.
|
||||
Receiver *r = (Receiver *)protected_data
|
||||
@ -686,16 +772,16 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
while self->sibling_next:
|
||||
self->sibling_next->invalidate ()
|
||||
self->invalidate ()
|
||||
return true
|
||||
return
|
||||
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
||||
// You are not allowed to perform this operation.
|
||||
dbg_send (1, 2)
|
||||
dbg_send (c->data[0])
|
||||
return true
|
||||
return
|
||||
reply = c->cap[0]
|
||||
if c->data[0] == CAP_DEGRADE:
|
||||
reply_cap (target & c->data[1], protected_data)
|
||||
return true
|
||||
return
|
||||
switch target & CAPTYPE_MASK:
|
||||
case CAPTYPE_RECEIVER:
|
||||
receiver_invoke (target, protected_data, c)
|
||||
@ -717,12 +803,13 @@ static bool kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
break
|
||||
default:
|
||||
panic (0x99337744, "invalid capability type invoked")
|
||||
return true
|
||||
return
|
||||
|
||||
bool Capability::invoke (Capability::Context *c):
|
||||
void Capability::invoke (Capability::Context *c):
|
||||
if (unsigned)target & ~KERNEL_MASK:
|
||||
// This is not a kernel capability: send a message to the receiver.
|
||||
return target->send_message (protected_data, c)
|
||||
target->send_message (protected_data, c)
|
||||
return
|
||||
// This is a kernel capability. Use a function to allow optimized call capabilities.
|
||||
reply_receiver = NULL
|
||||
return kernel_invoke ((unsigned)target, protected_data, c, this)
|
||||
kernel_invoke ((unsigned)target, protected_data, c, this)
|
||||
|
432
iris.h
432
iris.h
@ -52,8 +52,8 @@ extern "C" {
|
||||
#define CAP_RECEIVER_SET_OWNER 1
|
||||
#define CAP_RECEIVER_CREATE_CAPABILITY 2
|
||||
#define CAP_RECEIVER_CREATE_CALL_CAPABILITY 3
|
||||
#define CAP_RECEIVER_GET_REPLY_PROTECTED_DATA 4
|
||||
#define CAP_RECEIVER_SET_REPLY_PROTECTED_DATA 5
|
||||
#define CAP_RECEIVER_REPLY_PROTECTED_DATA 4
|
||||
#define CAP_RECEIVER_ALARM 5
|
||||
#define CAP_RECEIVER_ALL_RIGHTS 0x7f
|
||||
/* Not an operation; a capability with this bit set is a call capability. */
|
||||
#define CAP_RECEIVER_CALL 7
|
||||
@ -73,19 +73,19 @@ extern "C" {
|
||||
|
||||
#define CAP_THREAD_INFO 1 /* Details of this are arch-specific. */
|
||||
#define CAP_THREAD_SCHEDULE 2
|
||||
#define CAP_THREAD_DEBUG 3
|
||||
#define CAP_THREAD_ALLOC_RANGE 3
|
||||
#define CAP_THREAD_PHYSICAL_ADDRESS 4
|
||||
#define CAP_THREAD_ALLOC_PHYSICAL 5
|
||||
#define CAP_THREAD_MAKE_PRIV 6
|
||||
#define CAP_THREAD_GET_TOP_MEMORY 7
|
||||
#define CAP_THREAD_REGISTER_INTERRUPT 8
|
||||
#define CAP_THREAD_ALL_RIGHTS 0x1f
|
||||
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV) | (1 << CAP_THREAD_ALLOC_PHYSICAL))
|
||||
#define CAP_THREAD_ALL_RIGHTS 0x0f
|
||||
#define CAP_THREAD_ALL_PRIV_RIGHTS (CAP_THREAD_ALL_RIGHTS | (1 << CAP_THREAD_REGISTER_INTERRUPT) | (1 << CAP_THREAD_GET_TOP_MEMORY) | (1 << CAP_THREAD_MAKE_PRIV) | (1 << CAP_THREAD_ALLOC_PHYSICAL) | (1 << CAP_THREAD_PHYSICAL_ADDRESS))
|
||||
|
||||
/* These get/set_info are not arch-specific. */
|
||||
#define CAP_THREAD_INFO_PC ~0
|
||||
#define CAP_THREAD_INFO_SP ~1
|
||||
#define CAP_THREAD_INFO_FLAGS ~2
|
||||
#define CAP_THREAD_INFO_SLEEP ~3
|
||||
/* Flag values for processor state */
|
||||
#define THREAD_FLAG_PRIV 0x80000000
|
||||
#define THREAD_FLAG_WAITING 0x40000000
|
||||
@ -141,6 +141,11 @@ Capability cap_copy (Capability src)
|
||||
return src | 2;
|
||||
}
|
||||
|
||||
Capability cappage_cap (unsigned base, unsigned idx)
|
||||
{
|
||||
return base | (idx << 2) | 1;
|
||||
}
|
||||
|
||||
typedef struct Message
|
||||
{
|
||||
unsigned data[4];
|
||||
@ -148,11 +153,11 @@ typedef struct Message
|
||||
unsigned protected_data; /* only used for receiving. */
|
||||
} Message;
|
||||
|
||||
static int invoke (Capability target, Message *msg)
|
||||
static void invoke (Capability target, Message *msg)
|
||||
{
|
||||
unsigned ret;
|
||||
__asm__ volatile ("lw $v0, %1\n"
|
||||
"\tlw $a3, %2\n"
|
||||
__asm__ volatile ("lw $v0, %0\n"
|
||||
"\tlw $a3, %1\n"
|
||||
"\tlw $t0, 0($a3)\n"
|
||||
"\tlw $t1, 4($a3)\n"
|
||||
"\tlw $t2, 8($a3)\n"
|
||||
@ -161,20 +166,45 @@ static int invoke (Capability target, Message *msg)
|
||||
"\tlw $a1, 20($a3)\n"
|
||||
"\tlw $a2, 24($a3)\n"
|
||||
"\tlw $a3, 28($a3)\n"
|
||||
"\tsyscall\n"
|
||||
"\tmove %0, $v0"
|
||||
: "=r"(ret)
|
||||
"\tsyscall"
|
||||
:
|
||||
: "m"(target), "m"(msg)
|
||||
: "v0", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wait (Message *msg)
|
||||
static void wait (Message *msg)
|
||||
{
|
||||
int ret;
|
||||
__asm__ volatile ("li $v0, 2\n"
|
||||
"\tsyscall\n"
|
||||
"\tsw $v0, %0\n"
|
||||
"\tlw $v0, %0\n"
|
||||
"\tsw $t0, 0($v0)\n"
|
||||
"\tsw $t1, 4($v0)\n"
|
||||
"\tsw $t2, 8($v0)\n"
|
||||
"\tsw $t3, 12($v0)\n"
|
||||
"\tsw $a0, 16($v0)\n"
|
||||
"\tsw $a1, 20($v0)\n"
|
||||
"\tsw $a2, 24($v0)\n"
|
||||
"\tsw $a3, 28($v0)\n"
|
||||
"\tsw $v1, 32($v0)"
|
||||
:
|
||||
: "m"(msg)
|
||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
}
|
||||
|
||||
static void call (Capability target, Message *msg)
|
||||
{
|
||||
Capability t = cap_copy (target);
|
||||
__asm__ volatile ("lw $v0, %0\n"
|
||||
"\tlw $v1, %1\n"
|
||||
"\tlw $t0, 0($v1)\n"
|
||||
"\tlw $t1, 4($v1)\n"
|
||||
"\tlw $t2, 8($v1)\n"
|
||||
"\tlw $t3, 12($v1)\n"
|
||||
"\tlw $a0, 16($v1)\n"
|
||||
"\tlw $a1, 20($v1)\n"
|
||||
"\tlw $a2, 24($v1)\n"
|
||||
"\tlw $a3, 28($v1)\n"
|
||||
"\tsyscall\n"
|
||||
"\tlw $v0, %1\n"
|
||||
"\tsw $t0, 0($v0)\n"
|
||||
"\tsw $t1, 4($v0)\n"
|
||||
@ -185,167 +215,274 @@ static int wait (Message *msg)
|
||||
"\tsw $a2, 24($v0)\n"
|
||||
"\tsw $a3, 28($v0)\n"
|
||||
"\tsw $v1, 32($v0)"
|
||||
: "=m"(ret)
|
||||
: "m"(msg)
|
||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int call (Capability target, Message *msg)
|
||||
{
|
||||
unsigned ret;
|
||||
Capability t = cap_copy (target);
|
||||
__asm__ volatile ("lw $v0, %1\n"
|
||||
"\tlw $v1, %2\n"
|
||||
"\tlw $t0, 0($v1)\n"
|
||||
"\tlw $t1, 4($v1)\n"
|
||||
"\tlw $t2, 8($v1)\n"
|
||||
"\tlw $t3, 12($v1)\n"
|
||||
"\tlw $a0, 16($v1)\n"
|
||||
"\tlw $a1, 20($v1)\n"
|
||||
"\tlw $a2, 24($v1)\n"
|
||||
"\tlw $a3, 28($v1)\n"
|
||||
"\tsyscall\n"
|
||||
"\tsw $v0, %0\n"
|
||||
"\tlw $v0, %2\n"
|
||||
"\tsw $t0, 0($v0)\n"
|
||||
"\tsw $t1, 4($v0)\n"
|
||||
"\tsw $t2, 8($v0)\n"
|
||||
"\tsw $t3, 12($v0)\n"
|
||||
"\tsw $a0, 16($v0)\n"
|
||||
"\tsw $a1, 20($v0)\n"
|
||||
"\tsw $a2, 24($v0)\n"
|
||||
"\tsw $a3, 28($v0)\n"
|
||||
"\tsw $v1, 32($v0)"
|
||||
: "=m"(ret)
|
||||
:
|
||||
: "m"(t), "m"(msg)
|
||||
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
|
||||
}
|
||||
|
||||
static int invoke_01 (Capability t, unsigned d)
|
||||
static void invoke_01 (Capability t, unsigned d)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.data[0] = d;
|
||||
return invoke (t, &msg);
|
||||
msg.data[1] = 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[0] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static int invoke_02 (Capability t, unsigned d0, unsigned d1)
|
||||
static void invoke_02 (Capability t, unsigned d0, unsigned d1)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
return invoke (t, &msg);
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[0] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static int invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
||||
static void invoke_03 (Capability t, unsigned d0, unsigned d1, unsigned d2)
|
||||
{
|
||||
Message msg;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = d2;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[0] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static void invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = d2;
|
||||
msg.data[3] = d3;
|
||||
return invoke (t, &msg);
|
||||
msg.cap[0] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static int invoke_11 (Capability t, Capability c, unsigned d)
|
||||
static void invoke_11 (Capability t, Capability c, unsigned d)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d;
|
||||
return invoke (t, &msg);
|
||||
msg.data[1] = 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static int invoke_12 (Capability t, Capability c, unsigned d0, unsigned d1)
|
||||
static void invoke_12 (Capability t, Capability c, unsigned d0, unsigned d1)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
return invoke (t, &msg);
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static void invoke_13 (Capability t, Capability c, unsigned d0, unsigned d1, unsigned d2)
|
||||
{
|
||||
Message msg;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = d2;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
invoke (t, &msg);
|
||||
}
|
||||
|
||||
static Capability call_c01 (Capability c, unsigned d)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.cap[0] : 0;
|
||||
msg.data[1] = 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.cap[0];
|
||||
}
|
||||
|
||||
static Capability call_c02 (Capability c, unsigned d0, unsigned d1)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.cap[0] : 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.cap[0];
|
||||
}
|
||||
|
||||
static Capability call_c12 (Capability c, Capability c1, unsigned d0, unsigned d1)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.cap[1] = c1;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.cap[0] : 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.cap[0];
|
||||
}
|
||||
|
||||
static unsigned call_n01 (Capability c, unsigned d)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.data[0] : 0;
|
||||
msg.data[1] = 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static unsigned call_n11 (Capability c, Capability c1, unsigned d)
|
||||
{
|
||||
Message msg;
|
||||
msg.cap[0] = c;
|
||||
msg.cap[1] = c1;
|
||||
msg.data[0] = d;
|
||||
msg.data[1] = 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static unsigned call_n12 (Capability c, Capability c1, unsigned d0, unsigned d1)
|
||||
{
|
||||
Message msg;
|
||||
msg.cap[0] = c;
|
||||
msg.cap[1] = c1;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static unsigned call_n02 (Capability c, unsigned d0, unsigned d1)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.data[0] : 0;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static unsigned call_n03 (Capability c, unsigned d0, unsigned d1, unsigned d2)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = d2;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.data[0] : 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static unsigned call_n13 (Capability c, Capability c1, unsigned d0, unsigned d1, unsigned d2)
|
||||
{
|
||||
Message msg;
|
||||
msg.cap[0] = c;
|
||||
msg.cap[1] = c1;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = d2;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static unsigned call_n04 (Capability c, unsigned d0, unsigned d1, unsigned d2, unsigned d3)
|
||||
{
|
||||
Message msg;
|
||||
int ret;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = d2;
|
||||
msg.data[3] = d3;
|
||||
ret = call (__my_call, &msg);
|
||||
return ret ? msg.data[0] : 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
return msg.data[0];
|
||||
}
|
||||
|
||||
static Capability call_p02 (Capability c, unsigned d0, unsigned d1, unsigned *base_return)
|
||||
{
|
||||
Message msg;
|
||||
msg.cap[0] = c;
|
||||
msg.data[0] = d0;
|
||||
msg.data[1] = d1;
|
||||
msg.data[2] = 0;
|
||||
msg.data[3] = 0;
|
||||
msg.cap[1] = 0;
|
||||
msg.cap[2] = 0;
|
||||
msg.cap[3] = 0;
|
||||
call (__my_call, &msg);
|
||||
*base_return = msg.data[0];
|
||||
return msg.cap[0];
|
||||
}
|
||||
|
||||
static Capability degrade (Capability src, unsigned mask)
|
||||
@ -353,11 +490,6 @@ static Capability degrade (Capability src, unsigned mask)
|
||||
return call_c02 (src, CAP_DEGRADE, mask);
|
||||
}
|
||||
|
||||
static void kdebug (unsigned code)
|
||||
{
|
||||
invoke_02 (__my_thread, CAP_THREAD_DEBUG, code);
|
||||
}
|
||||
|
||||
static void schedule ()
|
||||
{
|
||||
invoke_01 (__my_thread, CAP_THREAD_SCHEDULE);
|
||||
@ -368,24 +500,29 @@ static void register_interrupt (unsigned num)
|
||||
invoke_12 (__my_thread, __my_receiver, CAP_THREAD_REGISTER_INTERRUPT, num);
|
||||
}
|
||||
|
||||
static Capability get_top_memory ()
|
||||
{
|
||||
return call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY);
|
||||
}
|
||||
|
||||
static void unregister_interrupt (unsigned num)
|
||||
{
|
||||
invoke_02 (__my_thread, CAP_THREAD_REGISTER_INTERRUPT, num);
|
||||
}
|
||||
|
||||
static void alloc_physical (Capability page, unsigned address, int cachable)
|
||||
static Capability get_top_memory ()
|
||||
{
|
||||
invoke_12 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, (address & PAGE_MASK) | (cachable ? 1 : 0));
|
||||
return call_c01 (__my_thread, CAP_THREAD_GET_TOP_MEMORY);
|
||||
}
|
||||
|
||||
static int receiver_set_owner (Capability receiver, Capability owner)
|
||||
static void alloc_physical (Capability page, unsigned address, int cachable, int freeable)
|
||||
{
|
||||
return invoke_11 (receiver, owner, CAP_RECEIVER_SET_OWNER);
|
||||
invoke_13 (__my_thread, page, CAP_THREAD_ALLOC_PHYSICAL, address & PAGE_MASK, (cachable ? 1 : 0) | (freeable ? 2 : 0));
|
||||
}
|
||||
|
||||
static unsigned alloc_range (Capability memory, unsigned pages)
|
||||
{
|
||||
return call_n12 (__my_thread, memory, CAP_THREAD_ALLOC_RANGE, pages);
|
||||
}
|
||||
|
||||
static void receiver_set_owner (Capability receiver, Capability owner)
|
||||
{
|
||||
invoke_11 (receiver, owner, CAP_RECEIVER_SET_OWNER);
|
||||
}
|
||||
|
||||
static Capability receiver_create_capability (Capability receiver, unsigned protected_data)
|
||||
@ -393,14 +530,45 @@ static Capability receiver_create_capability (Capability receiver, unsigned prot
|
||||
return call_c02 (receiver, CAP_RECEIVER_CREATE_CAPABILITY, protected_data);
|
||||
}
|
||||
|
||||
static int receiver_get_reply_protected_data (Capability receiver, unsigned data)
|
||||
static unsigned receiver_reply_protected_data (Capability receiver, int set, unsigned data)
|
||||
{
|
||||
return call_n01 (receiver, CAP_RECEIVER_GET_REPLY_PROTECTED_DATA);
|
||||
return call_n03 (receiver, CAP_RECEIVER_REPLY_PROTECTED_DATA, (unsigned)set, data);
|
||||
}
|
||||
|
||||
static int receiver_set_reply_protected_data (Capability receiver, unsigned data)
|
||||
static unsigned receiver_get_reply_protected_data (Capability receiver)
|
||||
{
|
||||
return invoke_02 (receiver, CAP_RECEIVER_SET_REPLY_PROTECTED_DATA, data);
|
||||
return receiver_reply_protected_data (receiver, 0, 0);
|
||||
}
|
||||
|
||||
static unsigned receiver_set_reply_protected_data (Capability receiver, unsigned data)
|
||||
{
|
||||
return receiver_reply_protected_data (receiver, 1, data);
|
||||
}
|
||||
|
||||
static unsigned receiver_alarm (Capability receiver, int set, unsigned data)
|
||||
{
|
||||
return call_n03 (receiver, CAP_RECEIVER_ALARM, (unsigned)set, data);
|
||||
}
|
||||
|
||||
static unsigned receiver_get_alarm (Capability receiver)
|
||||
{
|
||||
return receiver_alarm (receiver, 0, 0);
|
||||
}
|
||||
|
||||
static unsigned receiver_add_alarm (Capability receiver, unsigned data)
|
||||
{
|
||||
return receiver_alarm (receiver, 0, data);
|
||||
}
|
||||
|
||||
static unsigned receiver_set_alarm (Capability receiver, unsigned data)
|
||||
{
|
||||
return receiver_alarm (receiver, 1, data);
|
||||
}
|
||||
|
||||
static void my_sleep (unsigned value, Message *ret)
|
||||
{
|
||||
receiver_set_alarm (__my_receiver, value);
|
||||
wait (ret);
|
||||
}
|
||||
|
||||
static Capability receiver_create_call_capability (Capability receiver)
|
||||
@ -438,37 +606,38 @@ static Capability memory_create_memory (Capability memory)
|
||||
return memory_create (memory, CAPTYPE_MEMORY | REQUEST_MASK);
|
||||
}
|
||||
|
||||
static Capability memory_create_cappage (Capability memory)
|
||||
static Capability memory_create_cappage (Capability memory, unsigned *base_return)
|
||||
{
|
||||
return memory_create (memory, CAPTYPE_CAPPAGE | REQUEST_MASK);
|
||||
return call_p02 (memory, CAP_MEMORY_CREATE, CAPTYPE_CAPPAGE | REQUEST_MASK, base_return);
|
||||
}
|
||||
|
||||
static int memory_destroy (Capability memory, Capability target)
|
||||
static void memory_destroy (Capability memory, Capability target)
|
||||
{
|
||||
return invoke_11 (memory, target, CAP_MEMORY_DESTROY);
|
||||
invoke_11 (memory, target, CAP_MEMORY_DESTROY);
|
||||
}
|
||||
|
||||
/* TODO: #define CAP_MEMORY_LIST 3 */
|
||||
|
||||
static int memory_map (Capability memory, Capability page, unsigned address, int writable)
|
||||
static void memory_map (Capability memory, Capability page, unsigned address, int writable)
|
||||
{
|
||||
if (writable)
|
||||
address |= 1 << CAP_PAGE_WRITE;
|
||||
return invoke_12 (memory, page, CAP_MEMORY_MAP, address);
|
||||
invoke_12 (memory, page, CAP_MEMORY_MAP, address);
|
||||
}
|
||||
|
||||
static Capability memory_mapping (Capability memory, unsigned address)
|
||||
static Capability memory_mapping (Capability memory, void *address)
|
||||
{
|
||||
return call_c02 (memory, CAP_MEMORY_MAPPING, address);
|
||||
return call_c02 (memory, CAP_MEMORY_MAPPING, (unsigned)address);
|
||||
}
|
||||
|
||||
static unsigned memory_limit (Capability memory, unsigned limit)
|
||||
{
|
||||
return call_c02 (memory, CAP_MEMORY_MAPPING, address);
|
||||
return call_c02 (memory, CAP_MEMORY_LIMIT, limit);
|
||||
}
|
||||
|
||||
static void drop (Capability cap)
|
||||
{
|
||||
return;
|
||||
invoke_11 (__my_memory, cap, CAP_MEMORY_DROP);
|
||||
}
|
||||
|
||||
@ -507,29 +676,6 @@ static unsigned thread_wait (Capability thread, int wait)
|
||||
return thread_flags (thread, wait ? THREAD_FLAG_WAITING : 0, THREAD_FLAG_WAITING);
|
||||
}
|
||||
|
||||
static unsigned thread_sleep (Capability thread, unsigned value)
|
||||
{
|
||||
return thread_info (thread, CAP_THREAD_INFO_SLEEP, value, ~0);
|
||||
}
|
||||
|
||||
static int my_sleep (unsigned value, Message *ret)
|
||||
{
|
||||
ret->data[0] = CAP_THREAD_INFO;
|
||||
ret->data[1] = CAP_THREAD_INFO_SLEEP;
|
||||
ret->data[2] = value;
|
||||
ret->data[3] = ~0;
|
||||
ret->cap[0] = 0;
|
||||
ret->cap[1] = 0;
|
||||
ret->cap[2] = 0;
|
||||
ret->cap[3] = 0;
|
||||
return call (__my_thread, ret);
|
||||
}
|
||||
|
||||
static unsigned thread_get_sleep (Capability thread)
|
||||
{
|
||||
return thread_info (thread, CAP_THREAD_INFO_SLEEP, 0, 0);
|
||||
}
|
||||
|
||||
static unsigned thread_get_pc (Capability thread)
|
||||
{
|
||||
return thread_info (thread, CAP_THREAD_INFO_PC, 0, 0);
|
||||
@ -540,9 +686,9 @@ static unsigned thread_get_sp (Capability thread)
|
||||
return thread_info (thread, CAP_THREAD_INFO_SP, 0, 0);
|
||||
}
|
||||
|
||||
static int page_share (Capability page, Capability target, unsigned flags)
|
||||
static void page_share (Capability page, Capability target, unsigned flags)
|
||||
{
|
||||
return invoke_12 (page, target, CAP_PAGE_SHARE, flags);
|
||||
invoke_12 (page, target, CAP_PAGE_SHARE, flags);
|
||||
}
|
||||
|
||||
static unsigned page_flags (Capability page, unsigned new_flags, unsigned mask)
|
||||
@ -550,16 +696,24 @@ static unsigned page_flags (Capability page, unsigned new_flags, unsigned mask)
|
||||
return call_n03 (page, CAP_PAGE_FLAGS, new_flags, mask);
|
||||
}
|
||||
|
||||
static unsigned page_physical_address (Capability page)
|
||||
{
|
||||
return call_n11 (__my_thread, page, CAP_THREAD_PHYSICAL_ADDRESS);
|
||||
}
|
||||
|
||||
static Capability capability_get (Capability cap)
|
||||
{
|
||||
return call_c01 (cap, CAP_CAPABILITY_GET);
|
||||
}
|
||||
|
||||
static int cappage_set (Capability page, Capability cap, unsigned index)
|
||||
static void cappage_set (Capability page, Capability cap, unsigned index)
|
||||
{
|
||||
return invoke_12 (page, cap, CAP_CAPPAGE_SET, index);
|
||||
invoke_12 (page, cap, CAP_CAPPAGE_SET, index);
|
||||
}
|
||||
|
||||
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */
|
||||
#define kdebug(d0, d1) do { unsigned data0 = (unsigned)(d0); unsigned data1 = (unsigned)(d1); __asm__ volatile ("lw $a0, %0\n" "\tlw $a1, %1\n" "\tbreak" :: "m" (data0), "m" (data1)); } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
31
kernel.hhp
31
kernel.hhp
@ -68,10 +68,7 @@ struct Thread : public Object <Thread>:
|
||||
unsigned pc, sp
|
||||
Thread_arch arch
|
||||
unsigned flags
|
||||
unsigned sleep_count
|
||||
Thread *schedule_prev, *schedule_next
|
||||
void sleep ()
|
||||
void unsleep ()
|
||||
void run ()
|
||||
void unrun ()
|
||||
void wait ()
|
||||
@ -94,14 +91,17 @@ struct Capability : public Object <Capability>:
|
||||
Capability *children
|
||||
Capability *sibling_prev, *sibling_next
|
||||
unsigned protected_data
|
||||
bool invoke (Context *c)
|
||||
void invoke (Context *c)
|
||||
void invalidate ()
|
||||
|
||||
struct Receiver : public Object <Receiver>:
|
||||
Thread *owner
|
||||
Receiver *prev_owned, *next_owned
|
||||
Receiver *prev_alarm, *next_alarm
|
||||
unsigned alarm_count
|
||||
Capability *capabilities
|
||||
Message *messages
|
||||
Message *last_message
|
||||
unsigned reply_protected_data
|
||||
bool protected_only
|
||||
void own (Thread *o)
|
||||
@ -122,6 +122,8 @@ struct Page : public Object <Page>:
|
||||
|
||||
struct Cappage : public Object <Cappage>:
|
||||
ShareData data
|
||||
Capability *cap (unsigned idx):
|
||||
return &((Capability *)data.frame)[idx]
|
||||
void forget ()
|
||||
|
||||
struct Memory : public Object <Memory>:
|
||||
@ -140,8 +142,8 @@ struct Memory : public Object <Memory>:
|
||||
inline Page *get_mapping (unsigned address, bool *writable)
|
||||
|
||||
// Allocation of pages.
|
||||
bool use ()
|
||||
void unuse ()
|
||||
bool use (unsigned num = 1)
|
||||
void unuse (unsigned num = 1)
|
||||
unsigned palloc ()
|
||||
unsigned zalloc ()
|
||||
void pfree (unsigned page)
|
||||
@ -151,7 +153,7 @@ struct Memory : public Object <Memory>:
|
||||
void *search_free (unsigned size, void **first)
|
||||
Page *alloc_page ()
|
||||
Thread *alloc_thread ()
|
||||
Message *alloc_message (Receiver *target, unsigned protected_data)
|
||||
Message *alloc_message (Receiver *target)
|
||||
Receiver *alloc_receiver ()
|
||||
Capability *alloc_capability (Receiver *target, Capability *parent, Capability **parent_ptr, unsigned protected_data, Capability *ret = NULL)
|
||||
Capability *clone_capability (Capability *source, bool copy, Capability *ret = NULL)
|
||||
@ -160,7 +162,7 @@ struct Memory : public Object <Memory>:
|
||||
|
||||
void free_page (Page *page)
|
||||
void free_thread (Thread *thread)
|
||||
void free_message (Message *message)
|
||||
void free_message (Receiver *owner, Message *message)
|
||||
void free_receiver (Receiver *receiver)
|
||||
void free_capability (Capability *capability)
|
||||
void free_cappage (Cappage *page)
|
||||
@ -178,26 +180,27 @@ extern "C":
|
||||
void dbg_led (bool one, bool two, bool three)
|
||||
void dbg_sleep (unsigned ms)
|
||||
void dbg_send (unsigned code, unsigned bits = 32)
|
||||
EXTERN unsigned dbg_code
|
||||
|
||||
/// Defined in schedule.ccp
|
||||
void schedule ()
|
||||
void timer_interrupt ()
|
||||
|
||||
struct FreePage:
|
||||
FreePage *next
|
||||
|
||||
EXTERN Memory top_memory
|
||||
EXTERN Thread *sleepers, *runners
|
||||
EXTERN Receiver *first_alarm
|
||||
EXTERN Thread idle
|
||||
EXTERN Memory idle_memory
|
||||
EXTERN Page idle_page
|
||||
EXTERN Thread *first_scheduled, *first_sleeper
|
||||
EXTERN Thread *first_scheduled
|
||||
EXTERN Thread *current
|
||||
EXTERN bool do_schedule
|
||||
|
||||
// Defined in memory.cc
|
||||
unsigned init_memory (unsigned mem)
|
||||
unsigned raw_zalloc ()
|
||||
void raw_pfree (unsigned page)
|
||||
unsigned phys_alloc (unsigned num)
|
||||
void phys_free (unsigned page, unsigned num)
|
||||
|
||||
// Defined by architecture-specific files.
|
||||
void Thread_arch_init (Thread *thread)
|
||||
@ -219,4 +222,6 @@ void Memory::unmap (Page *page, unsigned address):
|
||||
Page *Memory::get_mapping (unsigned address, bool *writable):
|
||||
return Memory_arch_get_mapping (this, address, writable)
|
||||
|
||||
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
||||
|
||||
#endif
|
||||
|
167
memory.ccp
167
memory.ccp
@ -1,53 +1,135 @@
|
||||
#pypp 0
|
||||
#include "kernel.hh"
|
||||
|
||||
static FreePage *zero_pages, *junk_pages
|
||||
|
||||
extern unsigned _end
|
||||
|
||||
static void clear_page (unsigned page):
|
||||
for unsigned i = 0; i < PAGE_SIZE >> 2; ++i:
|
||||
((unsigned *)page)[i] = 0
|
||||
|
||||
static unsigned free_begin
|
||||
static unsigned free_end
|
||||
|
||||
unsigned init_memory (unsigned mem):
|
||||
zero_pages = NULL
|
||||
// Fill junk pages with all memory not currently used.
|
||||
junk_pages = (FreePage *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
|
||||
FreePage *p, *next
|
||||
unsigned count = 1
|
||||
for p = junk_pages, next = p; (unsigned)next - 0x80000000 < mem; p = next, next = (FreePage *)((unsigned)p + PAGE_SIZE):
|
||||
p->next = next
|
||||
++count
|
||||
p->next = NULL
|
||||
return count
|
||||
free_begin = ((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK
|
||||
free_end = (0x80000000 + mem) & PAGE_MASK
|
||||
return (free_end - free_begin) >> PAGE_BITS
|
||||
|
||||
unsigned phys_alloc (unsigned num):
|
||||
if free_begin + num * PAGE_SIZE > free_end:
|
||||
panic (0xaaaaaaaa, "out of memory")
|
||||
unsigned ret = free_begin
|
||||
free_begin += num * PAGE_SIZE
|
||||
for unsigned i = 0; i < num; ++i:
|
||||
clear_page (ret + i * PAGE_SIZE)
|
||||
return ret
|
||||
|
||||
void phys_free (unsigned page, unsigned num):
|
||||
// Not supported.
|
||||
|
||||
#if 0
|
||||
struct FreePages:
|
||||
FreePages *prev, *next
|
||||
unsigned num
|
||||
|
||||
static FreePages *first_free
|
||||
|
||||
unsigned init_memory (unsigned mem):
|
||||
first_free = (FreePages *)(((unsigned)&_end + ~PAGE_MASK) & PAGE_MASK)
|
||||
first_free->prev = NULL
|
||||
first_free->next = NULL
|
||||
first_free->num = ((mem & PAGE_MASK) - ((unsigned)first_free - 0x80000000)) >> PAGE_BITS
|
||||
return first_free->num
|
||||
|
||||
unsigned phys_alloc (unsigned num):
|
||||
FreePages *choice = NULL
|
||||
for FreePages *p = first_free; p; p = p->next:
|
||||
if p->num < num:
|
||||
continue
|
||||
if choice && choice->num < p->num:
|
||||
continue
|
||||
choice = p
|
||||
if !choice:
|
||||
// TODO: reorganizing may work to allow allocation.
|
||||
panic (0x01100223, "out of large enough memory")
|
||||
return 0
|
||||
if choice->num == num:
|
||||
if choice->prev:
|
||||
choice->prev->next = choice->next
|
||||
else:
|
||||
first_free = choice->next
|
||||
if choice->next:
|
||||
choice->next->prev = choice->prev
|
||||
clear_page ((unsigned)choice, num)
|
||||
return (unsigned)choice
|
||||
choice->num -= num
|
||||
unsigned ret = (unsigned)choice + (choice->num << PAGE_BITS)
|
||||
clear_page (ret, num)
|
||||
return ret
|
||||
|
||||
void phys_free (unsigned page, unsigned num):
|
||||
return
|
||||
unsigned size = num << PAGE_BITS
|
||||
if !first_free || (unsigned)first_free > page:
|
||||
// This is the first free block.
|
||||
FreePages *n = (FreePages *)page
|
||||
n->prev = NULL
|
||||
if (unsigned)first_free == page + size:
|
||||
// It fits exactly before the previous first free block.
|
||||
n->next = first_free->next
|
||||
n->num = num + first_free->num
|
||||
else:
|
||||
// It is a new block.
|
||||
n->next = first_free
|
||||
n->num = num
|
||||
first_free = n
|
||||
if n->next:
|
||||
n->next->prev = n
|
||||
return
|
||||
FreePages *p
|
||||
for p = first_free; p->next && (unsigned)p->next < page; p = p->next:
|
||||
// Do nothing.
|
||||
// The new block should be inserted directly after p.
|
||||
if (unsigned)p->next == page + size:
|
||||
// It can be merged with the block after it: do that.
|
||||
FreePages *n = (FreePages *)page
|
||||
n->prev = p
|
||||
n->next = p->next->next
|
||||
if n->next:
|
||||
n->next->prev = n
|
||||
n->num = num + p->next->num
|
||||
p->next = n
|
||||
if (unsigned)p + (p->num << PAGE_BITS) == (unsigned)n:
|
||||
// It can also be merged with the page before it: do that as well.
|
||||
p->num += n->num
|
||||
p->next = n->next
|
||||
if p->next:
|
||||
p->next->prev = p
|
||||
return
|
||||
// The new block cannot be merged with the block after it.
|
||||
if (unsigned)p + (p->num << PAGE_BITS) == page:
|
||||
// But it can be merged with the one before it: do that.
|
||||
p->num += num
|
||||
return
|
||||
// The new block cannot be merged at all.
|
||||
FreePages *n = (FreePages *)page
|
||||
n->next = p->next
|
||||
n->prev = p
|
||||
if n->next:
|
||||
n->next->prev = n
|
||||
p->next = n
|
||||
n->num = num
|
||||
#endif
|
||||
|
||||
unsigned raw_zalloc ():
|
||||
FreePage *ret = zero_pages
|
||||
if !ret:
|
||||
ret = junk_pages
|
||||
junk_pages = ret->next
|
||||
for unsigned i = 0; i < (PAGE_SIZE >> 2); ++i:
|
||||
((unsigned *)ret)[i] = 0
|
||||
else:
|
||||
zero_pages = ret->next
|
||||
ret->next = NULL
|
||||
return (unsigned)ret
|
||||
return phys_alloc (1)
|
||||
|
||||
void raw_pfree (unsigned page):
|
||||
if !page:
|
||||
return
|
||||
FreePage *p = (FreePage *)page
|
||||
p->next = junk_pages
|
||||
junk_pages = p
|
||||
return phys_free (page, 1)
|
||||
|
||||
unsigned Memory::palloc ():
|
||||
if !use ():
|
||||
return NULL
|
||||
FreePage *ret = junk_pages
|
||||
if !ret:
|
||||
ret = zero_pages
|
||||
zero_pages = ret->next
|
||||
else:
|
||||
junk_pages = ret->next
|
||||
return (unsigned)ret
|
||||
|
||||
unsigned Memory::zalloc ():
|
||||
if !use ():
|
||||
assert (false)
|
||||
return NULL
|
||||
return raw_zalloc ()
|
||||
|
||||
@ -55,9 +137,8 @@ void Memory::pfree (unsigned page):
|
||||
unuse ()
|
||||
return raw_pfree (page)
|
||||
|
||||
void Memory::zfree (unsigned page):
|
||||
unuse ()
|
||||
FreePage *p = (FreePage *)page
|
||||
p->next = zero_pages
|
||||
zero_pages = p
|
||||
unsigned Memory::palloc ():
|
||||
return zalloc ()
|
||||
|
||||
void Memory::zfree (unsigned page):
|
||||
pfree (page)
|
||||
|
@ -27,7 +27,7 @@ OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
|
||||
arch_kernel_sources = mips/interrupts.cc mips/test.cc mips/arch.cc
|
||||
boot_sources = mips/init.cc
|
||||
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
|
||||
arch_headers = mips/arch.hh
|
||||
arch_headers = mips/arch.hh mips/jz4730.hh
|
||||
boot_threads = keyboard lcd
|
||||
|
||||
uimage:
|
||||
@ -35,11 +35,11 @@ uimage:
|
||||
mips/entry.o: $(boot_threads)
|
||||
mips/init.o: TARGET_FLAGS = -I/usr/include
|
||||
$(boot_threads): TARGET_FLAGS = -I.
|
||||
$(boot_threads): mips/jz4730.hh boot-programs/devices.hh
|
||||
$(boot_threads): boot-programs/devices.hh
|
||||
|
||||
# Transform ':' into ';' so vim doesn't think there are errors.
|
||||
uimage: kernel.raw.gz Makefile mips/Makefile.arch
|
||||
mkimage -A MIPS -O Linux -C gzip -a $(load) -e 0x$(shell /bin/sh -c '$(OBJDUMP) -t kernel | grep __start$$ | cut -b-8') -n "Shevek's kernel" -d $< $@ | sed -e 's/:/;/g'
|
||||
mkimage -A MIPS -O Linux -C gzip -a $(load) -e 0xa$(shell /bin/sh -c '$(OBJDUMP) -t kernel | grep __start$$ | cut -b2-8') -n "Iris" -d $< $@ | sed -e 's/:/;/g'
|
||||
|
||||
%.o:%.S Makefile mips/Makefile.arch mips/arch.hh
|
||||
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@
|
||||
@ -49,7 +49,7 @@ kernel: mips/entry.o $(subst .cc,.o,$(kernel_sources)) mips/boot.o $(subst .cc,.
|
||||
$(LD) --omagic -Ttext $(load) $^ -o $@
|
||||
|
||||
%.raw: %
|
||||
$(OBJCOPY) -S $(addprefix --remove-section=.,$(junk)) -Obinary $< $@
|
||||
$(OBJCOPY) -S $(OBJCOPYFLAGS) -Obinary $< $@
|
||||
|
||||
%.gz: %
|
||||
gzip < $< > $@
|
||||
|
@ -318,3 +318,4 @@ void arch_register_interrupt (unsigned num, Receiver *r):
|
||||
intc_unmask_irq (num)
|
||||
else:
|
||||
intc_mask_irq (num)
|
||||
dbg_code = 0
|
||||
|
@ -25,13 +25,15 @@
|
||||
#define Status 12
|
||||
#define Config 16
|
||||
|
||||
// Note that this code starts at 0xa0000000, even though it is linked for
|
||||
// 0x80000000. This means that until the jump below, it must be PIC.
|
||||
__start:
|
||||
bal 1f
|
||||
nop
|
||||
.word _gp
|
||||
// For some reason the disassembler considers everything
|
||||
// after __start non-code until the next label. So I add a label.
|
||||
start_hack_for_disassembler:
|
||||
nop
|
||||
.word _gp
|
||||
1: lw $gp, 0($ra)
|
||||
|
||||
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
||||
|
@ -110,10 +110,11 @@ static unsigned mkcap (Memory *mem, unsigned type, void *obj):
|
||||
static void init_threads ():
|
||||
Thread *previous = NULL
|
||||
first_scheduled = NULL
|
||||
first_sleeper = NULL
|
||||
first_alarm = NULL
|
||||
Receiver *init_receiver = NULL
|
||||
for unsigned i = 0; i < NUM_THREADS; ++i:
|
||||
Memory *mem = top_memory.alloc_memory ()
|
||||
assert (mem)
|
||||
Thread *thread = mem->alloc_thread ()
|
||||
Page **pages = (Page **)mem->zalloc ()
|
||||
Elf32_Ehdr *header = (Elf32_Ehdr *)thread_start[i]
|
||||
@ -134,36 +135,42 @@ static void init_threads ():
|
||||
thread->sp = 0x80000000
|
||||
for unsigned section = 0; section < header->e_shnum; ++section:
|
||||
Elf32_Shdr *shdr = (Elf32_Shdr *)(thread_start[i] + header->e_shoff + section * header->e_shentsize)
|
||||
if !(shdr->sh_flags & SHF_ALLOC):
|
||||
if ~shdr->sh_flags & SHF_ALLOC:
|
||||
continue
|
||||
bool writable = shdr->sh_flags & SHF_WRITE
|
||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||
if shdr->sh_type != SHT_NOBITS:
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p <= ((shdr->sh_addr + shdr->sh_size - 1) & PAGE_MASK); p += PAGE_SIZE:
|
||||
unsigned idx = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||
unsigned idx = file_offset + section_offset
|
||||
if !pages[idx]:
|
||||
pages[idx] = mem->alloc_page ()
|
||||
pages[idx]->data.frame = thread_start[i] + (idx << PAGE_BITS)
|
||||
pages[idx]->data.flags = (writable ? PAGE_FLAG_WRITABLE : 0) | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||
pages[idx]->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||
++top_memory.limit
|
||||
mem->use ()
|
||||
if !mem->map (pages[idx], p, writable):
|
||||
panic (0x22446688, "unable to map initial page")
|
||||
else:
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p <= ((shdr->sh_addr + shdr->sh_size - 1) & PAGE_MASK); p += PAGE_SIZE:
|
||||
bool write = false
|
||||
Page *page = mem->get_mapping (p, &write)
|
||||
if !writable:
|
||||
panic (0x33399993, "unwritable bss section")
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||
Page *page = mem->get_mapping (p, &writable)
|
||||
if !page:
|
||||
page = mem->alloc_page ()
|
||||
if !page:
|
||||
panic (0x00220022, "out of memory")
|
||||
page->data.frame = mem->zalloc ()
|
||||
page->data.flags = (writable ? PAGE_FLAG_WRITABLE : 0) | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||
if !page->data.frame || !mem->map (page, p, true):
|
||||
if !page->data.frame:
|
||||
panic (0x02220022, "out of memory");
|
||||
page->data.flags = PAGE_FLAG_WRITABLE | PAGE_FLAG_PAYING | PAGE_FLAG_FRAME
|
||||
if !mem->map (page, p, true):
|
||||
panic (0x33557799, "unable to map initial bss page")
|
||||
else:
|
||||
if !write:
|
||||
if !writable:
|
||||
panic (0x20203030, "bss section starts on read-only page")
|
||||
for unsigned a = p; a < p + PAGE_SIZE; a += 4:
|
||||
for unsigned a = p; a < ((p + PAGE_SIZE) & PAGE_MASK); a += 4:
|
||||
if a >= shdr->sh_addr + shdr->sh_size:
|
||||
break
|
||||
if a < shdr->sh_addr:
|
||||
@ -201,11 +208,10 @@ static void init_threads ():
|
||||
|
||||
// Initialize the kernel, finish by falling into the idle task.
|
||||
void init (unsigned mem):
|
||||
dbg_code = 0
|
||||
// Disable interrupts and set interrupt vectors to normal.
|
||||
cp0_set0 (CP0_STATUS)
|
||||
// Initialize kernel variables to empty.
|
||||
sleepers = NULL
|
||||
runners = NULL
|
||||
unsigned count = init_memory (mem)
|
||||
// initialize system control coprocessor.
|
||||
init_cp0 ()
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "../kernel.hh"
|
||||
|
||||
static void handle_exit (Thread *old_current):
|
||||
if !current:
|
||||
if !current || (current == &idle):
|
||||
schedule ()
|
||||
if !current:
|
||||
current = &idle
|
||||
@ -77,7 +77,6 @@ Thread *tlb_refill ():
|
||||
Thread *interrupt ():
|
||||
//panic (0x88877722, "Interrupt")
|
||||
Thread *old_current = current
|
||||
//dbg_send (INTC_IPR)
|
||||
unsigned ipr = INTC_IPR
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
if ipr & (1 << i):
|
||||
@ -94,6 +93,7 @@ Thread *interrupt ():
|
||||
c.data[j] = 0
|
||||
c.cap[j] = NULL
|
||||
c.copy[j] = false
|
||||
dbg_code = (unsigned)arch_interrupt_receiver[i]->owner
|
||||
arch_interrupt_receiver[i]->send_message (i, &c)
|
||||
if ipr & (1 << IRQ_OST0):
|
||||
ost_clear_uf (0)
|
||||
@ -118,15 +118,12 @@ static void arch_invoke ():
|
||||
bool wait
|
||||
Thread *caller = current
|
||||
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
||||
do_schedule = false
|
||||
if wait:
|
||||
caller->wait ()
|
||||
if !target:
|
||||
// There must be no action here.
|
||||
//dbg_send (3, 2)
|
||||
//dbg_send (caller->arch.v0)
|
||||
// Calling an invalid capability always fails.
|
||||
caller->arch.v0 = 0
|
||||
else:
|
||||
if wait:
|
||||
caller->wait ()
|
||||
Capability::Context c
|
||||
c.cap[0] = caller->address_space->find_capability (caller->arch.a0, &c.copy[0])
|
||||
c.cap[1] = caller->address_space->find_capability (caller->arch.a1, &c.copy[1])
|
||||
@ -136,8 +133,9 @@ static void arch_invoke ():
|
||||
c.data[1] = caller->arch.t1
|
||||
c.data[2] = caller->arch.t2
|
||||
c.data[3] = caller->arch.t3
|
||||
caller->arch.v0 = target->invoke (&c) ? 1 : 0
|
||||
if caller != current && caller != &idle && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
|
||||
target->invoke (&c)
|
||||
// If the caller received a reply from the kernel, it is no longer set as current. Don't let it lose its timeslice.
|
||||
if caller != current && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING && !do_schedule:
|
||||
current = caller
|
||||
|
||||
/// A general exception has occurred.
|
||||
@ -160,15 +158,21 @@ Thread *exception ():
|
||||
panic (0x31223344, "TLB load or instruction fetch.")
|
||||
case 3:
|
||||
// TLB store.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
panic (0x41223344, "TLB store.")
|
||||
case 4:
|
||||
// Address error load or instruction fetch.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a)
|
||||
panic (0x51223344, "Address error load or instruction fetch.")
|
||||
case 5:
|
||||
// Address error store.
|
||||
unsigned a
|
||||
cp0_get (CP0_EPC, a)
|
||||
dbg_send (a, 16)
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
dbg_send (a, 32)
|
||||
panic (0x61223344, "Address error store.")
|
||||
case 6:
|
||||
// Bus error instruction fetch.
|
||||
@ -183,7 +187,10 @@ Thread *exception ():
|
||||
break
|
||||
case 9:
|
||||
// Breakpoint.
|
||||
panic (0x91223344, "Breakpoint.")
|
||||
//panic (0x91223344, "Breakpoint.")
|
||||
dbg_send (current->arch.a0, current->arch.a1)
|
||||
current->pc += 4
|
||||
break
|
||||
case 10:
|
||||
// Reserved instruction.
|
||||
panic (0xa1223344, "Reserved instruction.")
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
// Main clock, for cpu, serial port, and with divisors for most other hardware
|
||||
#define JZ_EXTAL 3686400
|
||||
//#define JZ_EXTAL 3072000
|
||||
// RTC clock
|
||||
#define RTC_CLOCK 32768
|
||||
|
||||
@ -36,7 +35,7 @@
|
||||
#define LCD_PHYSICAL 0x13050000
|
||||
#define CIM_PHYSICAL 0x13060000
|
||||
#define ETH_PHYSICAL 0x13100000
|
||||
#define NBM_PHYSICAL 0x13F00000
|
||||
#define NBM_PHYSICAL 0x13f00000
|
||||
#define CPM_PHYSICAL 0x10000000
|
||||
#define INTC_PHYSICAL 0x10001000
|
||||
#define OST_PHYSICAL 0x10002000
|
||||
@ -98,49 +97,53 @@
|
||||
|
||||
#else
|
||||
// In user space, they just need a mapping.
|
||||
#define HARB_BASE 0x00000000
|
||||
#define EMC_BASE 0x00001000
|
||||
#define DMAC_BASE 0x00002000
|
||||
#define UHC_BASE 0x00003000
|
||||
#define UDC_BASE 0x00004000
|
||||
#define LCD_BASE 0x00005000
|
||||
#define CIM_BASE 0x00006000
|
||||
#define ETH_BASE 0x00007000
|
||||
#define NBM_BASE 0x00008000
|
||||
#define CPM_BASE 0x00009000
|
||||
#define INTC_BASE 0x0000a000
|
||||
#define OST_BASE 0x0000b000
|
||||
#define RTC_BASE 0x0000c000
|
||||
#define WDT_BASE 0x0000d000
|
||||
#define GPIO_BASE 0x0000e000
|
||||
#define AIC_BASE 0x0000f000
|
||||
#define MSC_BASE 0x00010000
|
||||
#define UART0_BASE 0x00011000
|
||||
#define UART1_BASE 0x00012000
|
||||
#define UART2_BASE 0x00013000
|
||||
#define UART3_BASE 0x00014000
|
||||
#define FIR_BASE 0x00015000
|
||||
#define SCC_BASE 0x00016000
|
||||
#define SCC0_BASE 0x00017000
|
||||
#define I2C_BASE 0x00018000
|
||||
#define SSI_BASE 0x00019000
|
||||
#define SCC1_BASE 0x0001a000
|
||||
#define PWM0_BASE 0x0001b000
|
||||
#define PWM1_BASE 0x0001c000
|
||||
#define DES_BASE 0x0001d000
|
||||
#define UPRT_BASE 0x0001e000
|
||||
#define KBC_BASE 0x0001f000
|
||||
#define UNMAPPED_BASE 0x00000000
|
||||
|
||||
#define HARB_BASE 0x00001000
|
||||
#define EMC_BASE 0x00002000
|
||||
#define DMAC_BASE 0x00003000
|
||||
#define UHC_BASE 0x00004000
|
||||
#define UDC_BASE 0x00005000
|
||||
#define LCD_BASE 0x00006000
|
||||
#define CIM_BASE 0x00007000
|
||||
#define ETH_BASE 0x00008000
|
||||
#define NBM_BASE 0x00009000
|
||||
#define CPM_BASE 0x0000a000
|
||||
#define INTC_BASE 0x0000b000
|
||||
#define OST_BASE 0x0000c000
|
||||
#define RTC_BASE 0x0000d000
|
||||
#define WDT_BASE 0x0000e000
|
||||
#define GPIO_BASE 0x0000f000
|
||||
#define AIC_BASE 0x00010000
|
||||
#define MSC_BASE 0x00011000
|
||||
#define UART0_BASE 0x00012000
|
||||
#define UART1_BASE 0x00013000
|
||||
#define UART2_BASE 0x00014000
|
||||
#define UART3_BASE 0x00015000
|
||||
#define FIR_BASE 0x00016000
|
||||
#define SCC_BASE 0x00017000
|
||||
#define SCC0_BASE 0x00018000
|
||||
#define I2C_BASE 0x00019000
|
||||
#define SSI_BASE 0x0001a000
|
||||
#define SCC1_BASE 0x0001b000
|
||||
#define PWM0_BASE 0x0001c000
|
||||
#define PWM1_BASE 0x0001d000
|
||||
#define DES_BASE 0x0001e000
|
||||
#define UPRT_BASE 0x0001f000
|
||||
#define KBC_BASE 0x00020000
|
||||
|
||||
// Default lcd framebuffer mapping space.
|
||||
#define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00021000)
|
||||
|
||||
// Map IO memory (requires a priviledged __my_thread capability).
|
||||
#include <iris.h>
|
||||
static void __map_io (unsigned physical, unsigned mapping):
|
||||
Capability page = memory_create_page (__my_memory)
|
||||
// 0 means not cachable.
|
||||
alloc_physical (page, physical, 0)
|
||||
// 0 means not cachable; 0 means don't free when done.
|
||||
alloc_physical (page, physical, 0, 0)
|
||||
// 1 means writable.
|
||||
memory_map (__my_memory, page, mapping, 1)
|
||||
//drop (page)
|
||||
#endif
|
||||
drop (page)
|
||||
|
||||
#define map_harb() do { __map_io (HARB_PHYSICAL, HARB_BASE); } while (0)
|
||||
#define map_emc() do { __map_io (EMC_PHYSICAL, EMC_BASE); } while (0)
|
||||
@ -175,6 +178,8 @@ static void __map_io (unsigned physical, unsigned mapping):
|
||||
#define map_uprt() do { __map_io (UPRT_PHYSICAL, UPRT_BASE); } while (0)
|
||||
#define map_kbc() do { __map_io (KBC_PHYSICAL, KBC_BASE); } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define REG8(x) (*(volatile unsigned char *)(x))
|
||||
#define REG16(x) (*(volatile unsigned short *)(x))
|
||||
#define REG32(x) (*(volatile unsigned *)(x))
|
||||
|
@ -97,6 +97,8 @@ void dbg_sleep (unsigned ms):
|
||||
__gpio_as_output (CAPSLOCKLED_IO)
|
||||
|
||||
void dbg_send (unsigned code, unsigned bits):
|
||||
if bits > 32:
|
||||
bits = 32
|
||||
for int i = bits - 1; i >= 0; --i:
|
||||
bool on = code & (1 << i)
|
||||
dbg_led (false, false, false)
|
||||
|
60
schedule.ccp
60
schedule.ccp
@ -34,28 +34,11 @@ static void unrun_thread (Thread *thread):
|
||||
if thread->schedule_next:
|
||||
thread->schedule_next->schedule_prev = thread->schedule_prev
|
||||
|
||||
void Thread::sleep ():
|
||||
schedule_next = first_sleeper
|
||||
if schedule_next:
|
||||
schedule_next->schedule_prev = this
|
||||
schedule_prev = NULL
|
||||
first_sleeper = this
|
||||
|
||||
void Thread::unsleep ():
|
||||
if schedule_next:
|
||||
schedule_next->schedule_prev = schedule_prev
|
||||
if schedule_prev:
|
||||
schedule_prev->schedule_next = schedule_next
|
||||
else:
|
||||
first_sleeper = schedule_next
|
||||
|
||||
void Thread::run ():
|
||||
if flags & THREAD_FLAG_RUNNING:
|
||||
return
|
||||
flags |= THREAD_FLAG_RUNNING
|
||||
if flags & THREAD_FLAG_WAITING:
|
||||
if sleep_count != ~0:
|
||||
sleep ()
|
||||
if is_waiting ():
|
||||
return
|
||||
run_thread (this)
|
||||
|
||||
@ -63,48 +46,41 @@ void Thread::unrun ():
|
||||
if !(flags & THREAD_FLAG_RUNNING):
|
||||
return
|
||||
flags &= ~THREAD_FLAG_RUNNING
|
||||
if flags & THREAD_FLAG_WAITING:
|
||||
if sleep_count != ~0:
|
||||
unsleep ()
|
||||
if is_waiting ():
|
||||
return
|
||||
unrun_thread (this)
|
||||
|
||||
void Thread::unwait ():
|
||||
if !(flags & THREAD_FLAG_WAITING):
|
||||
return
|
||||
flags &= ~THREAD_FLAG_WAITING
|
||||
if sleep_count != ~0:
|
||||
unsleep ()
|
||||
if flags & THREAD_FLAG_RUNNING:
|
||||
run_thread (this)
|
||||
|
||||
static void sleep_tick (Thread *thread):
|
||||
if !thread->sleep_count:
|
||||
thread->unwait ()
|
||||
// Time-out: let the thread know with a special message.
|
||||
static void alarm_tick (Receiver *recv):
|
||||
if !recv->alarm_count:
|
||||
// Send message and stop counting.
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.data[i] = 0
|
||||
c.cap[i] = NULL
|
||||
c.copy[i] = false
|
||||
Thread_arch_receive (thread, ~0, &c)
|
||||
// Fall through to let sleep be set to ~0, so the next wait will be infinitely long again.
|
||||
--thread->sleep_count
|
||||
recv->send_message (~0, &c)
|
||||
if recv->prev_alarm:
|
||||
recv->prev_alarm->next_alarm = recv->next_alarm
|
||||
else:
|
||||
first_alarm = recv->next_alarm
|
||||
if recv->next_alarm:
|
||||
recv->next_alarm->prev_alarm = recv->prev_alarm
|
||||
// Fall through to let alarm be set to ~0, so the next wait will be infinitely long again.
|
||||
--recv->alarm_count
|
||||
|
||||
void Thread::wait ():
|
||||
if flags & THREAD_FLAG_WAITING:
|
||||
return
|
||||
if flags & THREAD_FLAG_RUNNING:
|
||||
unrun_thread (this)
|
||||
flags |= THREAD_FLAG_WAITING
|
||||
if sleep_count != ~0:
|
||||
sleep ()
|
||||
// Try to receive a message from a Receiver immediately.
|
||||
for Receiver *r = receivers; r; r = r->next_owned:
|
||||
if r->try_deliver ():
|
||||
return
|
||||
if sleep_count != ~0:
|
||||
sleep_tick (this)
|
||||
|
||||
void schedule ():
|
||||
Thread *old = current
|
||||
@ -117,10 +93,10 @@ void schedule ():
|
||||
|
||||
void timer_interrupt ():
|
||||
//panic (0x88877744, "Timer interrupt")
|
||||
Thread *thread, *next
|
||||
for thread = first_sleeper; thread; thread = next:
|
||||
next = thread->next
|
||||
sleep_tick (thread)
|
||||
Receiver *recv, *next
|
||||
for recv = first_alarm; recv; recv = next:
|
||||
next = recv->next
|
||||
alarm_tick (recv)
|
||||
schedule ()
|
||||
//#ifndef NDEBUG
|
||||
//static bool ledstate = false
|
||||
|
Loading…
Reference in New Issue
Block a user