mruby/c VM Source Code master (2026/08/06)
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#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); \
43 } while(0)
44
45/***** Typedefs *************************************************************/
46/***** Function prototypes **************************************************/
47/***** Local variables ******************************************************/
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])
54static volatile uint32_t tick_;
55static volatile uint32_t wakeup_tick_ = ((uint32_t)1 << 16); // no significant meaning.
56
57#if defined(MRBC_TASK_SCHEDULER_HOOK)
58static void (*scheduler_hook_)(void *ud);
59static void *scheduler_hook_ud_;
60#endif
61
62
63/***** Global variables *****************************************************/
64/***** Signal catching functions ********************************************/
65/***** Functions ************************************************************/
66#if defined(MRBC_TASK_SCHEDULER_HOOK)
67//================================================================
75void mrbc_task_set_scheduler_hook(void (*fn)(void *ud), void *ud)
76{
77 scheduler_hook_ = fn;
78 scheduler_hook_ud_ = ud;
79}
80#endif
81
82
83//================================================================
95{
96 // select target queue pointer.
97 // state value = 0 1 2 3 4 5 6 7 8
98 // /2 0, 0, 1, 1, 2, 2, 3, 3, 4
99 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
100 mrbc_tcb **pp_q = &tcb_queue_[ conv_tbl[ p_tcb->state / 2 ]];
101
102 // in case of insert on top.
103 if((*pp_q == NULL) ||
104 (p_tcb->priority_preemption < (*pp_q)->priority_preemption)) {
105 p_tcb->next = *pp_q;
106 *pp_q = p_tcb;
107 return;
108 }
109
110 // find insert point in sorted linked list.
111 mrbc_tcb *p = *pp_q;
112 while( p->next != NULL ) {
113 if( p_tcb->priority_preemption < p->next->priority_preemption ) break;
114 p = p->next;
115 }
116
117 // insert tcb to queue.
118 p_tcb->next = p->next;
119 p->next = p_tcb;
120}
121
122
123//================================================================
129{
130 // select target queue pointer. (same as mrbc_task_q_insert)
131 static const uint8_t conv_tbl[] = { 0, 1, 2, 0, 3 };
132 mrbc_tcb **pp_q = &tcb_queue_[ conv_tbl[ p_tcb->state / 2 ]];
133
134 if( *pp_q == p_tcb ) {
135 *pp_q = p_tcb->next;
136 p_tcb->next = NULL;
137 return;
138 }
139
140 mrbc_tcb *p = *pp_q;
141 while( p ) {
142 if( p->next == p_tcb ) {
143 p->next = p_tcb->next;
144 p_tcb->next = NULL;
145 return;
146 }
147
148 p = p->next;
149 }
150
151 assert(!"Not found target task in queue.");
152}
153
154
155//================================================================
164{
165 return q_waiting_;
166}
167
168
169//================================================================
172inline static void preempt_running_task(void)
173{
174 for( mrbc_tcb *t = q_ready_; t != NULL; t = t->next ) {
175 if( t->state == TASKSTATE_RUNNING ) t->vm.flag_preemption = 1;
176 }
177}
178
179
180//================================================================
191static int get_timed_wakeup_tick(const mrbc_tcb *t, uint32_t *out)
192{
193 if( t->reason == TASKREASON_SLEEP ) {
194 *out = t->wakeup_tick;
195 return 1;
196 }
198 *out = t->queue.wakeup_tick;
199 return 1;
200 }
201 return 0;
202}
203
204
205//================================================================
209#if defined(__EMSCRIPTEN__)
210#include <emscripten.h>
211EMSCRIPTEN_KEEPALIVE
212#endif
213void mrbc_tick(void)
214{
215 tick_++;
216
217 // Decrease the time slice value for running tasks.
218 mrbc_tcb *tcb = q_ready_;
219 if( (tcb != NULL) && (tcb->timeslice != 0) ) {
220 tcb->timeslice--;
221 if( tcb->timeslice == 0 ) tcb->vm.flag_preemption = 1;
222 }
223
224 // Check the wakeup tick.
225 if( (int32_t)(wakeup_tick_ - tick_) < 0 ) {
226 int flag_preemption = 0;
227 wakeup_tick_ = tick_ + ((uint32_t)1 << 16);
228
229 // Find a wake up task in waiting task queue. Both sleeping tasks and
230 // tasks blocked on a queue with a timeout carry a deadline.
231 tcb = q_waiting_;
232 while( tcb != NULL ) {
233 mrbc_tcb *t = tcb;
234 tcb = tcb->next;
235 uint32_t wake;
236 if( !get_timed_wakeup_tick(t, &wake) ) continue;
237
238 if( (int32_t)(wake - tick_) < 0 ) {
241 t->reason = 0;
243 flag_preemption = 1;
244 } else if( (int32_t)(wake - wakeup_tick_) < 0 ) {
245 wakeup_tick_ = wake;
246 }
247 }
248
249 if( flag_preemption ) preempt_running_task();
250 }
251}
252
253
254//================================================================
273mrbc_tcb * mrbc_tcb_new( int regs_size, enum MrbcTaskState task_state, int priority )
274{
275 mrbc_tcb *tcb;
276 unsigned int size = sizeof(mrbc_tcb) + sizeof(mrbc_value) * regs_size;
277
278 tcb = mrbc_raw_alloc(size);
279 memset(tcb, 0, size);
280#if defined(MRBC_DEBUG)
281 memcpy( tcb->obj_mark_, "TCB", 4 );
282#endif
283 tcb->priority = priority;
284 tcb->state = task_state;
285 tcb->vm.regs_size = regs_size;
286
287 return tcb;
288}
289
290
291//================================================================
298mrbc_tcb * mrbc_create_task(const void *byte_code, mrbc_tcb *tcb)
299{
301
302 tcb->priority_preemption = tcb->priority;
303
304 // assign VM ID
305 if( mrbc_vm_open( &tcb->vm ) == NULL ) {
306 mrbc_printf("Error: Can't assign VM-ID.\n");
307 return NULL;
308 }
309
310 if( mrbc_load_mrb(&tcb->vm, byte_code) != 0 ) {
312 mrbc_vm_close( &tcb->vm );
313 return NULL;
314 }
315 mrbc_vm_begin( &tcb->vm );
316
317 mrbc_hal_disable_irq();
320 mrbc_hal_enable_irq();
321
322 return tcb;
323}
324
325
326//================================================================
333{
334 if( tcb->state != TASKSTATE_DORMANT ) return -1;
335
336 mrbc_hal_disable_irq();
338 mrbc_hal_enable_irq();
339
340 mrbc_vm_close( &tcb->vm );
341
342 return 0;
343}
344
345
346//================================================================
352void mrbc_set_task_name(mrbc_tcb *tcb, const char *name)
353{
354 /* (note)
355 this is `strncpy( tcb->name, name, MRBC_TASK_NAME_LEN );`
356 for to avoid link error when compiling for PIC32 with XC32 v4.21
357 */
358 for( int i = 0; i < MRBC_TASK_NAME_LEN; i++ ) {
359 if( (tcb->name[i] = *name++) == 0 ) break;
360 }
361}
362
363
364//================================================================
370mrbc_tcb * mrbc_find_task(const char *name)
371{
372 mrbc_tcb *tcb = NULL;
373 mrbc_hal_disable_irq();
374
375 for( int i = 0; i < NUM_TCB_QUEUE; i++ ) {
376 for( tcb = tcb_queue_[i]; tcb != NULL; tcb = tcb->next ) {
377 if( strcmp( tcb->name, name ) == 0 ) goto RETURN_TCB;
378 }
379 }
380
381 RETURN_TCB:
382 mrbc_hal_enable_irq();
383 return tcb;
384}
385
386
387//================================================================
394{
395 if( tcb->state != TASKSTATE_DORMANT ) return -1;
396
397 mrbc_hal_disable_irq();
398
400
402 tcb->state = TASKSTATE_READY;
403 tcb->reason = 0;
404 tcb->priority_preemption = tcb->priority;
406
407 mrbc_hal_enable_irq();
408
409 return 0;
410}
411
412
413//----------------------------------------------------------------
414static void terminate_task( mrbc_tcb *tcb )
415{
416 mrbc_hal_disable_irq();
420 mrbc_hal_enable_irq();
421
422 if( ! tcb->vm.flag_permanence ) mrbc_vm_end( &tcb->vm );
423
424 // find task that called join.
425 mrbc_hal_disable_irq();
426 for( mrbc_tcb *t = q_waiting_; t != NULL; t = t->next ) {
427 if( t->reason == TASKREASON_JOIN && t->tcb_join == tcb ) {
429 t->state = TASKSTATE_READY;
430 t->reason = 0;
432 }
433 }
434 mrbc_hal_enable_irq();
435
436 for( mrbc_tcb *t = q_suspended_; t != NULL; t = t->next ) {
437 if( t->reason == TASKREASON_JOIN && t->tcb_join == tcb ) {
438 t->reason = 0;
439 }
440 }
441}
442
443
444//================================================================
448int mrbc_run(void)
449{
450 int ret = 0;
451 (void)ret; // avoid warning.
452
453 while( 1 ) {
454#if defined(MRBC_TASK_SCHEDULER_HOOK)
455 // Scheduler servicing point. Runs before the ready-queue read so
456 // a task woken here is picked up in this iteration.
457 if( scheduler_hook_ ) scheduler_hook_(scheduler_hook_ud_);
458#endif
459 mrbc_tcb *tcb = q_ready_;
460 if( tcb == NULL ) { // no task to run.
461#if MRBC_SCHEDULER_EXIT
462 mrbc_hal_disable_irq();
463 int flag_exit = !q_ready_ && !q_waiting_ && !q_suspended_;
464 mrbc_hal_enable_irq();
465 if( flag_exit ) return ret;
466#endif
467 mrbc_hal_idle_cpu();
468 continue;
469 }
470
471 /*
472 run the task.
473 */
474 tcb->state = TASKSTATE_RUNNING; // to execute.
475 tcb->timeslice = MRBC_TIMESLICE_TICK_COUNT;
476
477#if !defined(MRBC_NO_TIMER)
478 // Using hardware timer.
479 int ret_vm_run = mrbc_vm_run(&tcb->vm);
480 tcb->vm.flag_preemption = 0;
481#else
482 // Emulate time slice preemption.
483 int ret_vm_run = 0;
484 tcb->vm.flag_preemption = 1;
485 while( tcb->timeslice != 0 ) {
486 ret_vm_run = mrbc_vm_run( &tcb->vm );
487 tcb->timeslice--;
488 if( ret_vm_run != 0 ) break;
489 if( tcb->state != TASKSTATE_RUNNING ) break;
490 }
491 mrbc_tick();
492#endif
493
494 /*
495 did the task done?
496 */
497 if( ret_vm_run != 0 ) {
498 terminate_task( tcb );
499 if( ret_vm_run != 1 ) ret = ret_vm_run; // for debug info.
500 continue;
501 }
502
503 /*
504 Switch task.
505 */
506 if( tcb->state == TASKSTATE_RUNNING ) {
507 tcb->state = TASKSTATE_READY;
508
509 mrbc_hal_disable_irq();
510 mrbc_task_q_delete(tcb); // insert task on queue last.
512 mrbc_hal_enable_irq();
513 }
514
515 } // loop infinite.
516}
517
518
519//================================================================
523#if defined(__EMSCRIPTEN__)
524EMSCRIPTEN_KEEPALIVE
525int
526mrbc_run_step(void)
527{
528#if defined(MRBC_TASK_SCHEDULER_HOOK)
529 // Scheduler servicing point (see mrbc_run).
530 if (scheduler_hook_) scheduler_hook_(scheduler_hook_ud_);
531#endif
532
533 // Take the task that can be executed
534 mrbc_tcb *tcb = q_ready_;
535 if (tcb == NULL) {
536 // Even if there is no task to run, return 0
537 // so to wait for callbacks like event listener
538 return 0;
539 }
540
542 tcb->timeslice = MRBC_TIMESLICE_TICK_COUNT;
543
544 int ret_vm_run = mrbc_vm_run(&tcb->vm);
545 tcb->vm.flag_preemption = 0;
546
547 /*
548 did the task done?
549 */
550 if (ret_vm_run != 0) {
551 terminate_task( tcb );
552 return ret_vm_run;
553 }
554
555 // Switch task.
556 if (tcb->state == TASKSTATE_RUNNING) {
557 tcb->state = TASKSTATE_READY;
558 mrbc_hal_disable_irq();
561 mrbc_hal_enable_irq();
562 }
563
564 return 0;
565}
566#endif
567
568
569//================================================================
575void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
576{
577 mrbc_hal_disable_irq();
581 tcb->wakeup_tick = tick_ + (ms / MRBC_TICK_UNIT) + !!(ms % MRBC_TICK_UNIT);
582
583 if( (int32_t)(tcb->wakeup_tick - wakeup_tick_) < 0 ) {
585 }
586
588 mrbc_hal_enable_irq();
589
590 tcb->vm.flag_preemption = 1;
591}
592
593
594//================================================================
603uint32_t mrbc_deadline_after_ms(mrbc_int_t ms, int *p_overflow)
604{
605 int64_t ticks = (int64_t)(ms / MRBC_TICK_UNIT) + !!(ms % MRBC_TICK_UNIT);
606 if( ticks > INT32_MAX ) {
607 *p_overflow = 1;
608 return 0;
609 }
610 *p_overflow = 0;
611
612 uint32_t deadline = tick_ + (uint32_t)ticks;
613 // Never hand back the "no timeout" sentinel for a real deadline; pulling it
614 // back one tick costs at most one tick in the 1-in-2^32 collision case.
615 return deadline == MRBC_WAIT_FOREVER ? deadline - 1 : deadline;
616}
617
618
619//================================================================
625int mrbc_deadline_reached(uint32_t deadline)
626{
627 return (int32_t)(deadline - tick_) <= 0;
628}
629
630
631//================================================================
639void mrbc_register_wakeup(uint32_t wakeup_tick)
640{
641 if( (int32_t)(wakeup_tick - wakeup_tick_) < 0 ) {
642 wakeup_tick_ = wakeup_tick;
643 }
644}
645
646
647//================================================================
653{
654 switch( tcb->state ) {
656 mrbc_resume_task( tcb ); // for sleep without arguments.
657 break;
658
660 if( tcb->reason != TASKREASON_SLEEP ) break;
661
662 mrbc_hal_disable_irq();
664 tcb->state = TASKSTATE_READY;
665 tcb->reason = 0;
667
668 for( mrbc_tcb *t = q_waiting_; t != NULL; t = t->next ) {
669 uint32_t wake;
670 if( !get_timed_wakeup_tick(t, &wake) ) continue;
671 if( (int32_t)(wake - wakeup_tick_) < 0 ) {
672 wakeup_tick_ = wake;
673 }
674 }
675 mrbc_hal_enable_irq();
676 break;
677
678 default:
679 break;
680 }
681}
682
683
684//================================================================
690{
691 tcb->timeslice = 0;
692 tcb->vm.flag_preemption = 1;
693}
694
695
696//================================================================
702void mrbc_change_priority(mrbc_tcb *tcb, int priority)
703{
704 tcb->priority = priority;
705 tcb->priority_preemption = priority;
706
707 mrbc_hal_disable_irq();
708 mrbc_task_q_delete(tcb); // reorder task queue according to priority.
710
712
713 mrbc_hal_enable_irq();
714}
715
716
717//================================================================
723{
724 if( tcb->state == TASKSTATE_SUSPENDED ) return;
725
726 mrbc_hal_disable_irq();
730 mrbc_hal_enable_irq();
731
732 tcb->vm.flag_preemption = 1;
733}
734
735
736//================================================================
742{
743 if( tcb->state != TASKSTATE_SUSPENDED ) return;
744
745 int flag_to_ready_state = (tcb->reason == 0);
746
747 mrbc_hal_disable_irq();
748
749 if( flag_to_ready_state ) preempt_running_task();
750
752 tcb->state = flag_to_ready_state ? TASKSTATE_READY : TASKSTATE_WAITING;
754
755 mrbc_hal_enable_irq();
756
757 uint32_t wake;
758 if( get_timed_wakeup_tick(tcb, &wake) ) {
759 if( (int32_t)(wake - wakeup_tick_) < 0 ) {
760 wakeup_tick_ = wake;
761 }
762 }
763}
764
765
766//================================================================
775{
776 if( tcb->state == TASKSTATE_DORMANT ) return;
777
778 terminate_task( tcb );
779 tcb->vm.flag_preemption = 1;
780}
781
782
783//================================================================
789void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
790{
791 if( tcb->state == TASKSTATE_DORMANT ) return;
792 if( tcb_join->state == TASKSTATE_DORMANT ) return;
793
794 mrbc_hal_disable_irq();
796
798 tcb->reason = TASKREASON_JOIN;
799 tcb->tcb_join = tcb_join;
800
802 mrbc_hal_enable_irq();
803
804 tcb->vm.flag_preemption = 1;
805}
806
807
808
809//================================================================
815{
816 if( mutex == NULL ) {
817 mutex = mrbc_raw_alloc( sizeof(mrbc_mutex) );
818 }
819
820 static const mrbc_mutex init_val = MRBC_MUTEX_INITIALIZER;
821 *mutex = init_val;
822
823 return mutex;
824}
825
826
827//================================================================
834{
835 MRBC_MUTEX_TRACE("mutex lock / MUTEX: %p TCB: %p", mutex, tcb );
836
837 int ret = 0;
838 mrbc_hal_disable_irq();
839
840 // Try lock mutex;
841 if( mutex->lock == 0 ) { // a future does use TAS?
842 mutex->lock = 1;
843 mutex->tcb = tcb;
844 MRBC_MUTEX_TRACE(" lock OK\n" );
845 goto DONE;
846 }
847 MRBC_MUTEX_TRACE(" lock FAIL\n" );
848
849 // Can't lock mutex
850 // check recursive lock.
851 if( mutex->tcb == tcb ) {
852 ret = 1;
853 goto DONE;
854 }
855
856 // To WAITING state.
860 tcb->mutex = mutex;
862 tcb->vm.flag_preemption = 1;
863
864 DONE:
865 mrbc_hal_enable_irq();
866
867 return ret;
868}
869
870
871//================================================================
878{
879 MRBC_MUTEX_TRACE("mutex unlock / MUTEX: %p TCB: %p\n", mutex, tcb );
880
881 // check some parameters.
882 if( !mutex->lock ) return 1;
883 if( mutex->tcb != tcb ) return 2;
884
885 mrbc_hal_disable_irq();
886
887 // wakeup ONE waiting task if exist.
888 mrbc_tcb *tcb1;
889 for( tcb1 = q_waiting_; tcb1 != NULL; tcb1 = tcb1->next ) {
890 if( tcb1->reason == TASKREASON_MUTEX && tcb1->mutex == mutex ) break;
891 }
892 if( tcb1 ) {
893 MRBC_MUTEX_TRACE("SW1: TCB: %p\n", tcb1 );
894 mutex->tcb = tcb1;
895
896 mrbc_task_q_delete(tcb1);
897 tcb1->state = TASKSTATE_READY;
898 tcb1->reason = 0;
899 mrbc_task_q_insert(tcb1);
900
902 goto DONE;
903 }
904
905 // find ONE mutex locked task in suspended queue.
906 for( tcb1 = q_suspended_; tcb1 != NULL; tcb1 = tcb1->next ) {
907 if( tcb1->reason == TASKREASON_MUTEX && tcb1->mutex == mutex ) break;
908 }
909 if( tcb1 ) {
910 MRBC_MUTEX_TRACE("SW2: TCB: %p\n", tcb1 );
911 mutex->tcb = tcb1;
912 tcb1->reason = 0;
913 goto DONE;
914 }
915
916 // other case, unlock mutex
917 MRBC_MUTEX_TRACE("mutex unlock all.\n" );
918 mutex->lock = 0;
919 mutex->tcb = 0;
920
921 DONE:
922 mrbc_hal_enable_irq();
923
924 return 0;
925}
926
927
928//================================================================
935{
936 MRBC_MUTEX_TRACE("mutex try lock / MUTEX: %p TCB: %p", mutex, tcb );
937
938 int ret;
939 mrbc_hal_disable_irq();
940
941 if( mutex->lock == 0 ) {
942 mutex->lock = 1;
943 mutex->tcb = tcb;
944 ret = 0;
945 MRBC_MUTEX_TRACE(" trylock OK\n" );
946 }
947 else {
948 MRBC_MUTEX_TRACE(" trylock FAIL\n" );
949 ret = 1;
950 }
951
952 mrbc_hal_enable_irq();
953 return ret;
954}
955
956
957//================================================================
961void mrbc_cleanup(void)
962{
966
967 memset( tcb_queue_, 0, sizeof(tcb_queue_) );
968}
969
970
971//================================================================
975static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
976{
977 mrbc_tcb *tcb = mrbc_get_tcb(vm);
978
979 if( argc == 0 ) {
981 return;
982 }
983
984 switch( mrbc_type(v[1]) ) {
985 case MRBC_TT_INTEGER:
986 {
987 mrbc_int_t sec;
988 sec = mrbc_integer(v[1]);
989 SET_INT_RETURN(sec);
990 mrbc_sleep_ms(tcb, sec * 1000);
991 break;
992 }
993
994#if MRBC_USE_FLOAT
995 case MRBC_TT_FLOAT:
996 {
997 mrbc_float_t sec;
998 sec = mrbc_float(v[1]);
999 SET_INT_RETURN(sec);
1000 mrbc_sleep_ms(tcb, (mrbc_int_t)(sec * 1000));
1001 break;
1002 }
1003#endif
1004
1005 default:
1006 break;
1007 }
1008}
1009
1010
1011//================================================================
1015static void c_sleep_ms(mrbc_vm *vm, mrbc_value v[], int argc)
1016{
1017 mrbc_tcb *tcb = mrbc_get_tcb(vm);
1018
1019 mrbc_int_t msec = mrbc_integer(v[1]);
1020 SET_INT_RETURN(msec);
1021 mrbc_sleep_ms(tcb, msec);
1022}
1023
1024
1025
1026/*
1027 Task class
1028*/
1029//----------------------------------------------------------------
1031{
1032 mrbc_value ret;
1033
1034 // Only one instance is allocated.
1035 if( tcb->task_instance ) {
1036 ret = mrbc_immediate_value(MRBC_TT_OBJECT, .instance = tcb->task_instance );
1037 } else {
1038 ret = mrbc_instance_new(vm, MRBC_CLASS(Task), sizeof(mrbc_tcb *));
1039 *MRBC_INSTANCE_DATA_PTR( &ret, mrbc_tcb *) = tcb;
1040 tcb->task_instance = ret.instance;
1041 }
1042
1043 mrbc_incref(&ret);
1044 return ret;
1045}
1046
1047
1048//================================================================
1054static void c_task_get(mrbc_vm *vm, mrbc_value v[], int argc)
1055{
1056 mrbc_tcb *tcb = NULL;
1057
1058 if( mrbc_type(v[0]) != MRBC_TT_CLASS ) goto RETURN_NIL;
1059
1060 // in case of Task.get()
1061 if( argc == 0 ) {
1062 tcb = mrbc_get_tcb(vm);
1063 }
1064
1065#if MRBC_USE_STRING
1066 // in case of Task.get("TaskName")
1067 else if( mrbc_type(v[1]) == MRBC_TT_STRING ) {
1068 tcb = mrbc_find_task( mrbc_string_cstr( &v[1] ) );
1069 }
1070#endif
1071
1072 if( tcb ) {
1073 mrbc_value ret = sub_task_get(vm, tcb);
1074 SET_RETURN(ret);
1075 return; // normal return.
1076 }
1077
1078 RETURN_NIL:
1080}
1081
1082
1083//================================================================
1088static void c_task_list(mrbc_vm *vm, mrbc_value v[], int argc)
1089{
1090 mrbc_value ret = mrbc_array_new(vm, 1);
1091
1092 mrbc_hal_disable_irq();
1093
1094 for( int i = 0; i < NUM_TCB_QUEUE; i++ ) {
1095 for( mrbc_tcb *tcb = tcb_queue_[i]; tcb != NULL; tcb = tcb->next ) {
1096 mrbc_value task = sub_task_get(vm, tcb);
1097 mrbc_array_push( &ret, &task );
1098 }
1099 }
1100
1101 mrbc_hal_enable_irq();
1102
1103 SET_RETURN(ret);
1104}
1105
1106
1107#if MRBC_USE_STRING
1108//================================================================
1113static void c_task_name_list(mrbc_vm *vm, mrbc_value v[], int argc)
1114{
1115 mrbc_value ret = mrbc_array_new(vm, 1);
1116
1117 mrbc_hal_disable_irq();
1118
1119 for( int i = 0; i < NUM_TCB_QUEUE; i++ ) {
1120 for( mrbc_tcb *tcb = tcb_queue_[i]; tcb != NULL; tcb = tcb->next ) {
1121 mrbc_value s = mrbc_string_new_cstr(vm, tcb->name);
1122 mrbc_array_push( &ret, &s );
1123 }
1124 }
1125
1126 mrbc_hal_enable_irq();
1127
1128 SET_RETURN(ret);
1129}
1130
1131
1132//================================================================
1138static void c_task_set_name(mrbc_vm *vm, mrbc_value v[], int argc)
1139{
1140 mrbc_tcb *tcb;
1141
1142 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1143 DEPRECATED("Task.name=");
1144 tcb = mrbc_get_tcb(vm);
1145 } else {
1146 tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1147 }
1148
1149 if( mrbc_type(v[1]) != MRBC_TT_STRING ) {
1150 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1151 return;
1152 }
1153
1154 mrbc_set_task_name( tcb, mrbc_string_cstr(&v[1]) );
1155
1156 mrbc_incref( &v[1] );
1157 SET_RETURN( v[1] );
1158}
1159
1160
1161//================================================================
1167static void c_task_name(mrbc_vm *vm, mrbc_value v[], int argc)
1168{
1169 mrbc_value ret;
1170
1171 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1172 DEPRECATED("Task.name");
1173 ret = mrbc_string_new_cstr( vm, mrbc_get_tcb(vm)->name );
1174 } else {
1175 mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1176 ret = mrbc_string_new_cstr(vm, tcb->name );
1177 }
1178
1179 SET_RETURN(ret);
1180}
1181#endif
1182
1183
1184//================================================================
1190static void c_task_set_priority(mrbc_vm *vm, mrbc_value v[], int argc)
1191{
1192 mrbc_tcb *tcb;
1193
1194 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1195 DEPRECATED("Task.priority=");
1196 tcb = mrbc_get_tcb(vm);
1197 } else {
1198 tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1199 }
1200
1201 if( mrbc_type(v[1]) != MRBC_TT_INTEGER ) {
1202 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1203 return;
1204 }
1205 int n = mrbc_integer( v[1] );
1206 if( n < 0 || n > 255 ) {
1207 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1208 return;
1209 }
1210
1211 mrbc_change_priority( tcb, n );
1212
1213 SET_RETURN( v[1] );
1214}
1215
1216
1217//================================================================
1222static void c_task_priority(mrbc_vm *vm, mrbc_value v[], int argc)
1223{
1224 mrbc_tcb *tcb;
1225
1226 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1227 DEPRECATED("Task.priority");
1228 tcb = mrbc_get_tcb(vm);
1229 } else {
1230 tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1231 }
1232
1233 SET_INT_RETURN( tcb->priority );
1234}
1235
1236
1237//================================================================
1242#if MRBC_USE_STRING
1243static void c_task_status(mrbc_vm *vm, mrbc_value v[], int argc)
1244{
1245 static const char *status_name[] =
1246 { "DORMANT", "READY", "WAITING ", "", "SUSPENDED" };
1247 static const char *reason_name[] =
1248 { "", "SLEEP", "MUTEX", "", "JOIN" };
1249
1250 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1251
1252 const mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1253 mrbc_value ret = mrbc_string_new_cstr( vm, status_name[tcb->state / 2] );
1254
1255 if( tcb->state == TASKSTATE_WAITING ) {
1256 mrbc_string_append_cstr( &ret, reason_name[tcb->reason] );
1257 }
1258
1259 SET_RETURN(ret);
1260}
1261#endif
1262
1263
1264//================================================================
1270static void c_task_suspend(mrbc_vm *vm, mrbc_value v[], int argc)
1271{
1272 mrbc_tcb *tcb;
1273
1274 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1275 tcb = mrbc_get_tcb(vm);
1276 } else {
1277 tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1278 }
1279
1280 mrbc_suspend_task(tcb);
1281}
1282
1283
1284//================================================================
1289static void c_task_resume(mrbc_vm *vm, mrbc_value v[], int argc)
1290{
1291 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1292
1293 mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1294
1295 mrbc_resume_task(tcb);
1296}
1297
1298
1299//================================================================
1304static void c_task_terminate(mrbc_vm *vm, mrbc_value v[], int argc)
1305{
1306 mrbc_tcb *tcb;
1307
1308 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1309 tcb = mrbc_get_tcb(vm);
1310 } else {
1311 tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1312 }
1313
1315}
1316
1317
1318//================================================================
1324static void c_task_raise(mrbc_vm *vm, mrbc_value v[], int argc)
1325{
1326 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1327 mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1328
1329 mrbc_vm *vm1 = &tcb->vm;
1330 mrbc_value exc;
1331
1332 if( argc == 0 ) {
1333 exc = mrbc_exception_new( vm1, MRBC_CLASS(RuntimeError), 0, 0 );
1334 } else if( mrbc_type(v[1]) == MRBC_TT_EXCEPTION ) {
1335 exc = v[1];
1336 mrbc_incref(&exc);
1337 } else {
1338 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1339 return;
1340 }
1341
1342 mrbc_decref(&vm1->exception);
1343 vm1->exception = exc;
1344 vm1->flag_preemption = 2;
1345
1346 if( tcb->state == TASKSTATE_WAITING && tcb->reason == TASKREASON_SLEEP ) {
1347 void mrbc_wakeup_task(mrbc_tcb *tcb);
1348 mrbc_wakeup_task( tcb );
1349 }
1350}
1351
1352
1353//================================================================
1358static void c_task_join(mrbc_vm *vm, mrbc_value v[], int argc)
1359{
1360 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1361
1362 mrbc_tcb *tcb_me = mrbc_get_tcb(vm);
1363 mrbc_tcb *tcb_join = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1364
1365 mrbc_join_task(tcb_me, tcb_join);
1366}
1367
1368
1369//================================================================
1374static void c_task_value(mrbc_vm *vm, mrbc_value v[], int argc)
1375{
1376 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1377
1378 mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1379
1380 if( tcb->state != TASKSTATE_DORMANT ) {
1381 mrbc_raise(vm, 0, "task must be end");
1382 return;
1383 }
1384
1385 mrbc_incref( &tcb->vm.regs[0] );
1386 SET_RETURN( tcb->vm.regs[0] );
1387}
1388
1389
1390//================================================================
1395static void c_task_pass(mrbc_vm *vm, mrbc_value v[], int argc)
1396{
1397 if( mrbc_type(v[0]) != MRBC_TT_CLASS ) return;
1398
1399 mrbc_tcb *tcb = mrbc_get_tcb(vm);
1400 mrbc_relinquish(tcb);
1401}
1402
1403
1404//================================================================
1409#if MRBC_USE_STRING
1410static void c_task_create(mrbc_vm *vm, mrbc_value v[], int argc)
1411{
1412 const char *byte_code;
1413 int regs_size = MAX_REGS_SIZE;
1414
1415 // check argument.
1416 if( mrbc_type(v[0]) != MRBC_TT_CLASS ) goto ERROR_ARGUMENT;
1417
1418 if( argc >= 1 && mrbc_type(v[1]) != MRBC_TT_STRING ) goto ERROR_ARGUMENT;
1419 mrbc_incref( &v[1] );
1420 byte_code = mrbc_string_cstr(&v[1]);
1421
1422 if( argc >= 2 ) {
1423 if( mrbc_type(v[2]) != MRBC_TT_INTEGER ) goto ERROR_ARGUMENT;
1424 regs_size = mrbc_integer(v[2]);
1425 }
1426
1427 // create TCB
1429 tcb->vm.flag_permanence = 1;
1430
1431 if( !mrbc_create_task( byte_code, tcb ) ) return;
1432
1433 // create Instance
1434 mrbc_value ret = mrbc_instance_new(vm, v[0].cls, sizeof(mrbc_tcb *));
1435 *MRBC_INSTANCE_DATA_PTR( &ret, mrbc_tcb *) = tcb;
1436 SET_RETURN( ret );
1437 return;
1438
1439 ERROR_ARGUMENT:
1440 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1441}
1442#endif
1443
1444
1445//================================================================
1450static void c_task_run(mrbc_vm *vm, mrbc_value v[], int argc)
1451{
1452 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1453
1454 mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1455 if( tcb->state != TASKSTATE_DORMANT ) return;
1456
1457 mrbc_start_task(tcb);
1458}
1459
1460
1461//================================================================
1466static void c_task_rewind(mrbc_vm *vm, mrbc_value v[], int argc)
1467{
1468 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) return;
1469
1470 mrbc_tcb *tcb = *MRBC_INSTANCE_DATA_PTR(&v[0], mrbc_tcb *);
1471 if( tcb->state != TASKSTATE_DORMANT ) return;
1472
1473 mrbc_vm_begin( &tcb->vm );
1474}
1475
1476
1477/* MRBC_AUTOGEN_METHOD_TABLE
1478
1479 CLASS("Task")
1480 FILE("_autogen_class_rrt0.h")
1481
1482 METHOD( "get", c_task_get )
1483 METHOD( "current", c_task_get )
1484 METHOD( "list", c_task_list )
1485#if MRBC_USE_STRING
1486 METHOD( "name_list", c_task_name_list )
1487 METHOD( "name=", c_task_set_name )
1488 METHOD( "name", c_task_name )
1489#endif
1490 METHOD( "priority=", c_task_set_priority )
1491 METHOD( "priority", c_task_priority )
1492#if MRBC_USE_STRING
1493 METHOD( "status", c_task_status )
1494#endif
1495
1496 METHOD( "suspend", c_task_suspend )
1497 METHOD( "resume", c_task_resume )
1498 METHOD( "terminate", c_task_terminate )
1499 METHOD( "raise", c_task_raise )
1500
1501 METHOD( "join", c_task_join )
1502 METHOD( "value", c_task_value )
1503 METHOD( "pass", c_task_pass )
1504
1505#if MRBC_USE_STRING
1506 METHOD( "create", c_task_create )
1507#endif
1508 METHOD( "run", c_task_run )
1509 METHOD( "rewind", c_task_rewind )
1510*/
1511
1512
1513/*
1514 Mutex class
1515*/
1516//================================================================
1520static void c_mutex_new(mrbc_vm *vm, mrbc_value v[], int argc)
1521{
1522 v[0] = mrbc_instance_new(vm, v[0].cls, sizeof(mrbc_mutex));
1523
1525
1526 mrbc_mutex_init( mutex );
1527}
1528
1529
1530//================================================================
1534static void c_mutex_lock(mrbc_vm *vm, mrbc_value v[], int argc)
1535{
1537 int res = mrbc_mutex_lock(mutex, mrbc_get_tcb(vm));
1538 if( res == 0 ) return; // return self
1539
1540 // raise ThreadError
1541 assert(!"Mutex recursive lock.");
1542}
1543
1544
1545//================================================================
1549static void c_mutex_unlock(mrbc_vm *vm, mrbc_value v[], int argc)
1550{
1552 int res = mrbc_mutex_unlock( mutex, mrbc_get_tcb(vm));
1553 if( res == 0 ) return; // return self
1554
1555 // raise ThreadError
1556 assert(!"Mutex unlock error. not owner or not locked.");
1557}
1558
1559
1560//================================================================
1564static void c_mutex_trylock(mrbc_vm *vm, mrbc_value v[], int argc)
1565{
1567 int res = mrbc_mutex_trylock( mutex, mrbc_get_tcb(vm));
1568 SET_BOOL_RETURN( res == 0 );
1569}
1570
1571
1572//================================================================
1576static void c_mutex_locked(mrbc_vm *vm, mrbc_value v[], int argc)
1577{
1579 SET_BOOL_RETURN( mutex->lock != 0 );
1580}
1581
1582
1583//================================================================
1587static void c_mutex_owned(mrbc_vm *vm, mrbc_value v[], int argc)
1588{
1590 SET_BOOL_RETURN( mutex->lock != 0 && mutex->tcb == mrbc_get_tcb(vm) );
1591}
1592
1593
1594/* MRBC_AUTOGEN_METHOD_TABLE
1595
1596 CLASS("Mutex")
1597 APPEND("_autogen_class_rrt0.h")
1598
1599 METHOD( "new", c_mutex_new )
1600 METHOD( "lock", c_mutex_lock )
1601 METHOD( "unlock", c_mutex_unlock )
1602 METHOD( "try_lock", c_mutex_trylock )
1603 METHOD( "locked?", c_mutex_locked )
1604 METHOD( "owned?", c_mutex_owned )
1605*/
1606
1607
1608
1609//================================================================
1612static void c_vm_tick(mrbc_vm *vm, mrbc_value v[], int argc)
1613{
1615}
1616
1617/* MRBC_AUTOGEN_METHOD_TABLE
1618
1619 CLASS("VM")
1620 APPEND("_autogen_class_rrt0.h")
1621
1622 METHOD( "tick", c_vm_tick )
1623*/
1624#include "_autogen_class_rrt0.h"
1625
1626
1627
1628//================================================================
1634void mrbc_init(void *heap_ptr, unsigned int size)
1635{
1636 static uint8_t flag_hal_init_called = 0;
1637
1638 if( !flag_hal_init_called ) {
1639 mrbc_hal_init();
1640 flag_hal_init_called = 1;
1641 }
1642
1643 mrbc_init_alloc(heap_ptr, size);
1646
1647 // Initialize included classes
1648 static mrbc_class * const rrt0_cls[] = {
1649 MRBC_CLASS(Task), MRBC_CLASS(Mutex), MRBC_CLASS(VM)
1650 };
1652
1653 for( int i = 0; i < sizeof(rrt0_cls)/sizeof(rrt0_cls[0]); i++ ) {
1654 mrbc_class *cls = rrt0_cls[i];
1655
1656 cls->super = MRBC_CLASS(Object);
1657 cls->method_link = 0;
1658 vcls.cls = cls;
1659
1660 mrbc_set_const( vcls.cls->sym_id, &vcls );
1661 }
1662
1663 mrbc_define_method(0, 0, "sleep", c_sleep);
1664 mrbc_define_method(0, 0, "sleep_ms", c_sleep_ms);
1665
1667
1669}
1670
1671
1672
1673#ifdef MRBC_DEBUG
1674//================================================================
1681void pq(const mrbc_tcb *p_tcb)
1682{
1683 if( p_tcb == NULL ) return;
1684
1685 // vm_id, TCB, name
1686 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1687 mrbc_printf("%d:%08x %-8.8s ", t->vm.vm_id, MRBC_PTR_TO_UINT32(t),
1688 t->name[0] ? t->name : "(noname)" );
1689 }
1690 mrbc_printf("\n");
1691
1692#if 0
1693 // next ptr
1694 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1695 mrbc_printf(" next:%04x ", (uint16_t)MRBC_PTR_TO_UINT32(t->next));
1696 }
1697 mrbc_printf("\n");
1698#endif
1699
1700 // task priority, state.
1701 // st:SsRr
1702 // ^ suspended -> S:suspended
1703 // ^ waiting -> s:sleep m:mutex j:join q:queue
1704 // ^ ready -> R:ready
1705 // ^ running-> r:running
1706 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1707 mrbc_printf(" pri:%3d", t->priority_preemption);
1708#if 1
1709 mrbc_tcb t1 = *t; // Copy the value at this timing.
1710 mrbc_printf(" st:%c%c%c%c ",
1711 (t1.state & TASKSTATE_SUSPENDED)?'S':'-',
1712 (t1.state & TASKSTATE_SUSPENDED)? ("-SM!J!!!Q"[t1.reason]) :
1713 (t1.state & TASKSTATE_WAITING)? ("!sm!j!!!q"[t1.reason]) : '-',
1714 (t1.state & 0x02)?'R':'-',
1715 (t1.state & 0x01)?'r':'-' );
1716#else
1717 mrbc_printf(" s%04b r%04b ", t->state, t->reason);
1718#endif
1719 }
1720 mrbc_printf("\n");
1721
1722 // timeslice, vm->flag_preemption, wakeup tick
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);
1725 if( t->reason & TASKREASON_SLEEP ) {
1726 mrbc_printf("w:%-6d", t->wakeup_tick );
1727 } else {
1728 mrbc_printf("w:-- ");
1729 }
1730 }
1731 mrbc_printf("\n");
1732
1733 // join task
1734 for( const mrbc_tcb *t = p_tcb; t; t = t->next ) {
1735 if( t->reason & TASKREASON_JOIN ) {
1736 mrbc_printf(" join:%p ", t->tcb_join);
1737 } else {
1738 mrbc_printf(" ");
1739 }
1740 }
1741 mrbc_printf("\n");
1742
1743}
1744
1745void pqall(void)
1746{
1747 mrbc_hal_disable_irq();
1748 mrbc_printf("<< tick_ = %d, wakeup_tick_ = %d >>\n", tick_, wakeup_tick_);
1749 mrbc_printf("<<<<< DORMANT >>>>>\n"); pq(q_dormant_);
1750 mrbc_printf("<<<<< READY >>>>>\n"); pq(q_ready_);
1751 mrbc_printf("<<<<< WAITING >>>>>\n"); pq(q_waiting_);
1752 mrbc_printf("<<<<< SUSPENDED >>>>>\n"); pq(q_suspended_);
1753 mrbc_hal_enable_irq();
1754}
1755#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:75
#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:60
#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
void mrbc_init_task_queue(void)
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:281
void mrbc_init_class_c(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:249
void mrbc_init_class_mrblib(void)
Definition class.c:657
#define MRBC_CLASS(cls)
Definition class.h:55
#define MRBC_INSTANCE_DATA_PTR(v, t)
Definition class.h:79
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:205
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:306
Include at once the necessary header files.
void mrbc_join_task(mrbc_tcb *tcb, const mrbc_tcb *tcb_join)
Definition rrt0.c:789
static volatile uint32_t wakeup_tick_
Definition rrt0.c:55
void mrbc_set_task_name(mrbc_tcb *tcb, const char *name)
Definition rrt0.c:352
#define q_ready_
Definition rrt0.c:51
void mrbc_task_q_insert(mrbc_tcb *p_tcb)
Definition rrt0.c:94
void mrbc_init(void *heap_ptr, unsigned int size)
Definition rrt0.c:1634
void mrbc_terminate_task(mrbc_tcb *tcb)
Definition rrt0.c:774
mrbc_tcb * mrbc_task_q_waiting_head(void)
Definition rrt0.c:163
static mrbc_tcb * tcb_queue_[NUM_TCB_QUEUE]
Definition rrt0.c:49
void mrbc_resume_task(mrbc_tcb *tcb)
Definition rrt0.c:741
int mrbc_mutex_unlock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:877
#define q_dormant_
Definition rrt0.c:50
static void terminate_task(mrbc_tcb *tcb)
Definition rrt0.c:414
void mrbc_cleanup(void)
Definition rrt0.c:961
mrbc_tcb * mrbc_tcb_new(int regs_size, enum MrbcTaskState task_state, int priority)
Definition rrt0.c:273
mrbc_tcb * mrbc_find_task(const char *name)
Definition rrt0.c:370
mrbc_tcb * mrbc_create_task(const void *byte_code, mrbc_tcb *tcb)
Definition rrt0.c:298
void mrbc_tick(void)
Definition rrt0.c:213
mrbc_mutex * mrbc_mutex_init(mrbc_mutex *mutex)
Definition rrt0.c:814
void mrbc_change_priority(mrbc_tcb *tcb, int priority)
Definition rrt0.c:702
uint32_t mrbc_deadline_after_ms(mrbc_int_t ms, int *p_overflow)
Definition rrt0.c:603
void mrbc_sleep_ms(mrbc_tcb *tcb, uint32_t ms)
Definition rrt0.c:575
int mrbc_mutex_trylock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:934
int mrbc_deadline_reached(uint32_t deadline)
Definition rrt0.c:625
static mrbc_value sub_task_get(mrbc_vm *vm, mrbc_tcb *tcb)
Definition rrt0.c:1030
int mrbc_mutex_lock(mrbc_mutex *mutex, mrbc_tcb *tcb)
Definition rrt0.c:833
static volatile uint32_t tick_
Definition rrt0.c:54
void mrbc_register_wakeup(uint32_t wakeup_tick)
Definition rrt0.c:639
#define q_suspended_
Definition rrt0.c:53
#define MRBC_MUTEX_TRACE(...)
Definition rrt0.c:32
void mrbc_suspend_task(mrbc_tcb *tcb)
Definition rrt0.c:722
void mrbc_wakeup_task(mrbc_tcb *tcb)
Definition rrt0.c:652
static int get_timed_wakeup_tick(const mrbc_tcb *t, uint32_t *out)
Definition rrt0.c:191
void mrbc_relinquish(mrbc_tcb *tcb)
Definition rrt0.c:689
static void preempt_running_task(void)
Definition rrt0.c:172
#define DEPRECATED(msg)
Definition rrt0.c:37
#define q_waiting_
Definition rrt0.c:52
int mrbc_start_task(mrbc_tcb *tcb)
Definition rrt0.c:393
static void c_sleep(mrbc_vm *vm, mrbc_value v[], int argc)
Definition rrt0.c:975
int mrbc_run(void)
Definition rrt0.c:448
void mrbc_task_q_delete(mrbc_tcb *p_tcb)
Definition rrt0.c:128
#define NUM_TCB_QUEUE
Definition rrt0.c:48
int mrbc_delete_task(mrbc_tcb *tcb)
Definition rrt0.c:332
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:61
struct RMutex mrbc_mutex
Mutex.
static mrbc_tcb * mrbc_get_tcb(const mrbc_vm *vm)
Definition rrt0.h:179
@ TASKREASON_JOIN
Definition rrt0.h:56
@ TASKREASON_MUTEX
Definition rrt0.h:55
@ TASKREASON_QUEUE
Definition rrt0.h:57
@ TASKREASON_SLEEP
Definition rrt0.h:54
#define MRBC_WAIT_FOREVER
Definition rrt0.h:66
#define MRBC_TASK_NAME_LEN
Definition rrt0.h:69
#define MRBC_MUTEX_INITIALIZER
Definition rrt0.h:119
static const int MRBC_TASK_DEFAULT_PRIORITY
Definition rrt0.h:60
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
volatile int lock
Definition rrt0.h:115
struct RTcb * tcb
Definition rrt0.h:116
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:87
struct VM vm
Definition rrt0.h:105
char name[MRBC_TASK_NAME_LEN+1]
task name (optional)
Definition rrt0.h:92
const struct RTcb * tcb_join
joined task.
Definition rrt0.h:102
uint8_t priority_preemption
task priority. effective value.
Definition rrt0.h:88
uint8_t state
task state. defined in MrbcTaskState.
Definition rrt0.h:90
struct RMutex * mutex
Definition rrt0.h:96
mrbc_instance * task_instance
Task instance or NULL.
Definition rrt0.h:103
volatile uint8_t timeslice
time slice counter.
Definition rrt0.h:89
uint8_t reason
sub state. defined in MrbcTaskReason.
Definition rrt0.h:91
uint32_t wakeup_tick
wakeup time for sleep state.
Definition rrt0.h:95
struct RTcb::@363107132000246361337323266072372261072345062300::@123367244141214366021077021374060365005063270262 queue
queue wait state (TASKREASON_QUEUE).
struct RTcb * next
daisy chain in task queue.
Definition rrt0.h:86
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:205
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:572
#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:513
#define SET_NIL_RETURN()
Definition value.h:226
static void mrbc_incref(mrbc_value *v)
Definition value.h:557
@ 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_OBJECT
General instance.
Definition value.h:95
@ 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:402
mrbc_vm * mrbc_vm_open(mrbc_vm *vm)
Definition vm.c:309
int mrbc_vm_run(mrbc_vm *vm)
Definition vm.c:3160
void mrbc_vm_end(mrbc_vm *vm)
Definition vm.c:366
void mrbc_cleanup_vm(void)
Definition vm.c:201
void mrbc_vm_begin(mrbc_vm *vm)
Definition vm.c:340
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.
#define MAX_REGS_SIZE
Definition vm_config.h:25