add pragma to suppress -Wdangling-pointer warning for intentional
stack variable address storage in exception handling. the pointer
is safely managed and cleared before function returns.
Co-authored-by: Claude <noreply@anthropic.com>
remove MRB_TASK_CREATED and MRB_TASK_STOPPED from mrb_fiber_state enum
and define them as aliases to MRB_FIBER_CREATED and MRB_FIBER_TERMINATED.
this makes the relationship between tasks and fibers clearer and avoids
artificially extending the enum with semantically equivalent values.
Co-authored-by: Claude <noreply@anthropic.com>
remove MRB_USE_TASK_SCHEDULER ifdef guards from task.h and task.c
since the macro is always defined when compiling this gem
Co-authored-by: Claude <noreply@anthropic.com>
- remove redundant MRB_TASK_CREATED/STOPPED macros from task.h since
they are now properly defined in mrb_fiber_state enum in mruby.h
- declare kw_names array separately to avoid taking address of
temporary array in c++ compilation
Co-authored-by: Claude <noreply@anthropic.com>
clarify that task.new name parameter must be string, document
task#name returns "(noname)" for unnamed tasks, and provide full
structure of task.stat return value.
Co-authored-by: Claude <noreply@anthropic.com>
add tests for sleep/usleep validation, task creation, status/inspect
methods, control methods, task.stat, priority handling, and name
handling.
Co-authored-by: Claude <noreply@anthropic.com>
fix uninitialized kwargs array causing crashes, add type validation for
name (must be String) and priority (must be Integer) parameters, return
"(noname)" for unnamed tasks.
Co-authored-by: Claude <noreply@anthropic.com>
replaced stub with full implementation that returns a hash containing
scheduler statistics:
- tick: current tick counter
- wakeup_tick: next scheduled wakeup time
- dormant/ready/waiting/suspended: per-queue statistics
each queue stat includes:
- count: number of tasks in queue
- tasks: array of task objects in that queue
implements helper function mrb_stat_sub() to walk queues and collect
task information. uses irq disable/enable to ensure consistent snapshot.
returns hash directly as requested, not wrapped in stat object.
Co-authored-by: Claude <noreply@anthropic.com>
added inspect method that returns formatted string showing:
- task pointer address
- task name (string/symbol), or "(unnamed)" for nil/other types
- task status (RUNNING, READY, WAITING, SUSPENDED, DORMANT, UNKNOWN)
format matches original implementation: #<Task:0x12345678 name:STATUS>
avoids mrb_funcall during inspection to prevent vm state issues.
handles string and symbol names directly, treats other types as unnamed.
Co-authored-by: Claude <noreply@anthropic.com>
replaced stub implementation with proper status reporting that returns
symbols representing task state:
- :RUNNING for executing tasks
- :READY for tasks ready to execute
- :WAITING for tasks waiting (sleeping, blocked, etc.)
- :SUSPENDED for manually suspended tasks
- :DORMANT for terminated tasks
- :UNKNOWN for invalid states
implementation matches original mruby-task design using ternary operators
and MRB_SYM() macros for efficient symbol lookup.
Co-authored-by: Claude <noreply@anthropic.com>
improved sleep_us_impl() in several ways:
1. dynamic sleep intervals: now sleeps for actual remaining time instead
of fixed 1ms polling, reducing unnecessary wakeups and improving
efficiency for longer sleeps
2. error handling: added checks for clock_gettime() failures with fallback
to usleep(), and input validation to handle negative values
3. overflow prevention: use named constant USEC_PER_MSEC instead of
literal 1000 for microsecond-to-nanosecond conversion, and validate
input before conversion
4. wraparound handling: fixed tick comparison at line 580 to use signed
arithmetic like other tick comparisons in the codebase
5. code clarity: added time conversion constants (NSEC_PER_MSEC,
NSEC_PER_SEC, USEC_PER_MSEC) to replace magic numbers
all tests pass.
Co-authored-by: Claude <noreply@anthropic.com>
when sleep is called from root context (not within a task), it was
instantly advancing the simulated tick counter instead of actually
delaying. this caused task_pass.rb example to run tasks 0-5 instantly
without proper delays between iterations.
fixed by using clock_gettime() to track elapsed real time and sleeping
in 1ms intervals. also clear switching_ flag when returning from root
context sleep to prevent unwanted context switches.
removed find_earliest_wakeup_tick() function and time-advancing logic
from task_run_one_iteration() as real delays are now handled by sleep
itself.
Co-authored-by: Claude <noreply@anthropic.com>
Renamed constants to use more descriptive underscores:
- MRB_TASKSTATUS_* -> MRB_TASK_STATUS_*
- MRB_TASKREASON_* -> MRB_TASK_REASON_*
This improves code readability by making the constant names clearer.
Co-authored-by: Claude <noreply@anthropic.com>
Eliminated approximately 160 lines of duplicated code (~10% of file) by
extracting common patterns into reusable helpers. This improves
maintainability by consolidating task execution logic, validation
patterns, and state transitions into single locations.
Co-authored-by: Claude <noreply@anthropic.com>
Implement main task wrapper following Fiber's pattern, where root context
is represented by a special task object. This matches PicoRuby behavior
where Task.current always returns a task object, even from root context.
The main task is lazy-allocated on first Task.current call from root,
stored in mrb->task.main_task, and has name "main", status RUNNING,
priority 0. It wraps the root context without allocating a separate
execution context.
Co-authored-by: Claude <noreply@anthropic.com>
Enable Task.pass to work from root context by implementing mini-scheduler
iteration. When called from root context, Task.pass now runs one task
iteration, allowing cooperative multitasking without Task.run. This matches
PicoRuby behavior.
Co-authored-by: Claude <noreply@anthropic.com>
Fix task termination crash caused by fiber_terminate freeing task
context resources. When a task completes, the VM would call
fiber_terminate which frees cibase/stbase, then next resume attempt
crashes dereferencing NULL pointers.
Solution unifies task and fiber lifecycle management:
- Set vmexec flag before calling mrb_vm_exec to prevent fiber_terminate
from being called during normal task completion
- Save proc/pc to local variables to avoid CI_PROC_SET macro corruption
- Add termination check in mrb_task_free to prevent double-free
Tasks now follow the same execution pattern as Fiber, leveraging
VM's built-in context management.
Co-authored-by: Claude <noreply@anthropic.com>
Replace manual mrb_immediate_p check with mrb_gc_mark_value macro
which already includes the immediate check internally.
Co-authored-by: Claude <noreply@anthropic.com>
Implements dual-mechanism GC protection and optimizes task lookup
using pointer arithmetic based on PicoRuby reference implementation.
GC Protection:
- Add mrb_gc_register/unregister to protect Task objects
- Implement mrb_task_mark_all() to mark task contexts during GC
- Store proc reference in mrb_task to prevent premature collection
- Integrate marking into gc.c root_scan_phase
Performance Optimizations:
- Add MRB2TASK macro for O(1) context-to-task conversion
- Optimize Task.current: O(n) queue search -> O(1) pointer arithmetic
- Optimize Task.pass: simplify to root context check
- Optimize Task.join: use MRB2TASK for current task lookup
Bug Fixes:
- Fix MRB_TASK_CREATED/STOPPED to use MRB_FIBER_TERMINATED
- Add safety check to prevent execution of terminated tasks
- Initialize callinfo PC to bytecode start in task_init_context
Co-authored-by: Claude <noreply@anthropic.com>
dynamically enable/disable timer interrupts based on scheduler state.
timer disabled when only one runnable task exists.
timer enabled when multiple tasks need preemption or sleeping tasks need wakeup.
use counter arrays to track ready/waiting tasks per vm.
separate platform-specific timer control from generic decision logic.
update counters at all task state transitions.
eliminates 250 interrupts/second in single-task workloads.
improves cpu efficiency and power consumption.
simplifies porting to new platforms.
Co-authored-by: Claude <noreply@anthropic.com>
unified declaration and initialization of cmath variable.
used mrb_define_module_id for module definition.
optimized all 18 function definitions with symbol id api.
Co-authored-by: Claude <noreply@anthropic.com>
change sleep, usleep, sleep_ms from private methods to module functions
to match cruby behavior where sleep can be called as both bare sleep and
kernel.sleep.
Co-authored-by: Claude <noreply@anthropic.com>
replace global_mrb with vm_list to support up to 8 concurrent mrb_state
instances. sigalrm handler now ticks all registered VMs. first VM
initializes timer, last VM stops timer. proper cleanup in hal_final.
Co-authored-by: Claude <noreply@anthropic.com>
Since full-core.gembox includes mruby-task (which defines
MRB_USE_TASK_SCHEDULER), mruby-sleep's implementation becomes disabled
via conditional compilation. Exclude mruby-sleep from full-core.gembox
to avoid loading an effectively empty gem. mruby-task provides
task-aware sleep/usleep implementations instead.
Co-authored-by: Claude <noreply@anthropic.com>
Rename sleep_ms_impl to sleep_us_impl as the base implementation,
providing true microsecond precision for usleep. sleep_ms_impl now
simply calls sleep_us_impl with converted values.
This ensures usleep provides proper microsecond granularity instead of
losing precision by converting to milliseconds.
Co-authored-by: Claude <noreply@anthropic.com>
Add usleep method that provides task-aware sleep behavior with
microsecond precision. This overrides mruby-sleep's usleep when both
gems are loaded.
The implementation converts microseconds to milliseconds and uses the
same sleep_ms_impl as sleep_ms, providing cooperative sleep within
tasks and signal-safe blocking sleep otherwise.
Co-authored-by: Claude <noreply@anthropic.com>
The sleep implementation now properly handles signal interruptions from
the sigalrm timer by using nanosleep with retry loop instead of usleep.
This commit also makes sleep override mruby-sleep's implementation when
both gems are loaded, providing task-aware sleep behavior.
Changes:
- replace usleep with nanosleep for signal-safe blocking sleep
- add retry loop to handle eintr interruptions
- use mrb_define_private_method_id for both sleep and sleep_ms
- add time.h and presym.h headers
Co-authored-by: Claude <noreply@anthropic.com>
This commit fixes several critical issues in the task scheduler:
1. Context switching now properly saves and restores ci/cci pointers
and sets prev links, following the fiber implementation pattern.
This prevents crashes when tasks complete.
2. Sleep implementation now falls back to blocking sleep (usleep/Sleep)
when not in task context, fixing standalone sleep calls.
3. Removed unused functions q_find_task and task_free to eliminate
compiler warnings.
4. Added platform-specific headers for sleep functions on Unix/Windows.
5. Enabled HAL initialization which was previously commented out.
6. Added SA_RESTART flag to SIGALRM handler to prevent timer from
interrupting IO syscalls, fixing mrbtest IO.popen failures.
Co-authored-by: Claude <noreply@anthropic.com>
this patch fixes several critical issues in the task scheduler:
1. vm integration for computed goto dispatch mode:
- added task switching check in NEXT macro for computed goto
- previous implementation only worked with switch dispatch mode
- now Task.pass properly yields control to other tasks
2. task lifecycle tracking:
- added 'started' flag to mrb_task structure
- fixed first-run detection to avoid popping callinfo multiple times
- vm overwrites context status during execution, making it unreliable
3. removed mrblib/task.rb:
- empty Ruby method stubs were overriding C implementations
- all task methods now properly implemented in C
4. cleaned up task scheduler loop:
- proper task completion detection using switching flag
- round-robin scheduling for tasks at same priority
- clean scheduler exit when all tasks complete
tasks now cooperatively yield with Task.pass and complete cleanly.
Co-authored-by: Claude <noreply@anthropic.com>
add hardware abstraction layer with posix implementation:
- setitimer: generates periodic sigalrm for tick-based scheduling
- signal handler: calls mrb_tick on each timer interrupt
- sigprocmask: enables/disables interrupts by blocking sigalrm
- usleep: idle cpu implementation for posix platforms
the hal is initialized during gem init and starts the periodic
timer automatically. non-posix platforms get stub implementations.
tick period is configurable via MRB_TICK_UNIT (default 4ms).
Co-authored-by: Claude <noreply@anthropic.com>
implement task class methods:
- Task.new: creates task with block, optional name and priority
- Task.current: returns currently running task
- Task.list: returns array of all tasks in all queues
- Task.pass: yields to other tasks voluntarily
- Task.get: finds task by name
implement task instance methods:
- status: returns task status as symbol (:DORMANT, :READY, etc)
- name/name=: get/set task name
- priority/priority=: get/set priority with queue re-sorting
- suspend/resume: manual task suspension and resumption
- terminate: forcibly terminate task and wake joiners
- join: wait for task completion
the api provides full control over task lifecycle and scheduling
from ruby code while maintaining thread safety through irq protection.
Co-authored-by: Claude <noreply@anthropic.com>
modify END_DISPATCH macro to check for context switches after each
bytecode instruction. when switching flag is set or task has stopped,
return from mrb_vm_exec to yield control back to scheduler.
add TASK_STOP macro to mark task completion in OP_STOP instruction.
this allows scheduler to detect when tasks finish execution.
the integration enables cooperative preemption at bytecode granularity
while maintaining compatibility with non-task builds.
Co-authored-by: Claude <noreply@anthropic.com>
implement core scheduling components:
- mrb_tick: tick handler for timeslice countdown and sleep wakeup
- mrb_tasks_run: main scheduler loop with context switching
- sleep operations: sleep_ms_impl, sleep, sleep_ms
- hal stub implementations for compilation (temporary)
the scheduler uses tick-based preemption with round-robin at same
priority. sleeping tasks wake when their tick count expires.
completed tasks move to dormant queue and wake any waiting joiners.
Co-authored-by: Claude <noreply@anthropic.com>
add priority queue operations:
- q_get_queue: select queue based on task status
- q_insert_task: priority-based insertion (lower number = higher priority)
- q_delete_task: remove task from queue
- q_find_task: search for task in all queues
add task lifecycle functions:
- task_alloc: allocate and zero-initialize task structure
- task_free: free task and associated context (stack + callinfo)
- task_init_context: initialize execution context similar to fiber
* allocate vm stack with dynamic sizing based on irep->nregs
* allocate callinfo stack
* setup callinfo with proc and target class
* set context status to MRB_TASK_CREATED
this completes phase 2 of the task scheduler implementation.
Co-authored-by: Claude <noreply@anthropic.com>
replace confusing "tcb" (task control block) terminology with clearer
"mrb_task" naming:
- struct mrb_tcb -> struct mrb_task
- update mrb_task_state to use mrb_task pointers
- rename internal functions to avoid naming conflicts:
- mrb_task_new -> task_alloc
- mrb_task_free (lifecycle) -> task_free
- update field names for clarity:
- tcb_join -> join
- task (ruby object) -> self
- value (return value) -> result
this makes the code more readable and follows mruby naming conventions
like mrb_context, mrb_irep, etc.
Co-authored-by: Claude <noreply@anthropic.com>
extend mrb_fiber_state enum with task-specific states:
- MRB_TASK_CREATED: task context initialized
- MRB_TASK_STOPPED: task execution finished
add mrb_task_state structure to mrb_state:
- task queues array (dormant, ready, waiting, suspended)
- tick counter for scheduling
- wakeup_tick for sleep timing
- switching flag for context switches
remove duplicate mrb_task_state definition from task.h since it is
now defined in include/mruby.h. all changes guarded by
MRB_USE_TASK_SCHEDULER for zero overhead when disabled.
Co-authored-by: Claude <noreply@anthropic.com>
create mruby-task gem directory structure with:
- mrbgem.rake: gem specification with task scheduler define
- include/task.h: tcb structure and core scheduler declarations
- src/task.c: implementation skeleton with empty method stubs
- mrblib/task.rb: ruby api documentation and task::stat class
all methods have empty bodies ready for implementation.
Co-authored-by: Claude <noreply@anthropic.com>
The bug was in codegen_colon3 which used genop_2(OP_OCLASS, sym)
treating OCLASS as BB format, but OCLASS is B format that only
loads ::Object without a symbol parameter. The fix uses the correct
two-instruction pattern: OCLASS to load Object class, then GETMCNST
to retrieve the constant from it.
Co-authored-by: Claude <noreply@anthropic.com>
cast uint8_t node_type field to enum node_type to satisfy c++ stricter
type checking while maintaining memory efficiency of 1-byte storage.
Co-authored-by: Claude <noreply@anthropic.com>