mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
rrt0.c
Go to the documentation of this file.
1
12
13/***** Feature test switches ************************************************/
14/***** System headers *******************************************************/
15//@cond
16#include "vm_config.h"
17#include <stddef.h>
18#include <stdint.h>
19#include <string.h>
20#include <assert.h>
21//@endcond
22
23/***** Local headers ********************************************************/
24#include "mrubyc.h"
25
26/***** Macros ***************************************************************/
27#ifndef MRBC_SCHEDULER_EXIT
28#define MRBC_SCHEDULER_EXIT 0
29#endif
30
31#define VM2TCB(p) ((mrbc_tcb *)((uint8_t *)p - offsetof(mrbc_tcb, vm)))
32#define MRBC_MUTEX_TRACE(...) ((void)0)
33
34
35/***** Typedefs *************************************************************/
36/***** Function prototypes **************************************************/
37/***** Local variables ******************************************************/
38#define NUM_TASK_QUEUE 4
40#define q_dormant_ (task_queue_[0])
41#define q_ready_ (task_queue_[1])
42#define q_waiting_ (task_queue_[2])
43#define q_suspended_ (task_queue_[3])
44static volatile uint32_t tick_;
45static volatile uint32_t wakeup_tick_ = (1 << 16); // no significant meaning.
46
47
48/***** Global variables *****************************************************/
49/***** Signal catching functions ********************************************/
50/***** Functions ************************************************************/
51//================================================================
62static void q_insert_task(mrbc_tcb *p_tcb)
63{
64 // select target queue pointer.
65 // state value = 0 1 2 3 4 5 6 7 8
66 // /2 0, 0, 1, 1, 2, 2, 3, 3, 4
67 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
68 mrbc_tcb **pp_q = &task_queue_[ conv_tbl[ p_tcb->state / 2 ]];
69
70 // in case of insert on top.
71 if((*pp_q == NULL) ||
72 (p_tcb->priority_preemption < (*pp_q)->priority_preemption)) {
73 p_tcb->next = *pp_q;
74 *pp_q = p_tcb;
75 return;
76 }
77
78 // find insert point in sorted linked list.
79 mrbc_tcb *p = *pp_q;
80 while( p->next != NULL ) {
81 if( p_tcb->priority_preemption < p->next->priority_preemption ) break;
82 p = p->next;
83 }
84
85 // insert tcb to queue.
86 p_tcb->next = p->next;
87 p->next = p_tcb;
88}
89
90
91//================================================================
96static void q_delete_task(mrbc_tcb *p_tcb)
97{
98 // select target queue pointer. (same as q_insert_task)
99 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
100 mrbc_tcb **pp_q = &task_queue_[ conv_tbl[ p_tcb->state / 2 ]];
101
102 if( *pp_q == p_tcb ) {
103 *pp_q = p_tcb->next;
104 p_tcb->next = NULL;
105 return;
106 }
107
108 mrbc_tcb *p = *pp_q;
109 while( p ) {
110 if( p->next == p_tcb ) {
111 p->next = p_tcb->next;
112 p_tcb->next = NULL;
113 return;
114 }
115
116 p = p->next;
117 }
118
119 assert(!"Not found target task in queue.");
120}
121
122
123//================================================================
126inline static void preempt_running_task(void)
127{
128 for( mrbc_tcb *t = q_ready_; t != NULL; t = t->next ) {
129 if( t->state == TASKSTATE_RUNNING ) t->vm.flag_preemption = 1;
130 }
131}
132
133
134//================================================================
138#if defined(__EMSCRIPTEN__)
139#include <emscripten.h>
140EMSCRIPTEN_KEEPALIVE
141#endif
142void mrbc_tick(void)
143{
144 tick_++;
145
146 // Decrease the time slice value for running tasks.
147 mrbc_tcb *tcb = q_ready_;
148 if( (tcb != NULL) && (tcb->timeslice != 0) ) {
149 tcb->timeslice--;
150 if( tcb->timeslice == 0 ) tcb->vm.flag_preemption = 1;
151 }
152
153 // Check the wakeup tick.
154 if( (int32_t)(wakeup_tick_ - tick_) < 0 ) {
155 int flag_preemption = 0;
156 wakeup_tick_ = tick_ + (1 << 16);
157
158 // Find a wake up task in waiting task queue.
159 tcb = q_waiting_;
160 while( tcb != NULL ) {
161 mrbc_tcb *t = tcb;
162 tcb = tcb->next;
163 if( t->reason != TASKREASON_SLEEP ) continue;
164
165 if( (int32_t)(t->wakeup_tick - tick_) < 0 ) {
166 q_delete_task(t);
168 t->reason = 0;
169 q_insert_task(t);
170 flag_preemption = 1;
171 } else if( (int32_t)(t->wakeup_tick - wakeup_tick_) < 0 ) {
173 }
174 }
175
176 if( flag_preemption ) preempt_running_task();
177 }
178}
179
180
181//================================================================
200mrbc_tcb * mrbc_tcb_new( int regs_size, enum MrbcTaskState task_state, int priority )
201{
202 mrbc_tcb *tcb;
203
204 unsigned int size = sizeof(mrbc_tcb) + sizeof(mrbc_value) * regs_size;
205 tcb = mrbc_raw_alloc(size);
206 if( !tcb ) return NULL; // ENOMEM
207
208 memset(tcb, 0, size);
209#if defined(MRBC_DEBUG)
210 memcpy( tcb->obj_mark_, "TCB", 4 );
211#endif
212 tcb->priority = priority;
213 tcb->state = task_state;
214 tcb->vm.regs_size = regs_size;
215
216 return tcb;
217}
218
219
220//================================================================
227mrbc_tcb * mrbc_create_task(const void *byte_code, mrbc_tcb *tcb)
228{
230 if( !tcb ) return NULL; // ENOMEM
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 hal_disable_irq();
248 q_insert_task(tcb);
250 hal_enable_irq();
251
252 return tcb;
253}
254
255
256//================================================================
263{
264 if( tcb->state != TASKSTATE_DORMANT ) return -1;
265
266 hal_disable_irq();
267 q_delete_task(tcb);
268 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 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 hal_enable_irq();
313 return tcb;
314}
315
316
317//================================================================
324{
325 if( tcb->state != TASKSTATE_DORMANT ) return -1;
326
327 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 hal_enable_irq();
338
339 return 0;
340}
341
342
343//================================================================
347int mrbc_run(void)
348{
349 int ret = 0;
350
351 (void)ret; // avoid warning.
352
353 while( 1 ) {
354 mrbc_tcb *tcb = q_ready_;
355 if( tcb == NULL ) { // no task to run.
356#if MRBC_SCHEDULER_EXIT
357 if( !q_waiting_ && !q_suspended_ ) return ret;
358#endif
359 hal_idle_cpu();
360 continue;
361 }
362
363 /*
364 run the task.
365 */
366 tcb->state = TASKSTATE_RUNNING; // to execute.
367 tcb->timeslice = MRBC_TIMESLICE_TICK_COUNT;
368
369#if !defined(MRBC_NO_TIMER)
370 // Using hardware timer.
371 int ret_vm_run = mrbc_vm_run(&tcb->vm);
372 tcb->vm.flag_preemption = 0;
373#else
374 // Emulate time slice preemption.
375 int ret_vm_run;
376 tcb->vm.flag_preemption = 1;
377 while( tcb->timeslice != 0 ) {
378 ret_vm_run = mrbc_vm_run( &tcb->vm );
379 tcb->timeslice--;
380 if( ret_vm_run != 0 ) break;
381 if( tcb->state != TASKSTATE_RUNNING ) break;
382 }
383 mrbc_tick();
384#endif
385
386 /*
387 did the task done?
388 */
389 if( ret_vm_run != 0 ) {
390 hal_disable_irq();
391 q_delete_task(tcb);
393 q_insert_task(tcb);
394 hal_enable_irq();
395
396 if( ! tcb->vm.flag_permanence ) mrbc_vm_end( &tcb->vm );
397 if( ret_vm_run != 1 ) ret = ret_vm_run; // for debug info.
398
399 // find task that called join.
400 for( mrbc_tcb *tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next ) {
401 if( tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb ) {
402 hal_disable_irq();
403 q_delete_task(tcb1);
404 tcb1->state = TASKSTATE_READY;
405 tcb1->reason = 0;
406 q_insert_task(tcb1);
407 hal_enable_irq();
408 }
409 }
410 for( mrbc_tcb *tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next ) {
411 if( tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb ) {
412 tcb1->reason = 0;
413 }
414 }
415 continue;
416 }
417
418 /*
419 Switch task.
420 */
421 if( tcb->state == TASKSTATE_RUNNING ) {
422 tcb->state = TASKSTATE_READY;
423
424 hal_disable_irq();
425 q_delete_task(tcb); // insert task on queue last.
426 q_insert_task(tcb);
427 hal_enable_irq();
428 }
429 continue;
430 }
431}
432
433
434//================================================================
438#if defined(__EMSCRIPTEN__)
439EMSCRIPTEN_KEEPALIVE
440int
441mrbc_run_step(void)
442{
443 // Take the task that can be executed
444 mrbc_tcb *tcb = q_ready_;
445 if (tcb == NULL) {
446 // Even if there is no task to run, return 0
447 // so to wait for callbacks like event listener
448 return 0;
449 }
450
452 tcb->timeslice = MRBC_TIMESLICE_TICK_COUNT;
453
454 int ret_vm_run = mrbc_vm_run(&tcb->vm);
455 tcb->vm.flag_preemption = 0;
456
457 if (ret_vm_run != 0) {
458 hal_disable_irq();
459 q_delete_task(tcb);
461 q_insert_task(tcb);
462 hal_enable_irq();
463
464 if (!tcb->vm.flag_permanence) {
465 mrbc_vm_end(&tcb->vm);
466 }
467
468 for (mrbc_tcb *tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next) {
469 if (tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb) {
470 hal_disable_irq();
471 q_delete_task(tcb1);
472 tcb1->state = TASKSTATE_READY;
473 tcb1->reason = 0;
474 q_insert_task(tcb1);
475 hal_enable_irq();
476 }
477 }
478 for (mrbc_tcb *tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next) {
479 if (tcb1->reason == TASKREASON_JOIN && tcb1->tcb_join == tcb) {
480 tcb1->reason = 0;
481 }
482 }
483
484 return ret_vm_run;
485 }
486
487 // Switch task.
488 if (tcb->state == TASKSTATE_RUNNING) {
489 tcb->state = TASKSTATE_READY;
490 hal_disable_irq();
491 q_delete_task(tcb);
492 q_insert_task(tcb);
493 hal_enable_irq();
494 }
495
496 return 0;
497}
498#endif
499
500
501//================================================================
507void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
508{
509 hal_disable_irq();
510 q_delete_task(tcb);
513 tcb->wakeup_tick = tick_ + (ms / MRBC_TICK_UNIT) + !!(ms % MRBC_TICK_UNIT);
514
515 if( (int32_t)(tcb->wakeup_tick - wakeup_tick_) < 0 ) {
517 }
518
519 q_insert_task(tcb);
520 hal_enable_irq();
521
522 tcb->vm.flag_preemption = 1;
523}
524
525
526//================================================================
532{
533 switch( tcb->state ) {
535 mrbc_resume_task( tcb ); // for sleep without arguments.
536 break;
537
539 if( tcb->reason != TASKREASON_SLEEP ) break;
540
541 hal_disable_irq();
542 q_delete_task(tcb);
543 tcb->state = TASKSTATE_READY;
544 tcb->reason = 0;
545 q_insert_task(tcb);
546
547 for( mrbc_tcb *t = q_waiting_; t != NULL; t = t->next ) {
548 if( t->reason != TASKREASON_SLEEP ) continue;
549 if( (int32_t)(t->wakeup_tick - wakeup_tick_) < 0 ) {
550 wakeup_tick_ = t->wakeup_tick;
551 }
552 }
553 hal_enable_irq();
554 break;
555
556 default:
557 break;
558 }
559}
560
561
562//================================================================
568{
569 tcb->timeslice = 0;
570 tcb->vm.flag_preemption = 1;
571}
572
573
574//================================================================
580void mrbc_change_priority(mrbc_tcb *tcb, int priority)
581{
582 tcb->priority = priority;
583 tcb->priority_preemption = priority;
584
585 hal_disable_irq();
586 q_delete_task(tcb); // reorder task queue according to priority.
587 q_insert_task(tcb);
588
590
591 hal_enable_irq();
592}
593
594
595//================================================================
601{
602 if( tcb->state == TASKSTATE_SUSPENDED ) return;
603
604 hal_disable_irq();
605 q_delete_task(tcb);
607 q_insert_task(tcb);
608 hal_enable_irq();
609
610 tcb->vm.flag_preemption = 1;
611}
612
613
614//================================================================
620{
621 if( tcb->state != TASKSTATE_SUSPENDED ) return;
622
623 int flag_to_ready_state = (tcb->reason == 0);
624
625 hal_disable_irq();
626
627 if( flag_to_ready_state ) preempt_running_task();
628
629 q_delete_task(tcb);
630 tcb->state = flag_to_ready_state ? TASKSTATE_READY : TASKSTATE_WAITING;
631 q_insert_task(tcb);
632
633 hal_enable_irq();
634
635 if( tcb->reason & TASKREASON_SLEEP ) {
636 if( (int32_t)(tcb->wakeup_tick - wakeup_tick_) < 0 ) {
638 }
639 }
640}
641
642
643//================================================================
652{
653 if( tcb->state == TASKSTATE_DORMANT ) return;
654
655 hal_disable_irq();
656 q_delete_task(tcb);
658 q_insert_task(tcb);
659 hal_enable_irq();
660
661 tcb->vm.flag_preemption = 1;
662}
663
664
665//================================================================
671void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
672{
673 if( tcb->state == TASKSTATE_DORMANT ) return;
674 if( tcb_join->state == TASKSTATE_DORMANT ) return;
675
676 hal_disable_irq();
677 q_delete_task(tcb);
678
680 tcb->reason = TASKREASON_JOIN;
681 tcb->tcb_join = tcb_join;
682
683 q_insert_task(tcb);
684 hal_enable_irq();
685
686 tcb->vm.flag_preemption = 1;
687}
688
689
690
691//================================================================
697{
698 if( mutex == NULL ) {
699 mutex = mrbc_raw_alloc( sizeof(mrbc_mutex) );
700 if( mutex == NULL ) return NULL; // ENOMEM
701 }
702
703 static const mrbc_mutex init_val = MRBC_MUTEX_INITIALIZER;
704 *mutex = init_val;
705
706 return mutex;
707}
708
709
710//================================================================
717{
718 MRBC_MUTEX_TRACE("mutex lock / MUTEX: %p TCB: %p", mutex, tcb );
719
720 int ret = 0;
721 hal_disable_irq();
722
723 // Try lock mutex;
724 if( mutex->lock == 0 ) { // a future does use TAS?
725 mutex->lock = 1;
726 mutex->tcb = tcb;
727 MRBC_MUTEX_TRACE(" lock OK\n" );
728 goto DONE;
729 }
730 MRBC_MUTEX_TRACE(" lock FAIL\n" );
731
732 // Can't lock mutex
733 // check recursive lock.
734 if( mutex->tcb == tcb ) {
735 ret = 1;
736 goto DONE;
737 }
738
739 // To WAITING state.
740 q_delete_task(tcb);
743 tcb->mutex = mutex;
744 q_insert_task(tcb);
745 tcb->vm.flag_preemption = 1;
746
747 DONE:
748 hal_enable_irq();
749
750 return ret;
751}
752
753
754//================================================================
761{
762 MRBC_MUTEX_TRACE("mutex unlock / MUTEX: %p TCB: %p\n", mutex, tcb );
763
764 // check some parameters.
765 if( !mutex->lock ) return 1;
766 if( mutex->tcb != tcb ) return 2;
767
768 hal_disable_irq();
769
770 // wakeup ONE waiting task if exist.
771 mrbc_tcb *tcb1;
772 for( tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next ) {
773 if( tcb1->reason == TASKREASON_MUTEX && tcb1->mutex == mutex ) break;
774 }
775 if( tcb1 ) {
776 MRBC_MUTEX_TRACE("SW1: TCB: %p\n", tcb1 );
777 mutex->tcb = tcb1;
778
779 q_delete_task(tcb1);
780 tcb1->state = TASKSTATE_READY;
781 tcb1->reason = 0;
782 q_insert_task(tcb1);
783
785 goto DONE;
786 }
787
788 // find ONE mutex locked task in suspended queue.
789 for( tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next ) {
790 if( tcb1->reason == TASKREASON_MUTEX && tcb1->mutex == mutex ) break;
791 }
792 if( tcb1 ) {
793 MRBC_MUTEX_TRACE("SW2: TCB: %p\n", tcb1 );
794 mutex->tcb = tcb1;
795 tcb1->reason = 0;
796 goto DONE;
797 }
798
799 // other case, unlock mutex
800 MRBC_MUTEX_TRACE("mutex unlock all.\n" );
801 mutex->lock = 0;
802 mutex->tcb = 0;
803
804 DONE:
805 hal_enable_irq();
806
807 return 0;
808}
809
810
811//================================================================
818{
819 MRBC_MUTEX_TRACE("mutex try lock / MUTEX: %p TCB: %p", mutex, tcb );
820
821 int ret;
822 hal_disable_irq();
823
824 if( mutex->lock == 0 ) {
825 mutex->lock = 1;
826 mutex->tcb = tcb;
827 ret = 0;
828 MRBC_MUTEX_TRACE(" trylock OK\n" );
829 }
830 else {
831 MRBC_MUTEX_TRACE(" trylock FAIL\n" );
832 ret = 1;
833 }
834
835 hal_enable_irq();
836 return ret;
837}
838
839
840//================================================================
844void mrbc_cleanup(void)
845{
849
850 memset( task_queue_, 0, sizeof(task_queue_) );
851}
852
853
854//================================================================
858static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
859{
860 mrbc_tcb *tcb = VM2TCB(vm);
861
862 if( argc == 0 ) {
864 return;
865 }
866
867 switch( mrbc_type(v[1]) ) {
868 case MRBC_TT_INTEGER:
869 {
870 mrbc_int_t sec;
871 sec = mrbc_integer(v[1]);
872 SET_INT_RETURN(sec);
873 mrbc_sleep_ms(tcb, sec * 1000);
874 break;
875 }
876
877#if MRBC_USE_FLOAT
878 case MRBC_TT_FLOAT:
879 {
880 mrbc_float_t sec;
881 sec = mrbc_float(v[1]);
882 SET_INT_RETURN(sec);
883 mrbc_sleep_ms(tcb, (mrbc_int_t)(sec * 1000));
884 break;
885 }
886#endif
887
888 default:
889 break;
890 }
891}
892
893
894//================================================================
898static void c_sleep_ms(mrbc_vm *vm, mrbc_value v[], int argc)
899{
900 mrbc_tcb *tcb = VM2TCB(vm);
901
902 mrbc_int_t sec = mrbc_integer(v[1]);
903 SET_INT_RETURN(sec);
904 mrbc_sleep_ms(tcb, sec);
905}
906
907
908
909/*
910 Task class
911*/
912//================================================================
918static void c_task_get(mrbc_vm *vm, mrbc_value v[], int argc)
919{
920 mrbc_tcb *tcb = NULL;
921
922 if( v[0].tt != MRBC_TT_CLASS ) goto RETURN_NIL;
923
924 // in case of Task.get()
925 if( argc == 0 ) {
926 tcb = VM2TCB(vm);
927 }
928
929 // in case of Task.get("TasName")
930 else if( v[1].tt == MRBC_TT_STRING ) {
931 tcb = mrbc_find_task( mrbc_string_cstr( &v[1] ) );
932 }
933
934 if( tcb ) {
935 mrbc_value ret = mrbc_instance_new(vm, v->cls, sizeof(mrbc_tcb *));
936 *(mrbc_tcb **)ret.instance->data = tcb;
937 SET_RETURN(ret);
938 return; // normal return.
939 }
940
941 RETURN_NIL:
943}
944
945
946//================================================================
951static void c_task_list(mrbc_vm *vm, mrbc_value v[], int argc)
952{
953 mrbc_value ret = mrbc_array_new(vm, 1);
954
955 hal_disable_irq();
956
957 for( int i = 0; i < NUM_TASK_QUEUE; i++ ) {
958 for( mrbc_tcb *tcb = task_queue_[i]; tcb != NULL; tcb = tcb->next ) {
959 mrbc_value task = mrbc_instance_new(vm, v->cls, sizeof(mrbc_tcb *));
960 *(mrbc_tcb **)task.instance->data = tcb;
961 mrbc_array_push( &ret, &task );
962 }
963 }
964
965 hal_enable_irq();
966
967 SET_RETURN(ret);
968}
969
970
971//================================================================
976static void c_task_name_list(mrbc_vm *vm, mrbc_value v[], int argc)
977{
978 mrbc_value ret = mrbc_array_new(vm, 1);
979
980 hal_disable_irq();
981
982 for( int i = 0; i < NUM_TASK_QUEUE; i++ ) {
983 for( mrbc_tcb *tcb = task_queue_[i]; tcb != NULL; tcb = tcb->next ) {
985 mrbc_array_push( &ret, &s );
986 }
987 }
988
989 hal_enable_irq();
990
991 SET_RETURN(ret);
992}
993
994
995//================================================================
1000static void c_task_set_name(mrbc_vm *vm, mrbc_value v[], int argc)
1001{
1002 if( v[1].tt != MRBC_TT_STRING ) {
1003 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1004 return;
1005 }
1006
1007 mrbc_tcb *tcb;
1008
1009 if( v[0].tt == MRBC_TT_CLASS ) {
1010 tcb = VM2TCB(vm);
1011 } else {
1012 tcb = *(mrbc_tcb **)v[0].instance->data;
1013 }
1014 mrbc_set_task_name( tcb, mrbc_string_cstr(&v[1]) );
1015
1016 mrbc_incref( &v[1] );
1017 SET_RETURN( v[1] );
1018}
1019
1020
1021//================================================================
1027static void c_task_name(mrbc_vm *vm, mrbc_value v[], int argc)
1028{
1029 mrbc_value ret;
1030
1031 if( v[0].tt == MRBC_TT_CLASS ) {
1032 ret = mrbc_string_new_cstr( vm, VM2TCB(vm)->name );
1033 } else {
1034 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1035 ret = mrbc_string_new_cstr(vm, tcb->name );
1036 }
1037
1038 SET_RETURN(ret);
1039}
1040
1041
1042//================================================================
1048static void c_task_set_priority(mrbc_vm *vm, mrbc_value v[], int argc)
1049{
1050 mrbc_tcb *tcb;
1051
1052 if( v[0].tt == MRBC_TT_CLASS ) {
1053 tcb = VM2TCB(vm);
1054 } else {
1055 tcb = *(mrbc_tcb **)v[0].instance->data;
1056 }
1057
1058 if( v[1].tt != MRBC_TT_INTEGER ) {
1059 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1060 return;
1061 }
1062 int n = mrbc_integer( v[1] );
1063 if( n < 0 || n > 255 ) {
1064 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1065 return;
1066 }
1067
1068 mrbc_change_priority( tcb, n );
1069
1070 SET_RETURN( v[1] );
1071}
1072
1073
1074//================================================================
1079static void c_task_priority(mrbc_vm *vm, mrbc_value v[], int argc)
1080{
1081 mrbc_tcb *tcb;
1082
1083 if( v[0].tt == MRBC_TT_CLASS ) {
1084 tcb = VM2TCB(vm);
1085 } else {
1086 tcb = *(mrbc_tcb **)v[0].instance->data;
1087 }
1088
1089 SET_INT_RETURN( tcb->priority );
1090}
1091
1092
1093//================================================================
1098static void c_task_status(mrbc_vm *vm, mrbc_value v[], int argc)
1099{
1100 static const char *status_name[] =
1101 { "DORMANT", "READY", "WAITING ", "", "SUSPENDED" };
1102 static const char *reason_name[] =
1103 { "", "SLEEP", "MUTEX", "", "JOIN" };
1104
1105 if( v[0].tt == MRBC_TT_CLASS ) return;
1106
1107 const mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1108 mrbc_value ret = mrbc_string_new_cstr( vm, status_name[tcb->state / 2] );
1109
1110 if( tcb->state == TASKSTATE_WAITING ) {
1111 mrbc_string_append_cstr( &ret, reason_name[tcb->reason] );
1112 }
1113
1114 SET_RETURN(ret);
1115}
1116
1117
1118//================================================================
1124static void c_task_suspend(mrbc_vm *vm, mrbc_value v[], int argc)
1125{
1126 mrbc_tcb *tcb;
1127
1128 if( v[0].tt == MRBC_TT_CLASS ) {
1129 tcb = VM2TCB(vm);
1130 } else {
1131 tcb = *(mrbc_tcb **)v[0].instance->data;
1132 }
1133
1134 mrbc_suspend_task(tcb);
1135}
1136
1137
1138//================================================================
1143static void c_task_resume(mrbc_vm *vm, mrbc_value v[], int argc)
1144{
1145 if( v[0].tt == MRBC_TT_CLASS ) return;
1146
1147 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1148
1149 mrbc_resume_task(tcb);
1150}
1151
1152
1153//================================================================
1158static void c_task_terminate(mrbc_vm *vm, mrbc_value v[], int argc)
1159{
1160 mrbc_tcb *tcb;
1161
1162 if( v[0].tt == MRBC_TT_CLASS ) {
1163 tcb = VM2TCB(vm);
1164 } else {
1165 tcb = *(mrbc_tcb **)v[0].instance->data;
1166 }
1167
1169}
1170
1171
1172//================================================================
1178static void c_task_raise(mrbc_vm *vm, mrbc_value v[], int argc)
1179{
1180 if( v[0].tt == MRBC_TT_CLASS ) return;
1181 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1182 mrbc_vm *vm1 = &tcb->vm;
1183 mrbc_value exc;
1184
1185 if( argc == 0 ) {
1186 exc = mrbc_exception_new( vm1, MRBC_CLASS(RuntimeError), 0, 0 );
1187 } else if( v[1].tt == MRBC_TT_EXCEPTION ) {
1188 exc = v[1];
1189 mrbc_incref(&exc);
1190 } else {
1191 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1192 return;
1193 }
1194
1195 mrbc_decref(&vm1->exception);
1196 vm1->exception = exc;
1197 vm1->flag_preemption = 2;
1198
1199 if( tcb->state == TASKSTATE_WAITING && tcb->reason == TASKREASON_SLEEP ) {
1200 void mrbc_wakeup_task(mrbc_tcb *tcb);
1201 mrbc_wakeup_task( tcb );
1202 }
1203}
1204
1205
1206//================================================================
1211static void c_task_join(mrbc_vm *vm, mrbc_value v[], int argc)
1212{
1213 if( v[0].tt == MRBC_TT_CLASS ) return;
1214
1215 mrbc_tcb *tcb_me = VM2TCB(vm);
1216 mrbc_tcb *tcb_join = *(mrbc_tcb **)v[0].instance->data;
1217
1218 mrbc_join_task(tcb_me, tcb_join);
1219}
1220
1221
1222//================================================================
1227static void c_task_value(mrbc_vm *vm, mrbc_value v[], int argc)
1228{
1229 if( v[0].tt == MRBC_TT_CLASS ) return;
1230
1231 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1232
1233 if( tcb->state != TASKSTATE_DORMANT ) {
1234 mrbc_raise(vm, 0, "task must be end");
1235 return;
1236 }
1237
1238 mrbc_incref( &tcb->vm.regs[0] );
1239 SET_RETURN( tcb->vm.regs[0] );
1240}
1241
1242
1243//================================================================
1248static void c_task_pass(mrbc_vm *vm, mrbc_value v[], int argc)
1249{
1250 if( v[0].tt != MRBC_TT_CLASS ) return;
1251
1252 mrbc_tcb *tcb = VM2TCB(vm);
1253 mrbc_relinquish(tcb);
1254}
1255
1256
1257//================================================================
1262static void c_task_create(mrbc_vm *vm, mrbc_value v[], int argc)
1263{
1264 const char *byte_code;
1265 int regs_size = MAX_REGS_SIZE;
1266
1267 // check argument.
1268 if( v[0].tt != MRBC_TT_CLASS ) goto ERROR_ARGUMENT;
1269
1270 if( argc >= 1 && v[1].tt != MRBC_TT_STRING ) goto ERROR_ARGUMENT;
1271 mrbc_incref( &v[1] );
1272 byte_code = mrbc_string_cstr(&v[1]);
1273
1274 if( argc >= 2 ) {
1275 if( v[2].tt != MRBC_TT_INTEGER ) goto ERROR_ARGUMENT;
1276 regs_size = mrbc_integer(v[2]);
1277 }
1278
1279 // create TCB
1281 if( !tcb ) {
1282 mrbc_raise( vm, MRBC_CLASS(NoMemoryError), 0 );
1283 return;
1284 }
1285 tcb->vm.flag_permanence = 1;
1286
1287 if( !mrbc_create_task( byte_code, tcb ) ) return;
1288
1289 // create Instance
1290 mrbc_value ret = mrbc_instance_new(vm, v->cls, sizeof(mrbc_tcb *));
1291 *(mrbc_tcb **)ret.instance->data = tcb;
1292 SET_RETURN( ret );
1293 return;
1294
1295 ERROR_ARGUMENT:
1296 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1297}
1298
1299
1300//================================================================
1305static void c_task_run(mrbc_vm *vm, mrbc_value v[], int argc)
1306{
1307 if( v[0].tt == MRBC_TT_CLASS ) return;
1308
1309 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1310 if( tcb->state != TASKSTATE_DORMANT ) return;
1311
1312 mrbc_start_task(tcb);
1313}
1314
1315
1316//================================================================
1321static void c_task_rewind(mrbc_vm *vm, mrbc_value v[], int argc)
1322{
1323 if( v[0].tt == MRBC_TT_CLASS ) return;
1324
1325 mrbc_tcb *tcb = *(mrbc_tcb **)v[0].instance->data;
1326 if( tcb->state != TASKSTATE_DORMANT ) return;
1327
1328 mrbc_vm_begin( &tcb->vm );
1329}
1330
1331
1332/* MRBC_AUTOGEN_METHOD_TABLE
1333
1334 CLASS("Task")
1335 FILE("_autogen_class_rrt0.h")
1336
1337 METHOD( "get", c_task_get )
1338 METHOD( "current", c_task_get )
1339 METHOD( "list", c_task_list )
1340 METHOD( "name_list", c_task_name_list )
1341 METHOD( "name=", c_task_set_name )
1342 METHOD( "name", c_task_name )
1343 METHOD( "priority=", c_task_set_priority )
1344 METHOD( "priority", c_task_priority )
1345 METHOD( "status", c_task_status )
1346
1347 METHOD( "suspend", c_task_suspend )
1348 METHOD( "resume", c_task_resume )
1349 METHOD( "terminate", c_task_terminate )
1350 METHOD( "raise", c_task_raise )
1351
1352 METHOD( "join", c_task_join )
1353 METHOD( "value", c_task_value )
1354 METHOD( "pass", c_task_pass )
1355
1356 METHOD( "create", c_task_create )
1357 METHOD( "run", c_task_run )
1358 METHOD( "rewind", c_task_rewind )
1359*/
1360
1361
1362/*
1363 Mutex class
1364*/
1365//================================================================
1369static void c_mutex_new(mrbc_vm *vm, mrbc_value v[], int argc)
1370{
1371 *v = mrbc_instance_new(vm, v->cls, sizeof(mrbc_mutex));
1372 if( !v->instance ) return;
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, VM2TCB(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{
1398 int r = mrbc_mutex_unlock( (mrbc_mutex *)v->instance->data, VM2TCB(vm) );
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{
1412 int r = mrbc_mutex_trylock( (mrbc_mutex *)v->instance->data, VM2TCB(vm) );
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 == VM2TCB(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 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 };
1496 mrbc_value vcls = {.tt = MRBC_TT_CLASS};
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 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 hal_enable_irq();
1584}
1585#endif
void * mrbc_raw_alloc(unsigned int size)
Definition alloc.c:500
void mrbc_init_alloc(void *ptr, unsigned int size)
Definition alloc.c:438
void mrbc_cleanup_alloc(void)
Definition alloc.c:481
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:252
mrbc_value mrbc_array_new(struct VM *vm, int size)
Definition c_array.c:82
static char * mrbc_string_cstr(const mrbc_value *v)
Definition c_string.h:116
static mrbc_value mrbc_string_new_cstr(struct VM *vm, const char *src)
Definition c_string.h:85
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:128
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:331
void mrbc_init_class(void)
Definition class.c:633
void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
Definition class.c:304
#define MRBC_CLASS(cls)
Definition class.h:51
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:180
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:236
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:39
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:53
int mrbc_load_mrb(struct VM *vm, const void *bytecode)
Definition load.c:292
Include at once the necessary header files.
void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
Definition rrt0.c:671
static volatile uint32_t wakeup_tick_
Definition rrt0.c:45
void mrbc_set_task_name(mrbc_tcb *tcb, const char *name)
Definition rrt0.c:282
#define q_ready_
Definition rrt0.c:41
void mrbc_init(void *heap_ptr, unsigned int size)
Definition rrt0.c:1479
void mrbc_terminate_task(mrbc_tcb *tcb)
Definition rrt0.c:651
#define NUM_TASK_QUEUE
Definition rrt0.c:38
void mrbc_resume_task(mrbc_tcb *tcb)
Definition rrt0.c:619
int mrbc_mutex_unlock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:760
#define q_dormant_
Definition rrt0.c:40
void mrbc_cleanup(void)
Definition rrt0.c:844
#define VM2TCB(p)
Definition rrt0.c:31
mrbc_tcb * mrbc_tcb_new(int regs_size, enum MrbcTaskState task_state, int priority)
Definition rrt0.c:200
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:227
static void q_delete_task(mrbc_tcb *p_tcb)
Definition rrt0.c:96
void mrbc_tick(void)
Definition rrt0.c:142
static void q_insert_task(mrbc_tcb *p_tcb)
Definition rrt0.c:62
mrbc_mutex * mrbc_mutex_init(mrbc_mutex *mutex)
Definition rrt0.c:696
void mrbc_change_priority(mrbc_tcb *tcb, int priority)
Definition rrt0.c:580
void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
Definition rrt0.c:507
int mrbc_mutex_trylock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:817
int mrbc_mutex_lock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:716
static volatile uint32_t tick_
Definition rrt0.c:44
#define q_suspended_
Definition rrt0.c:43
#define MRBC_MUTEX_TRACE(...)
Definition rrt0.c:32
void mrbc_suspend_task(mrbc_tcb *tcb)
Definition rrt0.c:600
void mrbc_wakeup_task(mrbc_tcb *tcb)
Definition rrt0.c:531
void mrbc_relinquish(mrbc_tcb *tcb)
Definition rrt0.c:567
static void preempt_running_task(void)
Definition rrt0.c:126
#define q_waiting_
Definition rrt0.c:42
int mrbc_start_task(mrbc_tcb *tcb)
Definition rrt0.c:323
static mrbc_tcb * task_queue_[NUM_TASK_QUEUE]
Definition rrt0.c:39
static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
Definition rrt0.c:858
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:41
@ TASKSTATE_SUSPENDED
Suspended.
Definition rrt0.h:46
@ TASKSTATE_READY
Ready.
Definition rrt0.h:43
@ TASKSTATE_WAITING
Waiting.
Definition rrt0.h:45
@ TASKSTATE_RUNNING
Running.
Definition rrt0.h:44
@ TASKSTATE_DORMANT
Domant.
Definition rrt0.h:42
static const int MRBC_TASK_DEFAULT_STATE
Definition rrt0.h:56
struct RMutex mrbc_mutex
Mutex.
@ TASKREASON_JOIN
Definition rrt0.h:52
@ TASKREASON_MUTEX
Definition rrt0.h:51
@ TASKREASON_SLEEP
Definition rrt0.h:50
#define MRBC_TASK_NAME_LEN
Definition rrt0.h:59
#define MRBC_MUTEX_INITIALIZER
Definition rrt0.h:104
static const int MRBC_TASK_DEFAULT_PRIORITY
Definition rrt0.h:55
struct RMethod * method_link
pointer to method link.
Definition class.h:91
struct RClass * super
pointer to super class.
Definition class.h:89
mrbc_sym sym_id
class name's symbol ID
Definition class.h:84
uint8_t data[]
extended data
Definition class.h:160
volatile int lock
Definition rrt0.h:100
struct RTcb * tcb
Definition rrt0.h:101
struct RInstance * instance
Definition value.h:161
struct RClass * cls
Definition value.h:160
uint8_t priority
task priority. initial value.
Definition rrt0.h:77
struct VM vm
Definition rrt0.h:90
char name[MRBC_TASK_NAME_LEN+1]
task name (optional)
Definition rrt0.h:82
const struct RTcb * tcb_join
joined task.
Definition rrt0.h:88
uint8_t priority_preemption
task priority. effective value.
Definition rrt0.h:78
uint8_t state
task state. defined in MrbcTaskState.
Definition rrt0.h:80
struct RMutex * mutex
Definition rrt0.h:86
volatile uint8_t timeslice
time slice counter.
Definition rrt0.h:79
uint8_t reason
sub state. defined in MrbcTaskReason.
Definition rrt0.h:81
uint32_t wakeup_tick
wakeup time for sleep state.
Definition rrt0.h:85
struct RTcb * next
daisy chain in task queue.
Definition rrt0.h:76
Virtual Machine.
Definition vm.h:140
uint16_t regs_size
size of regs[]
Definition vm.h:150
volatile int8_t flag_preemption
Definition vm.h:145
mrbc_value exception
Raised exception or nil.
Definition vm.h:160
unsigned int flag_permanence
Definition vm.h:148
mrbc_value regs[]
Definition vm.h:161
void mrbc_cleanup_symbol(void)
Definition symbol.c:204
float mrbc_float_t
Definition value.h:51
int32_t mrbc_int_t
Definition value.h:45
static void mrbc_decref(mrbc_value *v)
Definition value.h:604
#define SET_BOOL_RETURN(n)
Definition value.h:278
#define SET_INT_RETURN(n)
Definition value.h:283
#define MRBC_PTR_TO_UINT32(p)
Definition value.h:548
#define SET_NIL_RETURN()
Definition value.h:266
static void mrbc_incref(mrbc_value *v)
Definition value.h:589
#define mrbc_type(o)
Definition value.h:193
@ MRBC_TT_STRING
String.
Definition value.h:95
@ MRBC_TT_FLOAT
Float.
Definition value.h:85
@ MRBC_TT_INTEGER
Integer.
Definition value.h:83
@ MRBC_TT_EXCEPTION
Exception.
Definition value.h:98
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
#define mrbc_float(o)
Definition value.h:195
#define SET_RETURN(n)
Definition value.h:261
#define mrbc_integer(o)
Definition value.h:194
void mrbc_vm_end(struct VM *vm)
Definition vm.c:375
mrbc_vm * mrbc_vm_open(struct VM *vm)
Definition vm.c:316
void mrbc_vm_begin(struct VM *vm)
Definition vm.c:348
void mrbc_cleanup_vm(void)
Definition vm.c:180
int mrbc_vm_run(struct VM *vm)
Definition vm.c:2889
void mrbc_vm_close(struct VM *vm)
Definition vm.c:411
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.
#define MAX_REGS_SIZE
Definition vm_config.h:23