28#ifndef MRBC_SCHEDULER_EXIT
29#define MRBC_SCHEDULER_EXIT 0
32#define MRBC_MUTEX_TRACE(...) ((void)0)
34#if !defined(MRBC_TIMESLICE_TICK_COUNT) || (MRBC_TIMESLICE_TICK_COUNT <= 0)
35#error "MRBC_TIMESLICE_TICK_COUNT must be a natural number."
37#define DEPRECATED(msg) do { \
38 static const char msg1[] = "Warning: "; \
39 static const char msg2[] = " method will be removed in future version.\n"; \
40 mrbc_hal_write(2, msg1, sizeof(msg1)-1); \
41 mrbc_hal_write(2, msg, strlen(msg)); \
42 mrbc_hal_write(2, msg2, sizeof(msg2)-1); \
48#define NUM_TCB_QUEUE 4
50#define q_dormant_ (tcb_queue_[0])
51#define q_ready_ (tcb_queue_[1])
52#define q_waiting_ (tcb_queue_[2])
53#define q_suspended_ (tcb_queue_[3])
57#if defined(MRBC_TASK_SCHEDULER_HOOK)
58static void (*scheduler_hook_)(
void *ud);
59static void *scheduler_hook_ud_;
66#if defined(MRBC_TASK_SCHEDULER_HOOK)
75void mrbc_task_set_scheduler_hook(
void (*fn)(
void *ud),
void *ud)
78 scheduler_hook_ud_ = ud;
99 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
103 if((*pp_q == NULL) ||
112 while( p->
next != NULL ) {
131 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
134 if( *pp_q == p_tcb ) {
142 if( p->
next == p_tcb ) {
151 assert(!
"Not found target task in queue.");
209#if defined(__EMSCRIPTEN__)
210#include <emscripten.h>
219 if( (tcb != NULL) && (tcb->
timeslice != 0) ) {
226 int flag_preemption = 0;
232 while( tcb != NULL ) {
238 if( (int32_t)(wake -
tick_) < 0 ) {
279 memset(tcb, 0, size);
280#if defined(MRBC_DEBUG)
281 memcpy( tcb->obj_mark_,
"TCB", 4 );
284 tcb->
state = task_state;
317 mrbc_hal_disable_irq();
320 mrbc_hal_enable_irq();
336 mrbc_hal_disable_irq();
338 mrbc_hal_enable_irq();
359 if( (tcb->
name[i] = *name++) == 0 )
break;
373 mrbc_hal_disable_irq();
377 if( strcmp( tcb->
name, name ) == 0 )
goto RETURN_TCB;
382 mrbc_hal_enable_irq();
397 mrbc_hal_disable_irq();
407 mrbc_hal_enable_irq();
416 mrbc_hal_disable_irq();
420 mrbc_hal_enable_irq();
425 mrbc_hal_disable_irq();
434 mrbc_hal_enable_irq();
454#if defined(MRBC_TASK_SCHEDULER_HOOK)
457 if( scheduler_hook_ ) scheduler_hook_(scheduler_hook_ud_);
461#if MRBC_SCHEDULER_EXIT
462 mrbc_hal_disable_irq();
464 mrbc_hal_enable_irq();
465 if( flag_exit )
return ret;
475 tcb->
timeslice = MRBC_TIMESLICE_TICK_COUNT;
477#if !defined(MRBC_NO_TIMER)
488 if( ret_vm_run != 0 )
break;
497 if( ret_vm_run != 0 ) {
499 if( ret_vm_run != 1 ) ret = ret_vm_run;
509 mrbc_hal_disable_irq();
512 mrbc_hal_enable_irq();
523#if defined(__EMSCRIPTEN__)
528#if defined(MRBC_TASK_SCHEDULER_HOOK)
530 if (scheduler_hook_) scheduler_hook_(scheduler_hook_ud_);
542 tcb->
timeslice = MRBC_TIMESLICE_TICK_COUNT;
550 if (ret_vm_run != 0) {
558 mrbc_hal_disable_irq();
561 mrbc_hal_enable_irq();
577 mrbc_hal_disable_irq();
588 mrbc_hal_enable_irq();
605 int64_t ticks = (int64_t)(ms / MRBC_TICK_UNIT) + !!(ms % MRBC_TICK_UNIT);
606 if( ticks > INT32_MAX ) {
612 uint32_t deadline =
tick_ + (uint32_t)ticks;
627 return (int32_t)(deadline -
tick_) <= 0;
654 switch( tcb->
state ) {
662 mrbc_hal_disable_irq();
675 mrbc_hal_enable_irq();
707 mrbc_hal_disable_irq();
713 mrbc_hal_enable_irq();
726 mrbc_hal_disable_irq();
730 mrbc_hal_enable_irq();
745 int flag_to_ready_state = (tcb->
reason == 0);
747 mrbc_hal_disable_irq();
755 mrbc_hal_enable_irq();
794 mrbc_hal_disable_irq();
802 mrbc_hal_enable_irq();
816 if( mutex == NULL ) {
838 mrbc_hal_disable_irq();
841 if( mutex->
lock == 0 ) {
851 if( mutex->
tcb == tcb ) {
865 mrbc_hal_enable_irq();
882 if( !mutex->
lock )
return 1;
883 if( mutex->
tcb != tcb )
return 2;
885 mrbc_hal_disable_irq();
922 mrbc_hal_enable_irq();
939 mrbc_hal_disable_irq();
941 if( mutex->
lock == 0 ) {
952 mrbc_hal_enable_irq();
1092 mrbc_hal_disable_irq();
1101 mrbc_hal_enable_irq();
1117 mrbc_hal_disable_irq();
1126 mrbc_hal_enable_irq();
1206 if( n < 0 || n > 255 ) {
1245 static const char *status_name[] =
1246 {
"DORMANT",
"READY",
"WAITING ",
"",
"SUSPENDED" };
1247 static const char *reason_name[] =
1248 {
"",
"SLEEP",
"MUTEX",
"",
"JOIN" };
1412 const char *byte_code;
1538 if( res == 0 )
return;
1541 assert(!
"Mutex recursive lock.");
1553 if( res == 0 )
return;
1556 assert(!
"Mutex unlock error. not owner or not locked.");
1624#include "_autogen_class_rrt0.h"
1636 static uint8_t flag_hal_init_called = 0;
1638 if( !flag_hal_init_called ) {
1640 flag_hal_init_called = 1;
1653 for(
int i = 0; i <
sizeof(rrt0_cls)/
sizeof(rrt0_cls[0]); i++ ) {
1683 if( p_tcb == NULL )
return;
1686 for(
const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1688 t->name[0] ? t->name :
"(noname)" );
1694 for(
const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1706 for(
const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1714 (t1.
state & 0x02)?
'R':
'-',
1715 (t1.
state & 0x01)?
'r':
'-' );
1717 mrbc_printf(
" s%04b r%04b ", t->state, t->reason);
1723 for(
const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1724 mrbc_printf(
" ts:%-2d fp:%d ", t->timeslice, t->vm.flag_preemption);
1734 for(
const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1747 mrbc_hal_disable_irq();
1753 mrbc_hal_enable_irq();
void * mrbc_raw_alloc(unsigned int size)
void mrbc_init_alloc(void *ptr, unsigned int size)
void mrbc_cleanup_alloc(void)
#define mrbc_immediate_value(...)
struct RObject mrbc_value
Value object. Default version.
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
static char * mrbc_string_cstr(const mrbc_value *v)
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
static mrbc_value mrbc_string_new_cstr(mrbc_vm *vm, const char *src)
void mrbc_init_task_queue(void)
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
void mrbc_init_class_c(void)
void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
void mrbc_init_class_mrblib(void)
#define MRBC_INSTANCE_DATA_PTR(v, t)
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
void mrbc_print_vm_exception(const struct VM *vm)
mrbc_value mrbc_exception_new(struct VM *vm, struct RClass *exc_cls, const void *message, int len)
void mrbc_init_global(void)
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
int mrbc_load_mrb(mrbc_vm *vm, const void *bytecode)
Include at once the necessary header files.
void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
static volatile uint32_t wakeup_tick_
void mrbc_set_task_name(mrbc_tcb *tcb, const char *name)
void mrbc_task_q_insert(mrbc_tcb *p_tcb)
void mrbc_init(void *heap_ptr, unsigned int size)
void mrbc_terminate_task(mrbc_tcb *tcb)
mrbc_tcb * mrbc_task_q_waiting_head(void)
static mrbc_tcb * tcb_queue_[NUM_TCB_QUEUE]
void mrbc_resume_task(mrbc_tcb *tcb)
int mrbc_mutex_unlock(mrbc_mutex *mutex, mrbc_tcb *tcb)
static void terminate_task(mrbc_tcb *tcb)
mrbc_tcb * mrbc_tcb_new(int regs_size, enum MrbcTaskState task_state, int priority)
mrbc_tcb * mrbc_find_task(const char *name)
mrbc_tcb * mrbc_create_task(const void *byte_code, mrbc_tcb *tcb)
mrbc_mutex * mrbc_mutex_init(mrbc_mutex *mutex)
void mrbc_change_priority(mrbc_tcb *tcb, int priority)
uint32_t mrbc_deadline_after_ms(mrbc_int_t ms, int *p_overflow)
void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
int mrbc_mutex_trylock(mrbc_mutex *mutex, mrbc_tcb *tcb)
int mrbc_deadline_reached(uint32_t deadline)
static mrbc_value sub_task_get(mrbc_vm *vm, mrbc_tcb *tcb)
int mrbc_mutex_lock(mrbc_mutex *mutex, mrbc_tcb *tcb)
static volatile uint32_t tick_
void mrbc_register_wakeup(uint32_t wakeup_tick)
#define MRBC_MUTEX_TRACE(...)
void mrbc_suspend_task(mrbc_tcb *tcb)
void mrbc_wakeup_task(mrbc_tcb *tcb)
static int get_timed_wakeup_tick(const mrbc_tcb *t, uint32_t *out)
void mrbc_relinquish(mrbc_tcb *tcb)
static void preempt_running_task(void)
int mrbc_start_task(mrbc_tcb *tcb)
static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
void mrbc_task_q_delete(mrbc_tcb *p_tcb)
int mrbc_delete_task(mrbc_tcb *tcb)
struct RTcb mrbc_tcb
Task control block.
@ TASKSTATE_SUSPENDED
Suspended.
@ TASKSTATE_WAITING
Waiting.
@ TASKSTATE_RUNNING
Running.
@ TASKSTATE_DORMANT
Domant.
static const int MRBC_TASK_DEFAULT_STATE
struct RMutex mrbc_mutex
Mutex.
static mrbc_tcb * mrbc_get_tcb(const mrbc_vm *vm)
#define MRBC_WAIT_FOREVER
#define MRBC_TASK_NAME_LEN
#define MRBC_MUTEX_INITIALIZER
static const int MRBC_TASK_DEFAULT_PRIORITY
struct RMethod * method_link
pointer to method link.
struct RClass * super
pointer to super class.
mrbc_sym sym_id
class name's symbol ID
struct RInstance * instance
uint8_t priority
task priority. initial value.
char name[MRBC_TASK_NAME_LEN+1]
task name (optional)
const struct RTcb * tcb_join
joined task.
uint8_t priority_preemption
task priority. effective value.
uint8_t state
task state. defined in MrbcTaskState.
mrbc_instance * task_instance
Task instance or NULL.
volatile uint8_t timeslice
time slice counter.
uint8_t reason
sub state. defined in MrbcTaskReason.
uint32_t wakeup_tick
wakeup time for sleep state.
struct RTcb::@363107132000246361337323266072372261072345062300::@123367244141214366021077021374060365005063270262 queue
queue wait state (TASKREASON_QUEUE).
struct RTcb * next
daisy chain in task queue.
uint16_t regs_size
size of regs[]
volatile int8_t flag_preemption
mrbc_value exception
Raised exception or nil.
unsigned int flag_permanence
void mrbc_cleanup_symbol(void)
static void mrbc_decref(mrbc_value *v)
#define SET_BOOL_RETURN(n)
#define SET_INT_RETURN(n)
#define MRBC_PTR_TO_UINT32(p)
static void mrbc_incref(mrbc_value *v)
@ MRBC_TT_INTEGER
Integer.
@ MRBC_TT_EXCEPTION
Exception.
@ MRBC_TT_OBJECT
General instance.
void mrbc_vm_close(mrbc_vm *vm)
mrbc_vm * mrbc_vm_open(mrbc_vm *vm)
int mrbc_vm_run(mrbc_vm *vm)
void mrbc_vm_end(mrbc_vm *vm)
void mrbc_cleanup_vm(void)
void mrbc_vm_begin(mrbc_vm *vm)
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.