mruby/c VM Source Code release 4.0.0
Loading...
Searching...
No Matches
rrt0.c
Go to the documentation of this file.
1
14
15/***** Feature test switches ************************************************/
16/***** System headers *******************************************************/
17//@cond
18#include "vm_config.h"
19#include <stdint.h>
20#include <string.h>
21#include <assert.h>
22//@endcond
23
24/***** Local headers ********************************************************/
25#include "mrubyc.h"
26
27/***** Macros ***************************************************************/
28#ifndef MRBC_SCHEDULER_EXIT
29#define MRBC_SCHEDULER_EXIT 0
30#endif
31
32#define MRBC_MUTEX_TRACE(...) ((void)0)
33
34#if !defined(MRBC_TIMESLICE_TICK_COUNT) || (MRBC_TIMESLICE_TICK_COUNT <= 0)
35#error "MRBC_TIMESLICE_TICK_COUNT must be a natural number."
36#endif
37
38/***** Typedefs *************************************************************/
39/***** Function prototypes **************************************************/
40/***** Local variables ******************************************************/
41#define NUM_TASK_QUEUE 4
43#define q_dormant_ (task_queue_[0])
44#define q_ready_ (task_queue_[1])
45#define q_waiting_ (task_queue_[2])
46#define q_suspended_ (task_queue_[3])
47static volatile uint32_t tick_;
48static volatile uint32_t wakeup_tick_ = (1 << 16); // no significant meaning.
49
50
51/***** Global variables *****************************************************/
52/***** Signal catching functions ********************************************/
53/***** Functions ************************************************************/
54//================================================================
65static void q_insert_task(mrbc_tcb *p_tcb)
66{
67 // select target queue pointer.
68 // state value = 0 1 2 3 4 5 6 7 8
69 // /2 0, 0, 1, 1, 2, 2, 3, 3, 4
70 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
71 mrbc_tcb **pp_q = &task_queue_[ conv_tbl[ p_tcb->state / 2 ]];
72
73 // in case of insert on top.
74 if((*pp_q == NULL) ||
75 (p_tcb->priority_preemption < (*pp_q)->priority_preemption)) {
76 p_tcb->next = *pp_q;
77 *pp_q = p_tcb;
78 return;
79 }
80
81 // find insert point in sorted linked list.
82 mrbc_tcb *p = *pp_q;
83 while( p->next != NULL ) {
84 if( p_tcb->priority_preemption < p->next->priority_preemption ) break;
85 p = p->next;
86 }
87
88 // insert tcb to queue.
89 p_tcb->next = p->next;
90 p->next = p_tcb;
91}
92
93
94//================================================================
99static void q_delete_task(mrbc_tcb *p_tcb)
100{
101 // select target queue pointer. (same as q_insert_task)
102 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
103 mrbc_tcb **pp_q = &task_queue_[ conv_tbl[ p_tcb->state / 2 ]];
104
105 if( *pp_q == p_tcb ) {
106 *pp_q = p_tcb->next;
107 p_tcb->next = NULL;
108 return;
109 }
110
111 mrbc_tcb *p = *pp_q;
112 while( p ) {
113 if( p->next == p_tcb ) {
114 p->next = p_tcb->next;
115 p_tcb->next = NULL;
116 return;
117 }
118
119 p = p->next;
120 }
121
122 assert(!"Not found target task in queue.");
123}
124
125
126//================================================================
129inline static void preempt_running_task(void)
130{
131 for( mrbc_tcb *t = q_ready_; t != NULL; t = t->next ) {
132 if( t->state == TASKSTATE_RUNNING ) t->vm.flag_preemption = 1;
133 }
134}
135
136
137//================================================================
141#if defined(__EMSCRIPTEN__)
142#include <emscripten.h>
143EMSCRIPTEN_KEEPALIVE
144#endif
145void mrbc_tick(void)
146{
147 tick_++;
148
149 // Decrease the time slice value for running tasks.
150 mrbc_tcb *tcb = q_ready_;
151 if( (tcb != NULL) && (tcb->timeslice != 0) ) {
152 tcb->timeslice--;
153 if( tcb->timeslice == 0 ) tcb->vm.flag_preemption = 1;
154 }
155
156 // Check the wakeup tick.
157 if( (int32_t)(wakeup_tick_ - tick_) < 0 ) {
158 int flag_preemption = 0;
159 wakeup_tick_ = tick_ + (1 << 16);
160
161 // Find a wake up task in waiting task queue.
162 tcb = q_waiting_;
163 while( tcb != NULL ) {
164 mrbc_tcb *t = tcb;
165 tcb = tcb->next;
166 if( t->reason != TASKREASON_SLEEP ) continue;
167
168 if( (int32_t)(t->wakeup_tick - tick_) < 0 ) {
169 q_delete_task(t);
171 t->reason = 0;
172 q_insert_task(t);
173 flag_preemption = 1;
174 } else if( (int32_t)(t->wakeup_tick - wakeup_tick_) < 0 ) {
176 }
177 }
178
179 if( flag_preemption ) preempt_running_task();
180 }
181}
182
183
184//================================================================
203mrbc_tcb * mrbc_tcb_new( int regs_size, enum MrbcTaskState task_state, int priority )
204{
205 mrbc_tcb *tcb;
206 unsigned int size = sizeof(mrbc_tcb) + sizeof(mrbc_value) * regs_size;
207
208 tcb = mrbc_raw_alloc(size);
209 memset(tcb, 0, size);
210#if defined(MRBC_DEBUG)
211 memcpy( tcb->obj_mark_, "TCB", 4 );
212#endif
213 tcb->priority = priority;
214 tcb->state = task_state;
215 tcb->vm.regs_size = regs_size;
216
217 return tcb;
218}
219
220
221//================================================================
228mrbc_tcb * mrbc_create_task(const void *byte_code, mrbc_tcb *tcb)
229{
231
232 tcb->priority_preemption = tcb->priority;
233
234 // assign VM ID
235 if( mrbc_vm_open( &tcb->vm ) == NULL ) {
236 mrbc_printf("Error: Can't assign VM-ID.\n");
237 return NULL;
238 }
239
240 if( mrbc_load_mrb(&tcb->vm, byte_code) != 0 ) {
242 mrbc_vm_close( &tcb->vm );
243 return NULL;
244 }
245 mrbc_vm_begin( &tcb->vm );
246
247 mrbc_hal_disable_irq();
248 q_insert_task(tcb);
250 mrbc_hal_enable_irq();
251
252 return tcb;
253}
254
255
256//================================================================
263{
264 if( tcb->state != TASKSTATE_DORMANT ) return -1;
265
266 mrbc_hal_disable_irq();
267 q_delete_task(tcb);
268 mrbc_hal_enable_irq();
269
270 mrbc_vm_close( &tcb->vm );
271
272 return 0;
273}
274
275
276//================================================================
282void mrbc_set_task_name(mrbc_tcb *tcb, const char *name)
283{
284 /* (note)
285 this is `strncpy( tcb->name, name, MRBC_TASK_NAME_LEN );`
286 for to avoid link error when compiling for PIC32 with XC32 v4.21
287 */
288 for( int i = 0; i < MRBC_TASK_NAME_LEN; i++ ) {
289 if( (tcb->name[i] = *name++) == 0 ) break;
290 }
291}
292
293
294//================================================================
300mrbc_tcb * mrbc_find_task(const char *name)
301{
302 mrbc_tcb *tcb = 0;
303 mrbc_hal_disable_irq();
304
305 for( int i = 0; i < NUM_TASK_QUEUE; i++ ) {
306 for( tcb = task_queue_[i]; tcb != NULL; tcb = tcb->next ) {
307 if( strcmp( tcb->name, name ) == 0 ) goto RETURN_TCB;
308 }
309 }
310
311 RETURN_TCB:
312 mrbc_hal_enable_irq();
313 return tcb;
314}
315
316
317//================================================================
324{
325 if( tcb->state != TASKSTATE_DORMANT ) return -1;
326
327 mrbc_hal_disable_irq();
328
330
331 q_delete_task(tcb);
332 tcb->state = TASKSTATE_READY;
333 tcb->reason = 0;
334 tcb->priority_preemption = tcb->priority;
335 q_insert_task(tcb);
336
337 mrbc_hal_enable_irq();
338
339 return 0;
340}
341
342
343//================================================================
347int mrbc_run(void)
348{
349 int ret = 0;
350 (void)ret; // avoid warning.
351
352 while( 1 ) {
353 mrbc_tcb *tcb = q_ready_;
354 if( tcb == NULL ) { // no task to run.
355#if MRBC_SCHEDULER_EXIT
356 mrbc_hal_disable_irq();
357 int flag_exit = !q_ready_ && !q_waiting_ && !q_suspended_;
358 mrbc_hal_enable_irq();
359 if( flag_exit ) return ret;
360#endif
361 mrbc_hal_idle_cpu();
362 continue;
363 }
364
365 /*
366 run the task.
367 */
368 tcb->state = TASKSTATE_RUNNING; // to execute.
369 tcb->timeslice = MRBC_TIMESLICE_TICK_COUNT;
370
371#if !defined(MRBC_NO_TIMER)
372 // Using hardware timer.
373 int ret_vm_run = mrbc_vm_run(&tcb->vm);
374 tcb->vm.flag_preemption = 0;
375#else
376 // Emulate time slice preemption.
377 int ret_vm_run = 0;
378 tcb->vm.flag_preemption = 1;
379 while( tcb->timeslice != 0 ) {
380 ret_vm_run = mrbc_vm_run( &tcb->vm );
381 tcb->timeslice--;
382 if( ret_vm_run != 0 ) break;
383 if( tcb->state != TASKSTATE_RUNNING ) break;
384 }
385 mrbc_tick();
386#endif
387
388 /*
389 did the task done?
390 */
391 if( ret_vm_run != 0 ) {
392 mrbc_hal_disable_irq();
393 q_delete_task(tcb);
395 q_insert_task(tcb);
396 mrbc_hal_enable_irq();
397
398 if( ! tcb->vm.flag_permanence ) mrbc_vm_end( &tcb->vm );
399 if( ret_vm_run != 1 ) ret = ret_vm_run; // for debug info.
400
401 // find task that called join.
402 for( mrbc_tcb *tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next ) {
403 if( tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb ) {
404 mrbc_hal_disable_irq();
405 q_delete_task(tcb1);
406 tcb1->state = TASKSTATE_READY;
407 tcb1->reason = 0;
408 q_insert_task(tcb1);
409 mrbc_hal_enable_irq();
410 }
411 }
412 for( mrbc_tcb *tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next ) {
413 if( tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb ) {
414 tcb1->reason = 0;
415 }
416 }
417 continue;
418 }
419
420 /*
421 Switch task.
422 */
423 if( tcb->state == TASKSTATE_RUNNING ) {
424 tcb->state = TASKSTATE_READY;
425
426 mrbc_hal_disable_irq();
427 q_delete_task(tcb); // insert task on queue last.
428 q_insert_task(tcb);
429 mrbc_hal_enable_irq();
430 }
431
432 } // loop infinite.
433}
434
435
436//================================================================
440#if defined(__EMSCRIPTEN__)
441EMSCRIPTEN_KEEPALIVE
442int
443mrbc_run_step(void)
444{
445 // Take the task that can be executed
446 mrbc_tcb *tcb = q_ready_;
447 if (tcb == NULL) {
448 // Even if there is no task to run, return 0
449 // so to wait for callbacks like event listener
450 return 0;
451 }
452
454 tcb->timeslice = MRBC_TIMESLICE_TICK_COUNT;
455
456 int ret_vm_run = mrbc_vm_run(&tcb->vm);
457 tcb->vm.flag_preemption = 0;
458
459 if (ret_vm_run != 0) {
460 mrbc_hal_disable_irq();
461 q_delete_task(tcb);
463 q_insert_task(tcb);
464 mrbc_hal_enable_irq();
465
466 if (!tcb->vm.flag_permanence) {
467 mrbc_vm_end(&tcb->vm);
468 }
469
470 for (mrbc_tcb *tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next) {
471 if (tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb) {
472 mrbc_hal_disable_irq();
473 q_delete_task(tcb1);
474 tcb1->state = TASKSTATE_READY;
475 tcb1->reason = 0;
476 q_insert_task(tcb1);
477 mrbc_hal_enable_irq();
478 }
479 }
480 for (mrbc_tcb *tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next) {
481 if (tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb) {
482 tcb1->reason = 0;
483 }
484 }
485
486 return ret_vm_run;
487 }
488
489 // Switch task.
490 if (tcb->state == TASKSTATE_RUNNING) {
491 tcb->state = TASKSTATE_READY;
492 mrbc_hal_disable_irq();
493 q_delete_task(tcb);
494 q_insert_task(tcb);
495 mrbc_hal_enable_irq();
496 }
497
498 return 0;
499}
500#endif
501
502
503//================================================================
509void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
510{
511 mrbc_hal_disable_irq();
512 q_delete_task(tcb);
515 tcb->wakeup_tick = tick_ + (ms / MRBC_TICK_UNIT) + !!(ms % MRBC_TICK_UNIT);
516
517 if( (int32_t)(tcb->wakeup_tick - wakeup_tick_) < 0 ) {
519 }
520
521 q_insert_task(tcb);
522 mrbc_hal_enable_irq();
523
524 tcb->vm.flag_preemption = 1;
525}
526
527
528//================================================================
534{
535 switch( tcb->state ) {
537 mrbc_resume_task( tcb ); // for sleep without arguments.
538 break;
539
541 if( tcb->reason != TASKREASON_SLEEP ) break;
542
543 mrbc_hal_disable_irq();
544 q_delete_task(tcb);
545 tcb->state = TASKSTATE_READY;
546 tcb->reason = 0;
547 q_insert_task(tcb);
548
549 for( mrbc_tcb *t = q_waiting_; t != NULL; t = t->next ) {
550 if( t->reason != TASKREASON_SLEEP ) continue;
551 if( (int32_t)(t->wakeup_tick - wakeup_tick_) < 0 ) {
552 wakeup_tick_ = t->wakeup_tick;
553 }
554 }
555 mrbc_hal_enable_irq();
556 break;
557
558 default:
559 break;
560 }
561}
562
563
564//================================================================
570{
571 tcb->timeslice = 0;
572 tcb->vm.flag_preemption = 1;
573}
574
575
576//================================================================
582void mrbc_change_priority(mrbc_tcb *tcb, int priority)
583{
584 tcb->priority = priority;
585 tcb->priority_preemption = priority;
586
587 mrbc_hal_disable_irq();
588 q_delete_task(tcb); // reorder task queue according to priority.
589 q_insert_task(tcb);
590
592
593 mrbc_hal_enable_irq();
594}
595
596
597//================================================================
603{
604 if( tcb->state == TASKSTATE_SUSPENDED ) return;
605
606 mrbc_hal_disable_irq();
607 q_delete_task(tcb);
609 q_insert_task(tcb);
610 mrbc_hal_enable_irq();
611
612 tcb->vm.flag_preemption = 1;
613}
614
615
616//================================================================
622{
623 if( tcb->state != TASKSTATE_SUSPENDED ) return;
624
625 int flag_to_ready_state = (tcb->reason == 0);
626
627 mrbc_hal_disable_irq();
628
629 if( flag_to_ready_state ) preempt_running_task();
630
631 q_delete_task(tcb);
632 tcb->state = flag_to_ready_state ? TASKSTATE_READY : TASKSTATE_WAITING;
633 q_insert_task(tcb);
634
635 mrbc_hal_enable_irq();
636
637 if( tcb->reason & TASKREASON_SLEEP ) {
638 if( (int32_t)(tcb->wakeup_tick - wakeup_tick_) < 0 ) {
640 }
641 }
642}
643
644
645//================================================================
654{
655 if( tcb->state == TASKSTATE_DORMANT ) return;
656
657 mrbc_hal_disable_irq();
658 q_delete_task(tcb);
660 q_insert_task(tcb);
661 mrbc_hal_enable_irq();
662
663 tcb->vm.flag_preemption = 1;
664}
665
666
667//================================================================
673void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
674{
675 if( tcb->state == TASKSTATE_DORMANT ) return;
676 if( tcb_join->state == TASKSTATE_DORMANT ) return;
677
678 mrbc_hal_disable_irq();
679 q_delete_task(tcb);
680
682 tcb->reason = TASKREASON_JOIN;
683 tcb->tcb_join = tcb_join;
684
685 q_insert_task(tcb);
686 mrbc_hal_enable_irq();
687
688 tcb->vm.flag_preemption = 1;
689}
690
691
692
693//================================================================
699{
700 if( mutex == NULL ) {
701 mutex = mrbc_raw_alloc( sizeof(mrbc_mutex) );
702 }
703
704 static const mrbc_mutex init_val = MRBC_MUTEX_INITIALIZER;
705 *mutex = init_val;
706
707 return mutex;
708}
709
710
711//================================================================
718{
719 MRBC_MUTEX_TRACE("mutex lock / MUTEX: %p TCB: %p", mutex, tcb );
720
721 int ret = 0;
722 mrbc_hal_disable_irq();
723
724 // Try lock mutex;
725 if( mutex->lock == 0 ) { // a future does use TAS?
726 mutex->lock = 1;
727 mutex->tcb = tcb;
728 MRBC_MUTEX_TRACE(" lock OK\n" );
729 goto DONE;
730 }
731 MRBC_MUTEX_TRACE(" lock FAIL\n" );
732
733 // Can't lock mutex
734 // check recursive lock.
735 if( mutex->tcb == tcb ) {
736 ret = 1;
737 goto DONE;
738 }
739
740 // To WAITING state.
741 q_delete_task(tcb);
744 tcb->mutex = mutex;
745 q_insert_task(tcb);
746 tcb->vm.flag_preemption = 1;
747
748 DONE:
749 mrbc_hal_enable_irq();
750
751 return ret;
752}
753
754
755//================================================================
762{
763 MRBC_MUTEX_TRACE("mutex unlock / MUTEX: %p TCB: %p\n", mutex, tcb );
764
765 // check some parameters.
766 if( !mutex->lock ) return 1;
767 if( mutex->tcb != tcb ) return 2;
768
769 mrbc_hal_disable_irq();
770
771 // wakeup ONE waiting task if exist.
772 mrbc_tcb *tcb1;
773 for( tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next ) {
774 if( tcb1->reason == TASKREASON_MUTEX && tcb1->mutex == mutex ) break;
775 }
776 if( tcb1 ) {
777 MRBC_MUTEX_TRACE("SW1: TCB: %p\n", tcb1 );
778 mutex->tcb = tcb1;
779
780 q_delete_task(tcb1);
781 tcb1->state = TASKSTATE_READY;
782 tcb1->reason = 0;
783 q_insert_task(tcb1);
784
786 goto DONE;
787 }
788
789 // find ONE mutex locked task in suspended queue.
790 for( tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next ) {
791 if( tcb1->reason == TASKREASON_MUTEX && tcb1->mutex == mutex ) break;
792 }
793 if( tcb1 ) {
794 MRBC_MUTEX_TRACE("SW2: TCB: %p\n", tcb1 );
795 mutex->tcb = tcb1;
796 tcb1->reason = 0;
797 goto DONE;
798 }
799
800 // other case, unlock mutex
801 MRBC_MUTEX_TRACE("mutex unlock all.\n" );
802 mutex->lock = 0;
803 mutex->tcb = 0;
804
805 DONE:
806 mrbc_hal_enable_irq();
807
808 return 0;
809}
810
811
812//================================================================
819{
820 MRBC_MUTEX_TRACE("mutex try lock / MUTEX: %p TCB: %p", mutex, tcb );
821
822 int ret;
823 mrbc_hal_disable_irq();
824
825 if( mutex->lock == 0 ) {
826 mutex->lock = 1;
827 mutex->tcb = tcb;
828 ret = 0;
829 MRBC_MUTEX_TRACE(" trylock OK\n" );
830 }
831 else {
832 MRBC_MUTEX_TRACE(" trylock FAIL\n" );
833 ret = 1;
834 }
835
836 mrbc_hal_enable_irq();
837 return ret;
838}
839
840
841//================================================================
845void mrbc_cleanup(void)
846{
850
851 memset( task_queue_, 0, sizeof(task_queue_) );
852}
853
854
855//================================================================
859static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
860{
861 mrbc_tcb *tcb = mrbc_get_tcb(vm);
862
863 if( argc == 0 ) {
865 return;
866 }
867
868 switch( mrbc_type(v[1]) ) {
869 case MRBC_TT_INTEGER:
870 {
871 mrbc_int_t sec;
872 sec = mrbc_integer(v[1]);
873 SET_INT_RETURN(sec);
874 mrbc_sleep_ms(tcb, sec * 1000);
875 break;
876 }
877
878#if MRBC_USE_FLOAT
879 case MRBC_TT_FLOAT:
880 {
881 mrbc_float_t sec;
882 sec = mrbc_float(v[1]);
883 SET_INT_RETURN(sec);
884 mrbc_sleep_ms(tcb, (mrbc_int_t)(sec * 1000));
885 break;
886 }
887#endif
888
889 default:
890 break;
891 }
892}
893
894
895//================================================================
899static void c_sleep_ms(mrbc_vm *vm, mrbc_value v[], int argc)
900{
901 mrbc_tcb *tcb = mrbc_get_tcb(vm);
902
903 mrbc_int_t sec = mrbc_integer(v[1]);
904 SET_INT_RETURN(sec);
905 mrbc_sleep_ms(tcb, sec);
906}
907
908
909
910/*
911 Task class
912*/
913//================================================================
919static void c_task_get(mrbc_vm *vm, mrbc_value v[], int argc)
920{
921 mrbc_tcb *tcb = NULL;
922
923 if( mrbc_type(v[0]) != MRBC_TT_CLASS ) goto RETURN_NIL;
924
925 // in case of Task.get()
926 if( argc == 0 ) {
927 tcb = mrbc_get_tcb(vm);
928 }
929
930 // in case of Task.get("TasName")
931 else if( mrbc_type(v[1]) == MRBC_TT_STRING ) {
932 tcb = mrbc_find_task( mrbc_string_cstr( &v[1] ) );
933 }
934
935 if( tcb ) {
936 mrbc_value ret = mrbc_instance_new(vm, v->cls, sizeof(mrbc_tcb *));
937 *(mrbc_tcb **)ret.instance->data = tcb;
938 SET_RETURN(ret);
939 return; // normal return.
940 }
941
942 RETURN_NIL:
944}
945
946
947//================================================================
952static void c_task_list(mrbc_vm *vm, mrbc_value v[], int argc)
953{
954 mrbc_value ret = mrbc_array_new(vm, 1);
955
956 mrbc_hal_disable_irq();
957
958 for( int i = 0; i < NUM_TASK_QUEUE; i++ ) {
959 for( mrbc_tcb *tcb = task_queue_[i]; tcb != NULL; tcb = tcb->next ) {
960 mrbc_value task = mrbc_instance_new(vm, v->cls, sizeof(mrbc_tcb *));
961 *(mrbc_tcb **)task.instance->data = tcb;
962 mrbc_array_push( &ret, &task );
963 }
964 }
965
966 mrbc_hal_enable_irq();
967
968 SET_RETURN(ret);
969}
970
971
972//================================================================
977static void c_task_name_list(mrbc_vm *vm, mrbc_value v[], int argc)
978{
979 mrbc_value ret = mrbc_array_new(vm, 1);
980
981 mrbc_hal_disable_irq();
982
983 for( int i = 0; i < NUM_TASK_QUEUE; i++ ) {
984 for( mrbc_tcb *tcb = task_queue_[i]; tcb != NULL; tcb = tcb->next ) {
986 mrbc_array_push( &ret, &s );
987 }
988 }
989
990 mrbc_hal_enable_irq();
991
992 SET_RETURN(ret);
993}
994
995
996//================================================================
1001static void c_task_set_name(mrbc_vm *vm, mrbc_value v[], int argc)
1002{
1003 if( mrbc_type(v[1]) != MRBC_TT_STRING ) {
1004 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1005 return;
1006 }
1007
1008 mrbc_tcb *tcb;
1009
1010 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1011 tcb = mrbc_get_tcb(vm);
1012 } else {
1013 tcb = *(mrbc_tcb **)v[0].instance->data;
1014 }
1015 mrbc_set_task_name( tcb, mrbc_string_cstr(&v[1]) );
1016
1017 mrbc_incref( &v[1] );
1018 SET_RETURN( v[1] );
1019}
1020
1021
1022//================================================================
1028static void c_task_name(mrbc_vm *vm, mrbc_value v[], int argc)
1029{
1030 mrbc_value ret;
1031
1032 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1033 ret = mrbc_string_new_cstr( vm, mrbc_get_tcb(vm)->name );
1034 } else {
1035 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1036 ret = mrbc_string_new_cstr(vm, tcb->name );
1037 }
1038
1039 SET_RETURN(ret);
1040}
1041
1042
1043//================================================================
1049static void c_task_set_priority(mrbc_vm *vm, mrbc_value v[], int argc)
1050{
1051 mrbc_tcb *tcb;
1052
1053 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1054 tcb = mrbc_get_tcb(vm);
1055 } else {
1056 tcb = *(mrbc_tcb **)v[0].instance->data;
1057 }
1058
1059 if( mrbc_type(v[1]) != MRBC_TT_INTEGER ) {
1060 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1061 return;
1062 }
1063 int n = mrbc_integer( v[1] );
1064 if( n < 0 || n > 255 ) {
1065 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1066 return;
1067 }
1068
1069 mrbc_change_priority( tcb, n );
1070
1071 SET_RETURN( v[1] );
1072}
1073
1074
1075//================================================================
1080static void c_task_priority(mrbc_vm *vm, mrbc_value v[], int argc)
1081{
1082 mrbc_tcb *tcb;
1083
1084 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1085 tcb = mrbc_get_tcb(vm);
1086 } else {
1087 tcb = *(mrbc_tcb **)v[0].instance->data;
1088 }
1089
1090 SET_INT_RETURN( tcb->priority );
1091}
1092
1093
1094//================================================================
1099static void c_task_status(mrbc_vm *vm, mrbc_value v[], int argc)
1100{
1101 static const char *status_name[] =
1102 { "DORMANT", "READY", "WAITING ", "", "SUSPENDED" };
1103 static const char *reason_name[] =
1104 { "", "SLEEP", "MUTEX", "", "JOIN" };
1105
1106 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1107
1108 const mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1109 mrbc_value ret = mrbc_string_new_cstr( vm, status_name[tcb->state / 2] );
1110
1111 if( tcb->state == TASKSTATE_WAITING ) {
1112 mrbc_string_append_cstr( &ret, reason_name[tcb->reason] );
1113 }
1114
1115 SET_RETURN(ret);
1116}
1117
1118
1119//================================================================
1125static void c_task_suspend(mrbc_vm *vm, mrbc_value v[], int argc)
1126{
1127 mrbc_tcb *tcb;
1128
1129 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1130 tcb = mrbc_get_tcb(vm);
1131 } else {
1132 tcb = *(mrbc_tcb **)v[0].instance->data;
1133 }
1134
1135 mrbc_suspend_task(tcb);
1136}
1137
1138
1139//================================================================
1144static void c_task_resume(mrbc_vm *vm, mrbc_value v[], int argc)
1145{
1146 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1147
1148 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1149
1150 mrbc_resume_task(tcb);
1151}
1152
1153
1154//================================================================
1159static void c_task_terminate(mrbc_vm *vm, mrbc_value v[], int argc)
1160{
1161 mrbc_tcb *tcb;
1162
1163 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1164 tcb = mrbc_get_tcb(vm);
1165 } else {
1166 tcb = *(mrbc_tcb **)v[0].instance->data;
1167 }
1168
1170}
1171
1172
1173//================================================================
1179static void c_task_raise(mrbc_vm *vm, mrbc_value v[], int argc)
1180{
1181 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1182 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1183 mrbc_vm *vm1 = &tcb->vm;
1184 mrbc_value exc;
1185
1186 if( argc == 0 ) {
1187 exc = mrbc_exception_new( vm1, MRBC_CLASS(RuntimeError), 0, 0 );
1188 } else if( mrbc_type(v[1]) == MRBC_TT_EXCEPTION ) {
1189 exc = v[1];
1190 mrbc_incref(&exc);
1191 } else {
1192 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1193 return;
1194 }
1195
1196 mrbc_decref(&vm1->exception);
1197 vm1->exception = exc;
1198 vm1->flag_preemption = 2;
1199
1200 if( tcb->state == TASKSTATE_WAITING && tcb->reason == TASKREASON_SLEEP ) {
1201 void mrbc_wakeup_task(mrbc_tcb *tcb);
1202 mrbc_wakeup_task( tcb );
1203 }
1204}
1205
1206
1207//================================================================
1212static void c_task_join(mrbc_vm *vm, mrbc_value v[], int argc)
1213{
1214 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1215
1216 mrbc_tcb *tcb_me = mrbc_get_tcb(vm);
1217 mrbc_tcb *tcb_join = *(mrbc_tcb **)v[0].instance->data;
1218
1219 mrbc_join_task(tcb_me, tcb_join);
1220}
1221
1222
1223//================================================================
1228static void c_task_value(mrbc_vm *vm, mrbc_value v[], int argc)
1229{
1230 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1231
1232 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1233
1234 if( tcb->state != TASKSTATE_DORMANT ) {
1235 mrbc_raise(vm, 0, "task must be end");
1236 return;
1237 }
1238
1239 mrbc_incref( &tcb->vm.regs[0] );
1240 SET_RETURN( tcb->vm.regs[0] );
1241}
1242
1243
1244//================================================================
1249static void c_task_pass(mrbc_vm *vm, mrbc_value v[], int argc)
1250{
1251 if( mrbc_type(v[0]) != MRBC_TT_CLASS ) return;
1252
1253 mrbc_tcb *tcb = mrbc_get_tcb(vm);
1254 mrbc_relinquish(tcb);
1255}
1256
1257
1258//================================================================
1263static void c_task_create(mrbc_vm *vm, mrbc_value v[], int argc)
1264{
1265 const char *byte_code;
1266 int regs_size = MAX_REGS_SIZE;
1267
1268 // check argument.
1269 if( mrbc_type(v[0]) != MRBC_TT_CLASS ) goto ERROR_ARGUMENT;
1270
1271 if( argc >= 1 && mrbc_type(v[1]) != MRBC_TT_STRING ) goto ERROR_ARGUMENT;
1272 mrbc_incref( &v[1] );
1273 byte_code = mrbc_string_cstr(&v[1]);
1274
1275 if( argc >= 2 ) {
1276 if( mrbc_type(v[2]) != MRBC_TT_INTEGER ) goto ERROR_ARGUMENT;
1277 regs_size = mrbc_integer(v[2]);
1278 }
1279
1280 // create TCB
1282 if( !tcb ) {
1283 mrbc_raise( vm, MRBC_CLASS(NoMemoryError), 0 );
1284 return;
1285 }
1286 tcb->vm.flag_permanence = 1;
1287
1288 if( !mrbc_create_task( byte_code, tcb ) ) return;
1289
1290 // create Instance
1291 mrbc_value ret = mrbc_instance_new(vm, v->cls, sizeof(mrbc_tcb *));
1292 *(mrbc_tcb **)ret.instance->data = tcb;
1293 SET_RETURN( ret );
1294 return;
1295
1296 ERROR_ARGUMENT:
1297 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1298}
1299
1300
1301//================================================================
1306static void c_task_run(mrbc_vm *vm, mrbc_value v[], int argc)
1307{
1308 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1309
1310 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1311 if( tcb->state != TASKSTATE_DORMANT ) return;
1312
1313 mrbc_start_task(tcb);
1314}
1315
1316
1317//================================================================
1322static void c_task_rewind(mrbc_vm *vm, mrbc_value v[], int argc)
1323{
1324 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1325
1326 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1327 if( tcb->state != TASKSTATE_DORMANT ) return;
1328
1329 mrbc_vm_begin( &tcb->vm );
1330}
1331
1332
1333/* MRBC_AUTOGEN_METHOD_TABLE
1334
1335 CLASS("Task")
1336 FILE("_autogen_class_rrt0.h")
1337
1338 METHOD( "get", c_task_get )
1339 METHOD( "current", c_task_get )
1340 METHOD( "list", c_task_list )
1341 METHOD( "name_list", c_task_name_list )
1342 METHOD( "name=", c_task_set_name )
1343 METHOD( "name", c_task_name )
1344 METHOD( "priority=", c_task_set_priority )
1345 METHOD( "priority", c_task_priority )
1346 METHOD( "status", c_task_status )
1347
1348 METHOD( "suspend", c_task_suspend )
1349 METHOD( "resume", c_task_resume )
1350 METHOD( "terminate", c_task_terminate )
1351 METHOD( "raise", c_task_raise )
1352
1353 METHOD( "join", c_task_join )
1354 METHOD( "value", c_task_value )
1355 METHOD( "pass", c_task_pass )
1356
1357 METHOD( "create", c_task_create )
1358 METHOD( "run", c_task_run )
1359 METHOD( "rewind", c_task_rewind )
1360*/
1361
1362
1363/*
1364 Mutex class
1365*/
1366//================================================================
1370static void c_mutex_new(mrbc_vm *vm, mrbc_value v[], int argc)
1371{
1372 *v = mrbc_instance_new(vm, v->cls, sizeof(mrbc_mutex));
1373
1375}
1376
1377
1378//================================================================
1382static void c_mutex_lock(mrbc_vm *vm, mrbc_value v[], int argc)
1383{
1384 int r = mrbc_mutex_lock( (mrbc_mutex *)v->instance->data, mrbc_get_tcb(vm) );
1385 if( r == 0 ) return; // return self
1386
1387 // raise ThreadError
1388 assert(!"Mutex recursive lock.");
1389}
1390
1391
1392//================================================================
1396static void c_mutex_unlock(mrbc_vm *vm, mrbc_value v[], int argc)
1397{
1399 if( r == 0 ) return; // return self
1400
1401 // raise ThreadError
1402 assert(!"Mutex unlock error. not owner or not locked.");
1403}
1404
1405
1406//================================================================
1410static void c_mutex_trylock(mrbc_vm *vm, mrbc_value v[], int argc)
1411{
1413 SET_BOOL_RETURN( r == 0 );
1414}
1415
1416
1417//================================================================
1421static void c_mutex_locked(mrbc_vm *vm, mrbc_value v[], int argc)
1422{
1423 mrbc_mutex *mutex = (mrbc_mutex *)v->instance->data;
1424 SET_BOOL_RETURN( mutex->lock != 0 );
1425}
1426
1427
1428//================================================================
1432static void c_mutex_owned(mrbc_vm *vm, mrbc_value v[], int argc)
1433{
1434 mrbc_mutex *mutex = (mrbc_mutex *)v->instance->data;
1435 SET_BOOL_RETURN( mutex->lock != 0 && mutex->tcb == mrbc_get_tcb(vm) );
1436}
1437
1438
1439/* MRBC_AUTOGEN_METHOD_TABLE
1440
1441 CLASS("Mutex")
1442 APPEND("_autogen_class_rrt0.h")
1443
1444 METHOD( "new", c_mutex_new )
1445 METHOD( "lock", c_mutex_lock )
1446 METHOD( "unlock", c_mutex_unlock )
1447 METHOD( "try_lock", c_mutex_trylock )
1448 METHOD( "locked?", c_mutex_locked )
1449 METHOD( "owned?", c_mutex_owned )
1450*/
1451
1452
1453
1454//================================================================
1457static void c_vm_tick(mrbc_vm *vm, mrbc_value v[], int argc)
1458{
1460}
1461
1462/* MRBC_AUTOGEN_METHOD_TABLE
1463
1464 CLASS("VM")
1465 APPEND("_autogen_class_rrt0.h")
1466
1467 METHOD( "tick", c_vm_tick )
1468*/
1469#include "_autogen_class_rrt0.h"
1470
1471
1472
1473//================================================================
1479void mrbc_init(void *heap_ptr, unsigned int size)
1480{
1481 static uint8_t flag_hal_init_called = 0;
1482
1483 if( !flag_hal_init_called ) {
1484 mrbc_hal_init();
1485 flag_hal_init_called = 1;
1486 }
1487
1488 mrbc_init_alloc(heap_ptr, size);
1491
1492 // (re) Initialize included classes
1493 static mrbc_class * const rrt0_cls[] = {
1494 MRBC_CLASS(Task), MRBC_CLASS(Mutex), MRBC_CLASS(VM)
1495 };
1497
1498 for( int i = 0; i < sizeof(rrt0_cls)/sizeof(rrt0_cls[0]); i++ ) {
1499 mrbc_class *cls = rrt0_cls[i];
1500
1501 cls->super = MRBC_CLASS(Object);
1502 cls->method_link = 0;
1503 vcls.cls = cls;
1504
1505 mrbc_set_const( vcls.cls->sym_id, &vcls );
1506 }
1507
1508 mrbc_define_method(0, 0, "sleep", c_sleep);
1509 mrbc_define_method(0, 0, "sleep_ms", c_sleep_ms);
1510}
1511
1512
1513
1514#ifdef MRBC_DEBUG
1515//================================================================
1522void pq(const mrbc_tcb *p_tcb)
1523{
1524 if( p_tcb == NULL ) return;
1525
1526 // vm_id, TCB, name
1527 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1528 mrbc_printf("%d:%08x %-8.8s ", t->vm.vm_id, MRBC_PTR_TO_UINT32(t),
1529 t->name[0] ? t->name : "(noname)" );
1530 }
1531 mrbc_printf("\n");
1532
1533#if 0
1534 // next ptr
1535 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1536 mrbc_printf(" next:%04x ", (uint16_t)MRBC_PTR_TO_UINT32(t->next));
1537 }
1538 mrbc_printf("\n");
1539#endif
1540
1541 // task priority, state.
1542 // st:SsRr
1543 // ^ suspended -> S:suspended
1544 // ^ waiting -> s:sleep m:mutex J:join (uppercase is suspend state)
1545 // ^ ready -> R:ready
1546 // ^ running-> r:running
1547 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1548 mrbc_printf(" pri:%3d", t->priority_preemption);
1549#if 1
1550 mrbc_tcb t1 = *t; // Copy the value at this timing.
1551 mrbc_printf(" st:%c%c%c%c ",
1552 (t1.state & TASKSTATE_SUSPENDED)?'S':'-',
1553 (t1.state & TASKSTATE_SUSPENDED)? ("-SM!J"[t1.reason]) :
1554 (t1.state & TASKSTATE_WAITING)? ("!sm!j"[t1.reason]) : '-',
1555 (t1.state & 0x02)?'R':'-',
1556 (t1.state & 0x01)?'r':'-' );
1557#else
1558 mrbc_printf(" s%04b r%03b ", t->state, t->reason);
1559#endif
1560 }
1561 mrbc_printf("\n");
1562
1563 // timeslice, vm->flag_preemption, wakeup tick
1564 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1565 mrbc_printf(" ts:%-2d fp:%d ", t->timeslice, t->vm.flag_preemption);
1566 if( t->reason & TASKREASON_SLEEP ) {
1567 mrbc_printf("w:%-6d", t->wakeup_tick );
1568 } else {
1569 mrbc_printf("w:-- ");
1570 }
1571 }
1572 mrbc_printf("\n");
1573}
1574
1575void pqall(void)
1576{
1577 mrbc_hal_disable_irq();
1578 mrbc_printf("<< tick_ = %d, wakeup_tick_ = %d >>\n", tick_, wakeup_tick_);
1579 mrbc_printf("<<<<< DORMANT >>>>>\n"); pq(q_dormant_);
1580 mrbc_printf("<<<<< READY >>>>>\n"); pq(q_ready_);
1581 mrbc_printf("<<<<< WAITING >>>>>\n"); pq(q_waiting_);
1582 mrbc_printf("<<<<< SUSPENDED >>>>>\n"); pq(q_suspended_);
1583 mrbc_hal_enable_irq();
1584}
1585#endif
void * mrbc_raw_alloc(unsigned int size)
Definition alloc.c:514
void mrbc_init_alloc(void *ptr, unsigned int size)
Definition alloc.c:452
void mrbc_cleanup_alloc(void)
Definition alloc.c:495
#define mrbc_immediate_value(...)
Definition boxing_no.h:71
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
#define mrbc_float(o)
Definition boxing_no.h:59
#define mrbc_integer(o)
Definition boxing_no.h:58
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:243
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
Definition c_array.c:83
static char * mrbc_string_cstr(const mrbc_value *v)
Definition c_string.h:122
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:134
static mrbc_value mrbc_string_new_cstr(mrbc_vm *vm, const char *src)
Definition c_string.h:91
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:306
void mrbc_init_class(void)
Definition class.c:622
void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
Definition class.c:274
#define MRBC_CLASS(cls)
Definition class.h:55
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:201
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:231
mrbc_value mrbc_exception_new(struct VM *vm, struct RClass *exc_cls, const void *message, int len)
Definition error.c:65
void mrbc_init_global(void)
Definition global.c:40
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:57
int mrbc_load_mrb(mrbc_vm *vm, const void *bytecode)
Definition load.c:303
Include at once the necessary header files.
void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
Definition rrt0.c:673
static volatile uint32_t wakeup_tick_
Definition rrt0.c:48
void mrbc_set_task_name(mrbc_tcb *tcb, const char *name)
Definition rrt0.c:282
#define q_ready_
Definition rrt0.c:44
void mrbc_init(void *heap_ptr, unsigned int size)
Definition rrt0.c:1479
void mrbc_terminate_task(mrbc_tcb *tcb)
Definition rrt0.c:653
#define NUM_TASK_QUEUE
Definition rrt0.c:41
void mrbc_resume_task(mrbc_tcb *tcb)
Definition rrt0.c:621
int mrbc_mutex_unlock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:761
#define q_dormant_
Definition rrt0.c:43
void mrbc_cleanup(void)
Definition rrt0.c:845
mrbc_tcb * mrbc_tcb_new(int regs_size, enum MrbcTaskState task_state, int priority)
Definition rrt0.c:203
mrbc_tcb * mrbc_find_task(const char *name)
Definition rrt0.c:300
mrbc_tcb * mrbc_create_task(const void *byte_code, mrbc_tcb *tcb)
Definition rrt0.c:228
static void q_delete_task(mrbc_tcb *p_tcb)
Definition rrt0.c:99
void mrbc_tick(void)
Definition rrt0.c:145
static void q_insert_task(mrbc_tcb *p_tcb)
Definition rrt0.c:65
mrbc_mutex * mrbc_mutex_init(mrbc_mutex *mutex)
Definition rrt0.c:698
void mrbc_change_priority(mrbc_tcb *tcb, int priority)
Definition rrt0.c:582
void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
Definition rrt0.c:509
int mrbc_mutex_trylock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:818
int mrbc_mutex_lock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:717
static volatile uint32_t tick_
Definition rrt0.c:47
#define q_suspended_
Definition rrt0.c:46
#define MRBC_MUTEX_TRACE(...)
Definition rrt0.c:32
void mrbc_suspend_task(mrbc_tcb *tcb)
Definition rrt0.c:602
void mrbc_wakeup_task(mrbc_tcb *tcb)
Definition rrt0.c:533
void mrbc_relinquish(mrbc_tcb *tcb)
Definition rrt0.c:569
static void preempt_running_task(void)
Definition rrt0.c:129
#define q_waiting_
Definition rrt0.c:45
int mrbc_start_task(mrbc_tcb *tcb)
Definition rrt0.c:323
static mrbc_tcb * task_queue_[NUM_TASK_QUEUE]
Definition rrt0.c:42
static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
Definition rrt0.c:859
int mrbc_run(void)
Definition rrt0.c:347
int mrbc_delete_task(mrbc_tcb *tcb)
Definition rrt0.c:262
struct RTcb mrbc_tcb
Task control block.
MrbcTaskState
Task state.
Definition rrt0.h:45
@ TASKSTATE_SUSPENDED
Suspended.
Definition rrt0.h:50
@ TASKSTATE_READY
Ready.
Definition rrt0.h:47
@ TASKSTATE_WAITING
Waiting.
Definition rrt0.h:49
@ TASKSTATE_RUNNING
Running.
Definition rrt0.h:48
@ TASKSTATE_DORMANT
Domant.
Definition rrt0.h:46
static const int MRBC_TASK_DEFAULT_STATE
Definition rrt0.h:60
struct RMutex mrbc_mutex
Mutex.
static mrbc_tcb * mrbc_get_tcb(const mrbc_vm *vm)
Definition rrt0.h:147
@ TASKREASON_JOIN
Definition rrt0.h:56
@ TASKREASON_MUTEX
Definition rrt0.h:55
@ TASKREASON_SLEEP
Definition rrt0.h:54
#define MRBC_TASK_NAME_LEN
Definition rrt0.h:63
#define MRBC_MUTEX_INITIALIZER
Definition rrt0.h:108
static const int MRBC_TASK_DEFAULT_PRIORITY
Definition rrt0.h:59
struct RMethod * method_link
pointer to method link.
Definition class.h:107
struct RClass * super
pointer to super class.
Definition class.h:103
mrbc_sym sym_id
class name's symbol ID
Definition class.h:97
uint8_t data[]
extended data
Definition class.h:184
volatile int lock
Definition rrt0.h:104
struct RTcb * tcb
Definition rrt0.h:105
struct RInstance * instance
Definition boxing_no.h:29
struct RClass * cls
Definition boxing_no.h:28
uint8_t priority
task priority. initial value.
Definition rrt0.h:81
struct VM vm
Definition rrt0.h:94
char name[MRBC_TASK_NAME_LEN+1]
task name (optional)
Definition rrt0.h:86
const struct RTcb * tcb_join
joined task.
Definition rrt0.h:92
uint8_t priority_preemption
task priority. effective value.
Definition rrt0.h:82
uint8_t state
task state. defined in MrbcTaskState.
Definition rrt0.h:84
struct RMutex * mutex
Definition rrt0.h:90
volatile uint8_t timeslice
time slice counter.
Definition rrt0.h:83
uint8_t reason
sub state. defined in MrbcTaskReason.
Definition rrt0.h:85
uint32_t wakeup_tick
wakeup time for sleep state.
Definition rrt0.h:89
struct RTcb * next
daisy chain in task queue.
Definition rrt0.h:80
Virtual Machine.
Definition vm.h:150
uint16_t regs_size
size of regs[]
Definition vm.h:171
volatile int8_t flag_preemption
Definition vm.h:155
mrbc_value exception
Raised exception or nil.
Definition vm.h:169
unsigned int flag_permanence
Definition vm.h:158
mrbc_value regs[]
Definition vm.h:172
void mrbc_cleanup_symbol(void)
Definition symbol.c:208
float mrbc_float_t
Definition value.h:52
int32_t mrbc_int_t
Definition value.h:47
static void mrbc_decref(mrbc_value *v)
Definition value.h:561
#define SET_BOOL_RETURN(n)
Definition value.h:238
#define SET_INT_RETURN(n)
Definition value.h:243
#define MRBC_PTR_TO_UINT32(p)
Definition value.h:504
#define SET_NIL_RETURN()
Definition value.h:226
static void mrbc_incref(mrbc_value *v)
Definition value.h:546
@ MRBC_TT_STRING
String.
Definition value.h:98
@ MRBC_TT_FLOAT
Float.
Definition value.h:88
@ MRBC_TT_INTEGER
Integer.
Definition value.h:86
@ MRBC_TT_EXCEPTION
Exception.
Definition value.h:101
@ MRBC_TT_CLASS
Class.
Definition value.h:90
#define SET_RETURN(n)
Definition value.h:221
void mrbc_vm_close(mrbc_vm *vm)
Definition vm.c:398
mrbc_vm * mrbc_vm_open(mrbc_vm *vm)
Definition vm.c:305
int mrbc_vm_run(mrbc_vm *vm)
Definition vm.c:3160
void mrbc_vm_end(mrbc_vm *vm)
Definition vm.c:362
void mrbc_cleanup_vm(void)
Definition vm.c:197
void mrbc_vm_begin(mrbc_vm *vm)
Definition vm.c:336
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.
#define MAX_REGS_SIZE
Definition vm_config.h:25