diff --git a/mrbgems/hal-posix-task/README.md b/mrbgems/hal-posix-task/README.md new file mode 100644 index 000000000..157ebdba2 --- /dev/null +++ b/mrbgems/hal-posix-task/README.md @@ -0,0 +1,102 @@ +# hal-posix-task + +POSIX Hardware Abstraction Layer (HAL) implementation for mruby-task. + +## Description + +Provides timer and interrupt support for the mruby-task cooperative scheduler on POSIX-compliant platforms. Uses `SIGALRM` and `setitimer()` for periodic timer ticks, and `sigprocmask()` for interrupt protection. + +## Supported Platforms + +- Linux +- macOS +- BSD (FreeBSD, OpenBSD, NetBSD) +- Other POSIX-compliant Unix systems + +## Requirements + +- POSIX-compliant operating system +- Signal support (`SIGALRM`, `sigaction`, `sigprocmask`) +- Timer support (`setitimer`, `ITIMER_REAL`) + +## Usage + +### Explicit HAL Selection (Recommended) + +```ruby +MRuby::Build.new do |conf| + # ... other configuration ... + + # Specify POSIX HAL - automatically brings in mruby-task + conf.gem core: 'hal-posix-task' +end +``` + +### Auto-detection (Development) + +```ruby +MRuby::Build.new do |conf| + # ... other configuration ... + + # Auto-detects and selects hal-posix-task on POSIX platforms + conf.gem core: 'mruby-task' +end +``` + +## Implementation Details + +### Timer Mechanism + +- Uses `setitimer(ITIMER_REAL, ...)` to generate periodic `SIGALRM` signals +- Timer interval configured by `MRB_TICK_UNIT` (default: 4ms) +- Signal handler calls `mrb_tick()` for all registered VM instances + +### Interrupt Protection + +- Critical sections protected using `sigprocmask()` to block `SIGALRM` +- Prevents race conditions during task queue modifications +- Supports nested critical sections through signal masking + +### Multi-VM Support + +- Supports up to `MRB_TASK_MAX_VMS` concurrent mruby VM instances (default: 8) +- Single shared timer ticks all registered VMs +- Per-VM task counters optimize timer usage (timer disabled when idle) + +### Timer Optimization + +The implementation dynamically enables/disables the timer based on task state: + +- **Timer enabled** when: Multiple ready tasks OR any waiting tasks exist +- **Timer disabled** when: Single task or all tasks dormant/suspended +- Reduces CPU usage and power consumption when scheduler is idle + +## Configuration + +Override these macros in your build config if needed: + +```ruby +conf.gem core: 'hal-posix-task' do |spec| + # Custom tick interval (10ms instead of default 4ms) + spec.build.defines << 'MRB_TICK_UNIT=10' + + # Custom timeslice (5 ticks instead of default 3) + spec.build.defines << 'MRB_TIMESLICE_TICK_COUNT=5' + + # More concurrent VMs (16 instead of default 8) + spec.build.defines << 'MRB_TASK_MAX_VMS=16' +end +``` + +## Known Limitations + +- `SIGALRM` conflicts with other code using the same signal +- Timer resolution limited by platform (typically 1-10ms) +- Signal delivery may be delayed under heavy system load +- Not suitable for hard real-time requirements + +## See Also + +- `mruby-task` - Core task scheduler +- `hal-win-task` - Windows HAL implementation +- Task scheduler documentation: `mrbgems/mruby-task/README.md` diff --git a/mrbgems/hal-posix-task/mrbgem.rake b/mrbgems/hal-posix-task/mrbgem.rake new file mode 100644 index 000000000..570161c77 --- /dev/null +++ b/mrbgems/hal-posix-task/mrbgem.rake @@ -0,0 +1,8 @@ +MRuby::Gem::Specification.new('hal-posix-task') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' + spec.summary = 'POSIX HAL for mruby-task (Linux, macOS, BSD, Unix)' + + # HAL gem depends on feature gem - brings in mruby-task automatically + spec.add_dependency 'mruby-task', core: 'mruby-task' +end diff --git a/mrbgems/hal-posix-task/src/task_hal.c b/mrbgems/hal-posix-task/src/task_hal.c new file mode 100644 index 000000000..d5f7bbe5b --- /dev/null +++ b/mrbgems/hal-posix-task/src/task_hal.c @@ -0,0 +1,174 @@ +/* +** task_hal.c - POSIX HAL implementation for mruby-task +** +** See Copyright Notice in mruby.h +** +** POSIX implementation using SIGALRM and setitimer() for timer, +** and sigprocmask() for interrupt protection. +** +** Supported platforms: Linux, macOS, BSD, Unix +*/ + +#include +#include "task_hal.h" +#include +#include +#include +#include + +/* Multi-VM support */ +static mrb_state *vm_list[MRB_TASK_MAX_VMS]; +static volatile sig_atomic_t vm_count = 0; +static sigset_t alarm_mask; + +/* SIGALRM signal handler - ticks all registered VMs */ +static void +sigalrm_handler(int sig) +{ + int i; + (void)sig; + /* Tick all registered VMs */ + for (i = 0; i < vm_count; i++) { + if (vm_list[i]) { + mrb_tick(vm_list[i]); + } + } +} + +/* + * HAL Interface Implementation + */ + +void +mrb_task_hal_init(mrb_state *mrb) +{ + struct sigaction sa; + struct itimerval timer; + int i; + int vm_index = -1; + + /* Initialize task state */ + for (i = 0; i < 4; i++) { + mrb->task.queues[i] = NULL; + } + mrb->task.tick = 0; + mrb->task.wakeup_tick = UINT32_MAX; + mrb->task.switching = FALSE; + + /* Block SIGALRM during registration to avoid race */ + sigemptyset(&alarm_mask); + sigaddset(&alarm_mask, SIGALRM); + sigprocmask(SIG_BLOCK, &alarm_mask, NULL); + + /* Check if this VM is already registered */ + for (i = 0; i < vm_count; i++) { + if (vm_list[i] == mrb) { + vm_index = i; + break; + } + } + + /* Register new VM if not already present */ + if (vm_index < 0) { + if (vm_count >= MRB_TASK_MAX_VMS) { + sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); + mrb_raisef(mrb, E_RUNTIME_ERROR, + "too many mrb_states with task scheduler (max: %d)", + MRB_TASK_MAX_VMS); + } + vm_list[vm_count] = mrb; + vm_count++; + } + + /* Set up signal handler and timer only for first VM */ + if (vm_count == 1) { + /* Set up signal handler - SA_RESTART to avoid breaking IO operations */ + sa.sa_handler = sigalrm_handler; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGALRM, &sa, NULL); + + /* Start timer */ + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = MRB_TICK_UNIT * 1000; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = MRB_TICK_UNIT * 1000; + setitimer(ITIMER_REAL, &timer, NULL); + } + + /* Unblock SIGALRM */ + sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); +} + +void +mrb_task_enable_irq(void) +{ + sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); +} + +void +mrb_task_disable_irq(void) +{ + sigprocmask(SIG_BLOCK, &alarm_mask, NULL); +} + +void +mrb_task_hal_idle_cpu(mrb_state *mrb) +{ + (void)mrb; + /* On POSIX, just pause briefly */ + usleep(MRB_TICK_UNIT * 1000); +} + +void +mrb_task_hal_final(mrb_state *mrb) +{ + struct itimerval timer; + int i, j; + + /* Block SIGALRM during unregistration */ + sigprocmask(SIG_BLOCK, &alarm_mask, NULL); + + /* Find and remove this VM from the list */ + for (i = 0; i < vm_count; i++) { + if (vm_list[i] == mrb) { + /* Shift remaining VMs down */ + for (j = i; j < vm_count - 1; j++) { + vm_list[j] = vm_list[j + 1]; + } + vm_list[vm_count - 1] = NULL; + vm_count--; + break; + } + } + + /* Stop timer if last VM */ + if (vm_count == 0) { + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = 0; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = 0; + setitimer(ITIMER_REAL, &timer, NULL); + } + + /* Unblock SIGALRM */ + sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); +} + +/* + * Gem initialization (empty - HAL functions called by mruby-task) + */ + +void +mrb_hal_posix_task_gem_init(mrb_state *mrb) +{ + (void)mrb; + /* HAL interface functions are called by mruby-task gem */ +} + +void +mrb_hal_posix_task_gem_final(mrb_state *mrb) +{ + (void)mrb; + /* Cleanup handled by mrb_task_hal_final called from mruby-task */ +} diff --git a/mrbgems/hal-win-task/README.md b/mrbgems/hal-win-task/README.md new file mode 100644 index 000000000..b959afdec --- /dev/null +++ b/mrbgems/hal-win-task/README.md @@ -0,0 +1,109 @@ +# hal-win-task + +Windows Hardware Abstraction Layer (HAL) implementation for mruby-task. + +## Description + +Provides timer and interrupt support for the mruby-task cooperative scheduler on Windows platforms. Uses multimedia timer (`timeSetEvent`/`timeKillEvent`) for periodic timer ticks, and `CRITICAL_SECTION` for interrupt protection. + +## Supported Platforms + +- Windows 7 and later +- Windows Server 2008 R2 and later +- All versions with multimedia timer support + +## Requirements + +- Windows operating system +- Multimedia timer API (`winmm.lib`) +- Visual C++, MinGW, or compatible compiler + +## Usage + +### Explicit HAL Selection (Recommended) + +```ruby +MRuby::Build.new do |conf| + # ... other configuration ... + + # Specify Windows HAL - automatically brings in mruby-task + conf.gem core: 'hal-win-task' +end +``` + +### Auto-detection (Development) + +```ruby +MRuby::Build.new do |conf| + # ... other configuration ... + + # Auto-detects and selects hal-win-task on Windows platforms + conf.gem core: 'mruby-task' +end +``` + +## Implementation Details + +### Timer Mechanism + +- Uses Windows multimedia timer (`timeSetEvent`) for periodic callbacks +- Timer interval configured by `MRB_TICK_UNIT` (default: 4ms) +- `TIME_KILL_SYNCHRONOUS` flag ensures clean timer shutdown +- Requests 1ms timer resolution via `timeBeginPeriod(1)` + +### Interrupt Protection + +- Critical sections protected using `CRITICAL_SECTION` objects +- Prevents race conditions during task queue modifications +- `EnterCriticalSection`/`LeaveCriticalSection` used for mutual exclusion +- Supports nested critical sections (automatic lock counting) + +### Multi-VM Support + +- Supports up to `MRB_TASK_MAX_VMS` concurrent mruby VM instances (default: 8) +- Single shared timer ticks all registered VMs +- Per-VM task counters optimize timer usage (timer disabled when idle) +- Interlocked operations (`InterlockedIncrement`/`InterlockedDecrement`) for thread safety + +### Timer Optimization + +The implementation dynamically enables/disables the timer based on task state: + +- **Timer enabled** when: Multiple ready tasks OR any waiting tasks exist +- **Timer disabled** when: Single task or all tasks dormant/suspended +- Reduces CPU usage and power consumption when scheduler is idle + +## Configuration + +Override these macros in your build config if needed: + +```ruby +conf.gem core: 'hal-win-task' do |spec| + # Custom tick interval (10ms instead of default 4ms) + spec.build.defines << 'MRB_TICK_UNIT=10' + + # Custom timeslice (5 ticks instead of default 3) + spec.build.defines << 'MRB_TIMESLICE_TICK_COUNT=5' + + # More concurrent VMs (16 instead of default 8) + spec.build.defines << 'MRB_TASK_MAX_VMS=16' +end +``` + +## Known Limitations + +- Timer resolution typically limited to 1-2ms even with `timeBeginPeriod(1)` +- Multimedia timers consume system resources (kernel timer objects) +- Timer callbacks execute in separate thread context (handled internally) +- Not suitable for hard real-time requirements +- May interfere with other multimedia applications requesting different timer resolutions + +## See Also + +- `mruby-task` - Core task scheduler +- `hal-posix-task` - POSIX/Unix HAL implementation +- Task scheduler documentation: `mrbgems/mruby-task/README.md` + +## Build Notes + +The `winmm` library is automatically linked by the gem specification. No additional linker configuration is needed. diff --git a/mrbgems/hal-win-task/mrbgem.rake b/mrbgems/hal-win-task/mrbgem.rake new file mode 100644 index 000000000..ea40075e8 --- /dev/null +++ b/mrbgems/hal-win-task/mrbgem.rake @@ -0,0 +1,11 @@ +MRuby::Gem::Specification.new('hal-win-task') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' + spec.summary = 'Windows HAL for mruby-task' + + # HAL gem depends on feature gem - brings in mruby-task automatically + spec.add_dependency 'mruby-task', core: 'mruby-task' + + # Windows multimedia timer library + spec.linker.libraries << 'winmm' +end diff --git a/mrbgems/hal-win-task/src/task_hal.c b/mrbgems/hal-win-task/src/task_hal.c new file mode 100644 index 000000000..ec2b07d2a --- /dev/null +++ b/mrbgems/hal-win-task/src/task_hal.c @@ -0,0 +1,176 @@ +/* +** task_hal.c - Windows HAL implementation for mruby-task +** +** See Copyright Notice in mruby.h +** +** Windows implementation using multimedia timer (timeSetEvent/timeKillEvent) +** for periodic timer, and CRITICAL_SECTION for interrupt protection. +** +** Supported platforms: Windows (all versions with multimedia timer support) +*/ + +#include +#include "task_hal.h" +#include +#include +#include + +/* Multi-VM support */ +static mrb_state *vm_list[MRB_TASK_MAX_VMS]; +static volatile LONG vm_count = 0; +static CRITICAL_SECTION irq_lock; +static MMRESULT timer_id = 0; + +/* Multimedia timer callback - called periodically by Windows */ +static void CALLBACK +timer_callback(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) +{ + int i; + (void)uID; (void)uMsg; (void)dwUser; (void)dw1; (void)dw2; + + /* Tick all registered VMs */ + EnterCriticalSection(&irq_lock); + for (i = 0; i < vm_count; i++) { + if (vm_list[i]) { + mrb_tick(vm_list[i]); + } + } + LeaveCriticalSection(&irq_lock); +} + +/* + * HAL Interface Implementation + */ + +void +mrb_task_hal_init(mrb_state *mrb) +{ + int i; + LONG idx; + + /* Initialize task state */ + for (i = 0; i < 4; i++) { + mrb->task.queues[i] = NULL; + } + mrb->task.tick = 0; + mrb->task.wakeup_tick = UINT32_MAX; + mrb->task.switching = FALSE; + + /* Initialize critical section on first VM */ + if (vm_count == 0) { + InitializeCriticalSection(&irq_lock); + } + + EnterCriticalSection(&irq_lock); + + /* Check if this VM is already registered */ + idx = -1; + for (i = 0; i < vm_count; i++) { + if (vm_list[i] == mrb) { + idx = i; + break; + } + } + + /* Register new VM if not already present */ + if (idx < 0) { + if (vm_count >= MRB_TASK_MAX_VMS) { + LeaveCriticalSection(&irq_lock); + mrb_raisef(mrb, E_RUNTIME_ERROR, + "too many mrb_states with task scheduler (max: %d)", + MRB_TASK_MAX_VMS); + } + vm_list[vm_count] = mrb; + InterlockedIncrement(&vm_count); + } + + /* Start timer for first VM */ + if (vm_count == 1) { + /* Request 1ms timer resolution */ + timeBeginPeriod(1); + + /* Create periodic timer with MRB_TICK_UNIT interval */ + timer_id = timeSetEvent( + MRB_TICK_UNIT, /* interval in milliseconds */ + 1, /* resolution in milliseconds */ + timer_callback, /* callback function */ + 0, /* user data */ + TIME_PERIODIC | TIME_KILL_SYNCHRONOUS + ); + } + + LeaveCriticalSection(&irq_lock); +} + +void +mrb_task_enable_irq(void) +{ + LeaveCriticalSection(&irq_lock); +} + +void +mrb_task_disable_irq(void) +{ + EnterCriticalSection(&irq_lock); +} + +void +mrb_task_hal_idle_cpu(mrb_state *mrb) +{ + (void)mrb; + /* On Windows, just sleep briefly */ + Sleep(MRB_TICK_UNIT); +} + +void +mrb_task_hal_final(mrb_state *mrb) +{ + int i, j; + + EnterCriticalSection(&irq_lock); + + /* Find and remove this VM from the list */ + for (i = 0; i < vm_count; i++) { + if (vm_list[i] == mrb) { + /* Shift remaining VMs down */ + for (j = i; j < vm_count - 1; j++) { + vm_list[j] = vm_list[j + 1]; + } + vm_list[vm_count - 1] = NULL; + InterlockedDecrement(&vm_count); + break; + } + } + + /* Stop timer if last VM */ + if (vm_count == 0) { + if (timer_id != 0) { + timeKillEvent(timer_id); + timeEndPeriod(1); + timer_id = 0; + } + LeaveCriticalSection(&irq_lock); + DeleteCriticalSection(&irq_lock); + } + else { + LeaveCriticalSection(&irq_lock); + } +} + +/* + * Gem initialization (empty - HAL functions called by mruby-task) + */ + +void +mrb_hal_win_task_gem_init(mrb_state *mrb) +{ + (void)mrb; + /* HAL interface functions are called by mruby-task gem */ +} + +void +mrb_hal_win_task_gem_final(mrb_state *mrb) +{ + (void)mrb; + /* Cleanup handled by mrb_task_hal_final called from mruby-task */ +} diff --git a/mrbgems/mruby-task/README.md b/mrbgems/mruby-task/README.md index c92c32277..df5b34d88 100644 --- a/mrbgems/mruby-task/README.md +++ b/mrbgems/mruby-task/README.md @@ -251,42 +251,180 @@ These grow automatically as needed, similar to Fiber. ### HAL (Hardware Abstraction Layer) -The task scheduler requires platform-specific timer and interrupt support via four HAL functions: +The task scheduler uses a Hardware Abstraction Layer (HAL) to support different platforms. Platform-specific timer and interrupt handling is provided by separate HAL gems. -```c -void mrb_task_hal_init(mrb_state *mrb); // Initialize timer -void mrb_task_enable_irq(void); // Enable timer interrupts -void mrb_task_disable_irq(void); // Disable timer interrupts -void mrb_task_hal_idle_cpu(mrb_state *mrb); // Idle when no tasks ready +#### Built-in HAL Gems + +**hal-posix-task** - For POSIX systems (Linux, macOS, BSD, Unix) + +- Uses `SIGALRM` and `setitimer()` for timer +- Uses `sigprocmask()` for interrupt protection +- Uses `SA_RESTART` to prevent `EINTR` on system calls +- Supports multiple VMs per process + +**hal-win-task** - For Windows + +- Uses multimedia timer API (`timeSetEvent`/`timeKillEvent`) +- Uses `CRITICAL_SECTION` for interrupt protection +- Supports multiple VMs per process + +#### HAL Selection + +The task scheduler will automatically select an appropriate HAL gem based on your platform. For explicit control, you can specify the HAL gem in your build configuration: + +```ruby +MRuby::Build.new do |conf| + # Option 1: Explicit HAL selection (recommended) + conf.gem core: 'hal-posix-task' # For Linux/macOS/BSD + # or + conf.gem core: 'hal-win-task' # For Windows + + # mruby-task automatically loads if HAL is loaded + # But you can also specify it explicitly: + conf.gem core: 'mruby-task' +end ``` -### POSIX Platform +**Auto-detection behavior:** -On POSIX systems (Linux, macOS, BSD), the implementation uses: +- If you include `mruby-task` but no HAL gem, it will automatically load the appropriate HAL +- On Linux/macOS/BSD: loads `hal-posix-task` +- On Windows: loads `hal-win-task` +- On unknown platforms: fails with helpful error message -- `SIGALRM` signal for timer interrupts -- `setitimer()` for periodic tick generation -- `sigprocmask()` for interrupt enable/disable -- `SA_RESTART` flag to prevent `EINTR` on system calls +**Multi-VM support:** -### Other Platforms +- Both HAL implementations support multiple `mrb_state` instances +- A single system timer ticks all registered VMs +- Maximum VMs: configurable via `MRB_TASK_MAX_VMS` (default: 8) -For embedded or non-POSIX platforms, you must implement the HAL functions. See -the POSIX implementation in `src/task.c` as a reference. +#### Custom HAL Implementation -Example for a hypothetical embedded platform: +For embedded systems or unsupported platforms, you can create a custom HAL gem. The HAL must provide five functions defined in `mruby-task/include/task_hal.h`: ```c -void mrb_task_hal_init(mrb_state *mrb) { - // Setup hardware timer to call mrb_tick() every MRB_TICK_UNIT ms - hardware_timer_init(MRB_TICK_UNIT, timer_irq_handler); +/** + * Initialize timer and register VM + * Called during gem initialization + * Must set up periodic timer to call mrb_tick(mrb) every MRB_TICK_UNIT ms + */ +void mrb_task_hal_init(mrb_state *mrb); + +/** + * Cleanup timer and unregister VM + * Called during gem finalization + */ +void mrb_task_hal_final(mrb_state *mrb); + +/** + * Enable timer interrupts (exit critical section) + * Must be reentrant for nested calls + */ +void mrb_task_enable_irq(void); + +/** + * Disable timer interrupts (enter critical section) + * Must be reentrant for nested calls + */ +void mrb_task_disable_irq(void); + +/** + * Put CPU in low-power/idle mode + * Called when no tasks are ready but some are waiting + * Should sleep ~MRB_TICK_UNIT milliseconds + */ +void mrb_task_hal_idle_cpu(mrb_state *mrb); +``` + +**Example custom HAL gem structure:** + +``` +mrbgems/hal-myplatform-task/ +├── mrbgem.rake # Gem specification +├── include/ +│ └── task_hal.h # Symlink to mruby-task/include/task_hal.h +└── src/ + └── task_hal.c # Platform implementation +``` + +**mrbgem.rake:** + +```ruby +MRuby::Gem::Specification.new('hal-myplatform-task') do |spec| + spec.license = 'MIT' + spec.authors = 'Your Name' + spec.summary = 'My Platform HAL for mruby-task' + + # HAL gem depends on feature gem (important for build order) + spec.add_dependency 'mruby-task', core: 'mruby-task' + + # Add any platform-specific libraries or flags + # spec.linker.libraries << 'myplatform_timer' +end +``` + +**task_hal.c example for embedded system:** + +```c +#include +#include "task_hal.h" +#include "myplatform_hardware.h" + +static mrb_state *registered_vm = NULL; + +void mrb_task_hal_init(mrb_state *mrb) +{ + registered_vm = mrb; + + // Setup hardware timer to fire every MRB_TICK_UNIT milliseconds + hardware_timer_init(MRB_TICK_UNIT, timer_isr); + hardware_timer_start(); } -void timer_irq_handler(void) { - mrb_tick(global_mrb); // Must be called from timer interrupt +void mrb_task_hal_final(mrb_state *mrb) +{ + hardware_timer_stop(); + registered_vm = NULL; +} + +void mrb_task_enable_irq(void) +{ + hardware_enable_interrupts(); +} + +void mrb_task_disable_irq(void) +{ + hardware_disable_interrupts(); +} + +void mrb_task_hal_idle_cpu(mrb_state *mrb) +{ + (void)mrb; + hardware_sleep_mode(); // Enter low-power mode until interrupt +} + +// Timer ISR - must call mrb_tick() for scheduler +void timer_isr(void) +{ + if (registered_vm) { + mrb_tick(registered_vm); + } +} + +// Gem initialization (required but can be empty) +void mrb_hal_myplatform_task_gem_init(mrb_state *mrb) +{ + (void)mrb; +} + +void mrb_hal_myplatform_task_gem_final(mrb_state *mrb) +{ + (void)mrb; } ``` +See `hal-posix-task` and `hal-win-task` source code for complete reference implementations. + ## Examples ### Basic Multitasking diff --git a/mrbgems/mruby-task/include/task_hal.h b/mrbgems/mruby-task/include/task_hal.h new file mode 100644 index 000000000..448e6c808 --- /dev/null +++ b/mrbgems/mruby-task/include/task_hal.h @@ -0,0 +1,165 @@ +/* +** task_hal.h - Task scheduler Hardware Abstraction Layer (HAL) +** +** See Copyright Notice in mruby.h +** +** This header defines the HAL interface that platform-specific implementations +** must provide. The HAL separates platform-specific timer and interrupt handling +** from the core task scheduler logic. +*/ + +#ifndef MRUBY_TASK_HAL_H +#define MRUBY_TASK_HAL_H + +#include + +/* + * Configuration - can be overridden in platform-specific build configs + */ + +/* Tick period in milliseconds - how often the timer fires */ +#ifndef MRB_TICK_UNIT +#define MRB_TICK_UNIT 4 +#endif + +/* Number of timer ticks per task timeslice */ +#ifndef MRB_TIMESLICE_TICK_COUNT +#define MRB_TIMESLICE_TICK_COUNT 3 +#endif + +/* Maximum number of concurrent mrb_state instances with task scheduler */ +#ifndef MRB_TASK_MAX_VMS +#define MRB_TASK_MAX_VMS 8 +#endif + +/* + * HAL Interface Functions + * + * Platform-specific implementations (hal-posix-task, hal-win-task, etc.) + * must provide these functions. + */ + +/** + * Initialize hardware timer and interrupt system + * + * Called once during mruby-task gem initialization. Should set up a periodic + * timer that calls mrb_tick(mrb) every MRB_TICK_UNIT milliseconds. + * + * Requirements: + * - Initialize platform-specific timer hardware/APIs + * - Set up timer to fire every MRB_TICK_UNIT milliseconds + * - Register mrb_state for multi-VM support if needed + * - Initialize interrupt protection mechanisms (mutexes, signal masks, etc.) + * - Timer should call mrb_tick() on each tick for all registered VMs + * + * @param mrb The mruby state to associate with the timer + */ +void mrb_task_hal_init(mrb_state *mrb); + +/** + * Cleanup timer and interrupt resources + * + * Called during mruby-task gem finalization. Should clean up all resources + * allocated by mrb_task_hal_init(). + * + * Requirements: + * - Stop and cleanup platform timer + * - Unregister mrb_state from multi-VM support + * - Free any allocated HAL resources + * - If last VM, cleanup global HAL state + * + * @param mrb The mruby state to disassociate from the timer + */ +void mrb_task_hal_final(mrb_state *mrb); + +/** + * Enable timer interrupts (exit critical section) + * + * Called by the task scheduler when it's safe to allow timer interrupts. + * Should enable timer interrupts/callbacks that were disabled by + * mrb_task_disable_irq(). + * + * Requirements: + * - Must be reentrant (can be called multiple times) + * - Should use nesting counter or equivalent for nested critical sections + * - On POSIX: unmask signals + * - On Windows: leave critical section + * - On embedded: enable timer interrupts + */ +void mrb_task_enable_irq(void); + +/** + * Disable timer interrupts (enter critical section) + * + * Called by the task scheduler before modifying shared task state. + * Should disable timer interrupts/callbacks to prevent concurrent access. + * + * Requirements: + * - Must be reentrant (can be called multiple times) + * - Should use nesting counter or equivalent for nested critical sections + * - On POSIX: block signals + * - On Windows: enter critical section + * - On embedded: disable timer interrupts + */ +void mrb_task_disable_irq(void); + +/** + * Put CPU in low-power/idle mode + * + * Called by the scheduler when no tasks are ready to run but some tasks + * are waiting or suspended. Should briefly idle the CPU or sleep for + * approximately MRB_TICK_UNIT milliseconds to allow timer to fire. + * + * Requirements: + * - Should return when timer fires or after ~MRB_TICK_UNIT milliseconds + * - Must allow timer interrupts to occur during idle + * - On POSIX: usleep() or nanosleep() + * - On Windows: Sleep() + * - On embedded: platform-specific sleep/wait-for-interrupt instruction + * + * @param mrb The mruby state (for context, may be unused) + */ +void mrb_task_hal_idle_cpu(mrb_state *mrb); + +/* + * Core scheduler functions (implemented in task.c, called by HAL) + * + * These are provided by the core scheduler for HAL implementations to call. + */ + +/** + * Tick handler - advances scheduler time and wakes sleeping tasks + * + * HAL timer callback must call this function every MRB_TICK_UNIT milliseconds + * for each registered mrb_state. This function: + * - Increments the global tick counter + * - Decrements running task's timeslice + * - Wakes tasks whose sleep time has expired + * - Triggers context switches when needed + * + * @param mrb The mruby state to tick + */ +void mrb_tick(mrb_state *mrb); + +/** + * Main scheduler loop - runs all tasks until completion + * + * Executes tasks in priority order until all tasks are dormant. + * Handles task switching, preemption, and idle states. + * + * @param mrb The mruby state containing the task scheduler + * @return mrb_nil_value() when all tasks complete + */ +mrb_value mrb_tasks_run(mrb_state *mrb); + +/** + * Mark all tasks for garbage collection + * + * Called by the GC during marking phase to protect task objects + * and their associated data from collection. + * + * @param mrb The mruby state + */ +void mrb_task_mark_all(mrb_state *mrb); + +#endif /* MRUBY_TASK_HAL_H */ diff --git a/mrbgems/mruby-task/mrbgem.rake b/mrbgems/mruby-task/mrbgem.rake index 1c235a3b6..b82351ce2 100644 --- a/mrbgems/mruby-task/mrbgem.rake +++ b/mrbgems/mruby-task/mrbgem.rake @@ -6,8 +6,30 @@ MRuby::Gem::Specification.new('mruby-task') do |spec| # Enable task scheduler globally (required for vm.c integration) spec.build.defines << 'MRB_USE_TASK_SCHEDULER' - # Windows: link with multimedia timer library - if spec.for_windows? - spec.linker.libraries << 'winmm' + # Check if HAL gem is loaded + # HAL gems must be explicitly specified in build config (recommended) or via auto-selection below + spec.build.gems.one? { |g| g.name =~ /^hal-.*-task$/ } or begin + # No HAL found - determine appropriate error message or auto-load + suggested_hal = if spec.for_windows? + 'hal-win-task' + elsif RUBY_PLATFORM =~ /linux|darwin|bsd/ + 'hal-posix-task' + else + nil + end + + if suggested_hal + # Auto-load HAL gem for convenience (for development) + # This works because HAL gems declare dependency on mruby-task + warn "mruby-task: No HAL specified, loading #{suggested_hal} (explicit selection recommended)" + spec.build.gem core: suggested_hal + else + # Unknown platform - fail with helpful message + fail "mruby-task: No HAL available for platform '#{RUBY_PLATFORM}'.\n" \ + "Please specify HAL gem explicitly in your build config:\n" \ + " conf.gem core: 'hal-posix-task' # For Linux/macOS/BSD\n" \ + " conf.gem core: 'hal-win-task' # For Windows\n" \ + "Or create custom HAL - see mrbgems/mruby-task/README.md" + end end end diff --git a/mrbgems/mruby-task/src/task.c b/mrbgems/mruby-task/src/task.c index dd86dcda8..20cd577d7 100644 --- a/mrbgems/mruby-task/src/task.c +++ b/mrbgems/mruby-task/src/task.c @@ -19,13 +19,8 @@ #include #include #include -#ifdef _WIN32 -#include -#else -#include -#include -#endif #include "../include/task.h" +#include "task_hal.h" /* * Queue helper macros @@ -283,10 +278,6 @@ task_init_context(mrb_state *mrb, mrb_task *t, const struct RProc *proc) * Scheduler core */ -/* Forward declarations for timer control (defined in HAL section) */ -static void update_timer_state(void); -static void task_count_update(mrb_state *mrb, uint8_t old_status, uint8_t new_status); - /* Wake up tasks waiting on join for a completed task */ static void wake_up_join_waiters(mrb_state *mrb, mrb_task *completed_task) @@ -301,7 +292,6 @@ wake_up_join_waiters(mrb_state *mrb, mrb_task *completed_task) curr->reason = MRB_TASK_REASON_NONE; curr->join = NULL; q_insert_task(mrb, curr); - task_count_update(mrb, MRB_TASK_STATUS_WAITING, MRB_TASK_STATUS_READY); mrb_task_enable_irq(); } curr = next; @@ -312,12 +302,10 @@ wake_up_join_waiters(mrb_state *mrb, mrb_task *completed_task) static void task_change_state(mrb_state *mrb, mrb_task *t, uint8_t new_status) { - uint8_t old_status = t->status; mrb_task_disable_irq(); q_delete_task(mrb, t); t->status = new_status; q_insert_task(mrb, t); - task_count_update(mrb, old_status, new_status); mrb_task_enable_irq(); } @@ -381,7 +369,6 @@ execute_task(mrb_state *mrb, mrb_task *t) q_delete_task(mrb, t); t->status = MRB_TASK_STATUS_DORMANT; q_insert_task(mrb, t); - task_count_update(mrb, MRB_TASK_STATUS_RUNNING, MRB_TASK_STATUS_DORMANT); mrb_task_enable_irq(); /* Wake up tasks waiting on join */ @@ -495,6 +482,14 @@ mrb_tasks_run(mrb_state *mrb) * Sleep operations */ +/* Platform-specific includes for root-context sleeping */ +#if defined(__unix__) || defined(__APPLE__) || defined(__MACH__) +#include +#include +#elif defined(_WIN32) +#include +#endif + static void sleep_us_impl(mrb_state *mrb, mrb_int usec) { @@ -580,7 +575,6 @@ sleep_us_impl(mrb_state *mrb, mrb_int usec) } q_insert_task(mrb, t); - task_count_update(mrb, MRB_TASK_STATUS_READY, MRB_TASK_STATUS_WAITING); mrb_task_enable_irq(); @@ -610,7 +604,6 @@ mrb_f_sleep(mrb_state *mrb, mrb_value self) q_delete_task(mrb, t); t->status = MRB_TASK_STATUS_SUSPENDED; q_insert_task(mrb, t); - task_count_update(mrb, MRB_TASK_STATUS_READY, MRB_TASK_STATUS_SUSPENDED); mrb_task_enable_irq(); switching_ = TRUE; } @@ -659,580 +652,6 @@ mrb_f_usleep(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(usec); } -/* - * HAL POSIX implementation (Linux, BSD, macOS) - */ - -#if defined(__unix__) || defined(__APPLE__) || defined(__MACH__) -#include -#include -#include - -/* Maximum number of concurrent mrb_states with task scheduler */ -#ifndef MRB_TASK_MAX_VMS -#define MRB_TASK_MAX_VMS 8 -#endif - -static mrb_state *vm_list[MRB_TASK_MAX_VMS]; -static volatile sig_atomic_t vm_count = 0; -static volatile sig_atomic_t timer_enabled = 0; -static sigset_t alarm_mask; - -/* Task counters for each VM */ -static uint16_t vm_ready_counts[MRB_TASK_MAX_VMS]; -static uint16_t vm_waiting_counts[MRB_TASK_MAX_VMS]; - -/* Find VM index in vm_list */ -static int -find_vm_index(mrb_state *mrb) -{ - int i; - for (i = 0; i < vm_count; i++) { - if (vm_list[i] == mrb) { - return i; - } - } - return -1; -} - -/* Helper functions to maintain task counters and update timer */ -static void -task_count_update(mrb_state *mrb, uint8_t old_status, uint8_t new_status) -{ - int vm_idx = find_vm_index(mrb); - if (vm_idx < 0) return; - - /* Decrement old queue counter */ - if (old_status == MRB_TASK_STATUS_READY || old_status == MRB_TASK_STATUS_RUNNING) { - if (vm_ready_counts[vm_idx] > 0) { - vm_ready_counts[vm_idx]--; - } - } - else if (old_status == MRB_TASK_STATUS_WAITING) { - if (vm_waiting_counts[vm_idx] > 0) { - vm_waiting_counts[vm_idx]--; - } - } - - /* Increment new queue counter */ - if (new_status == MRB_TASK_STATUS_READY || new_status == MRB_TASK_STATUS_RUNNING) { - vm_ready_counts[vm_idx]++; - } - else if (new_status == MRB_TASK_STATUS_WAITING) { - vm_waiting_counts[vm_idx]++; - } - - update_timer_state(); -} - -/* Check if timer should be enabled based on task counts */ -static int -should_timer_be_enabled(void) -{ - int i; - /* Timer needed if any VM has multiple ready tasks OR any waiting tasks */ - for (i = 0; i < vm_count; i++) { - if (vm_ready_counts[i] > 1 || vm_waiting_counts[i] > 0) { - return 1; - } - } - return 0; -} - -/* Platform-specific timer control */ -static void -hal_set_timer_enabled(int enable) -{ - struct itimerval timer; - - if (enable) { - /* Enable timer */ - timer.it_value.tv_sec = 0; - timer.it_value.tv_usec = MRB_TICK_UNIT * 1000; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = MRB_TICK_UNIT * 1000; - } - else { - /* Disable timer */ - timer.it_value.tv_sec = 0; - timer.it_value.tv_usec = 0; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = 0; - } - - setitimer(ITIMER_REAL, &timer, NULL); -} - -/* Update timer state based on task counts */ -static void -update_timer_state(void) -{ - int needs_timer = should_timer_be_enabled(); - - /* Update timer only if state changed */ - if (needs_timer && !timer_enabled) { - hal_set_timer_enabled(1); - timer_enabled = 1; - } - else if (!needs_timer && timer_enabled) { - hal_set_timer_enabled(0); - timer_enabled = 0; - } -} - -static void -sigalrm_handler(int sig) -{ - int i; - (void)sig; - /* Tick all registered VMs */ - for (i = 0; i < vm_count; i++) { - if (vm_list[i]) { - mrb_tick(vm_list[i]); - } - } -} - -void -mrb_task_hal_init(mrb_state *mrb) -{ - struct sigaction sa; - int i; - int vm_index = -1; - - /* Initialize task state */ - for (i = 0; i < 4; i++) { - mrb->task.queues[i] = NULL; - } - mrb->task.tick = 0; - mrb->task.wakeup_tick = UINT32_MAX; - mrb->task.switching = FALSE; - - /* Block SIGALRM during registration to avoid race */ - sigemptyset(&alarm_mask); - sigaddset(&alarm_mask, SIGALRM); - sigprocmask(SIG_BLOCK, &alarm_mask, NULL); - - /* Check if this VM is already registered */ - for (i = 0; i < vm_count; i++) { - if (vm_list[i] == mrb) { - vm_index = i; - break; - } - } - - /* Register new VM if not already present */ - if (vm_index < 0) { - if (vm_count >= MRB_TASK_MAX_VMS) { - sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); - mrb_raisef(mrb, E_RUNTIME_ERROR, - "too many mrb_states with task scheduler (max: %d)", - MRB_TASK_MAX_VMS); - } - vm_list[vm_count] = mrb; - vm_ready_counts[vm_count] = 0; - vm_waiting_counts[vm_count] = 0; - vm_count++; - } - - /* Set up signal handler only for first VM */ - if (vm_count == 1) { - /* Set up signal handler - no SA_RESTART so nanosleep returns on EINTR */ - sa.sa_handler = sigalrm_handler; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaction(SIGALRM, &sa, NULL); - } - - /* Update timer state based on current task queues */ - update_timer_state(); - - /* Unblock SIGALRM */ - sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); -} - -void -mrb_task_enable_irq(void) -{ - sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); -} - -void -mrb_task_disable_irq(void) -{ - sigprocmask(SIG_BLOCK, &alarm_mask, NULL); -} - -void -mrb_task_hal_idle_cpu(mrb_state *mrb) -{ - (void)mrb; - /* On POSIX, just pause briefly */ - usleep(MRB_TICK_UNIT * 1000); -} - -void -mrb_task_hal_final(mrb_state *mrb) -{ - int i, j; - - /* Block SIGALRM during unregistration */ - sigprocmask(SIG_BLOCK, &alarm_mask, NULL); - - /* Find and remove this VM from the list */ - for (i = 0; i < vm_count; i++) { - if (vm_list[i] == mrb) { - /* Shift remaining VMs and counters down */ - for (j = i; j < vm_count - 1; j++) { - vm_list[j] = vm_list[j + 1]; - vm_ready_counts[j] = vm_ready_counts[j + 1]; - vm_waiting_counts[j] = vm_waiting_counts[j + 1]; - } - vm_list[vm_count - 1] = NULL; - vm_ready_counts[vm_count - 1] = 0; - vm_waiting_counts[vm_count - 1] = 0; - vm_count--; - break; - } - } - - /* Update timer state based on remaining VMs */ - update_timer_state(); - - /* Unblock SIGALRM */ - sigprocmask(SIG_UNBLOCK, &alarm_mask, NULL); -} - -#elif defined(_WIN32) -/* - * HAL Windows implementation - */ - -#include -#include - -/* Maximum number of concurrent mrb_states with task scheduler */ -#ifndef MRB_TASK_MAX_VMS -#define MRB_TASK_MAX_VMS 8 -#endif - -static mrb_state *vm_list[MRB_TASK_MAX_VMS]; -static volatile LONG vm_count = 0; -static volatile LONG timer_enabled = 0; -static CRITICAL_SECTION irq_lock; -static MMRESULT timer_id = 0; - -/* Task counters for each VM */ -static uint16_t vm_ready_counts[MRB_TASK_MAX_VMS]; -static uint16_t vm_waiting_counts[MRB_TASK_MAX_VMS]; - -/* Find VM index in vm_list */ -static int -find_vm_index(mrb_state *mrb) -{ - int i; - for (i = 0; i < vm_count; i++) { - if (vm_list[i] == mrb) { - return i; - } - } - return -1; -} - -/* Helper functions to maintain task counters and update timer */ -static void -task_count_update(mrb_state *mrb, uint8_t old_status, uint8_t new_status) -{ - int vm_idx = find_vm_index(mrb); - if (vm_idx < 0) return; - - /* Decrement old queue counter */ - if (old_status == MRB_TASK_STATUS_READY || old_status == MRB_TASK_STATUS_RUNNING) { - if (vm_ready_counts[vm_idx] > 0) { - vm_ready_counts[vm_idx]--; - } - } - else if (old_status == MRB_TASK_STATUS_WAITING) { - if (vm_waiting_counts[vm_idx] > 0) { - vm_waiting_counts[vm_idx]--; - } - } - - /* Increment new queue counter */ - if (new_status == MRB_TASK_STATUS_READY || new_status == MRB_TASK_STATUS_RUNNING) { - vm_ready_counts[vm_idx]++; - } - else if (new_status == MRB_TASK_STATUS_WAITING) { - vm_waiting_counts[vm_idx]++; - } - - update_timer_state(); -} - -/* Check if timer should be enabled based on task counts */ -static int -should_timer_be_enabled(void) -{ - int i; - /* Timer needed if any VM has multiple ready tasks OR any waiting tasks */ - for (i = 0; i < vm_count; i++) { - if (vm_ready_counts[i] > 1 || vm_waiting_counts[i] > 0) { - return 1; - } - } - return 0; -} - -/* Multimedia timer callback - called periodically by Windows */ -static void CALLBACK -timer_callback(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) -{ - int i; - (void)uID; (void)uMsg; (void)dwUser; (void)dw1; (void)dw2; - - /* Tick all registered VMs */ - EnterCriticalSection(&irq_lock); - for (i = 0; i < vm_count; i++) { - if (vm_list[i]) { - mrb_tick(vm_list[i]); - } - } - LeaveCriticalSection(&irq_lock); -} - -/* Platform-specific timer control */ -static void -hal_set_timer_enabled(int enable) -{ - if (enable) { - /* Enable timer - create multimedia timer if not already running */ - if (timer_id == 0) { - /* Request 1ms timer resolution */ - timeBeginPeriod(1); - - /* Create periodic timer with MRB_TICK_UNIT interval */ - timer_id = timeSetEvent( - MRB_TICK_UNIT, /* interval in milliseconds */ - 1, /* resolution in milliseconds */ - timer_callback, /* callback function */ - 0, /* user data */ - TIME_PERIODIC | TIME_KILL_SYNCHRONOUS - ); - } - } - else { - /* Disable timer */ - if (timer_id != 0) { - timeKillEvent(timer_id); - timeEndPeriod(1); - timer_id = 0; - } - } -} - -/* Update timer state based on task counts */ -static void -update_timer_state(void) -{ - int needs_timer = should_timer_be_enabled(); - - /* Update timer only if state changed */ - if (needs_timer && !timer_enabled) { - hal_set_timer_enabled(1); - InterlockedExchange(&timer_enabled, 1); - } - else if (!needs_timer && timer_enabled) { - hal_set_timer_enabled(0); - InterlockedExchange(&timer_enabled, 0); - } -} - -void -mrb_task_hal_init(mrb_state *mrb) -{ - int i; - LONG idx; - - /* Initialize task state */ - for (i = 0; i < 4; i++) { - mrb->task.queues[i] = NULL; - } - mrb->task.tick = 0; - mrb->task.wakeup_tick = UINT32_MAX; - mrb->task.switching = FALSE; - - /* Initialize critical section on first VM */ - if (vm_count == 0) { - InitializeCriticalSection(&irq_lock); - } - - EnterCriticalSection(&irq_lock); - - /* Check if this VM is already registered */ - idx = -1; - for (i = 0; i < vm_count; i++) { - if (vm_list[i] == mrb) { - idx = i; - break; - } - } - - /* Register new VM if not already present */ - if (idx < 0) { - if (vm_count >= MRB_TASK_MAX_VMS) { - LeaveCriticalSection(&irq_lock); - mrb_raisef(mrb, E_RUNTIME_ERROR, - "too many mrb_states with task scheduler (max: %d)", - MRB_TASK_MAX_VMS); - } - vm_list[vm_count] = mrb; - vm_ready_counts[vm_count] = 0; - vm_waiting_counts[vm_count] = 0; - InterlockedIncrement(&vm_count); - } - - /* Update timer state based on current task queues */ - update_timer_state(); - - LeaveCriticalSection(&irq_lock); -} - -void -mrb_task_enable_irq(void) -{ - LeaveCriticalSection(&irq_lock); -} - -void -mrb_task_disable_irq(void) -{ - EnterCriticalSection(&irq_lock); -} - -void -mrb_task_hal_idle_cpu(mrb_state *mrb) -{ - (void)mrb; - /* On Windows, just sleep briefly */ - Sleep(MRB_TICK_UNIT); -} - -void -mrb_task_hal_final(mrb_state *mrb) -{ - int i, j; - - EnterCriticalSection(&irq_lock); - - /* Find and remove this VM from the list */ - for (i = 0; i < vm_count; i++) { - if (vm_list[i] == mrb) { - /* Shift remaining VMs and counters down */ - for (j = i; j < vm_count - 1; j++) { - vm_list[j] = vm_list[j + 1]; - vm_ready_counts[j] = vm_ready_counts[j + 1]; - vm_waiting_counts[j] = vm_waiting_counts[j + 1]; - } - vm_list[vm_count - 1] = NULL; - vm_ready_counts[vm_count - 1] = 0; - vm_waiting_counts[vm_count - 1] = 0; - InterlockedDecrement(&vm_count); - break; - } - } - - /* Update timer state based on remaining VMs */ - update_timer_state(); - - /* Cleanup critical section if last VM */ - if (vm_count == 0) { - LeaveCriticalSection(&irq_lock); - DeleteCriticalSection(&irq_lock); - } - else { - LeaveCriticalSection(&irq_lock); - } -} - -#else -/* Stub implementation for unsupported platforms */ -/* WARNING: Task scheduler requires platform-specific timer implementation */ -/* This stub allows compilation but task scheduling will NOT work correctly */ - -/* Stub for task_count_update */ -static void -task_count_update(mrb_state *mrb, uint8_t old_status, uint8_t new_status) -{ - (void)mrb; - (void)old_status; - (void)new_status; - /* Platform-specific task counting for timer control not implemented */ -} - -/* Platform-specific timer control stub */ -static void -hal_set_timer_enabled(int enable) -{ - (void)enable; - /* TODO: Platform-specific timer control */ -} - -/* Stub for update_timer_state */ -static void -update_timer_state(void) -{ - /* TODO: Implement timer state management */ -} - -static int -should_timer_be_enabled(void) -{ - return 0; /* Stub: always return false */ -} - -void -mrb_task_hal_init(mrb_state *mrb) -{ - int i; - - /* Initialize task state */ - for (i = 0; i < 4; i++) { - mrb->task.queues[i] = NULL; - } - mrb->task.tick = 0; - mrb->task.wakeup_tick = UINT32_MAX; - mrb->task.switching = FALSE; - - /* TODO: Platform-specific timer initialization */ -} - -void -mrb_task_enable_irq(void) -{ - /* TODO: Platform-specific interrupt enable */ -} - -void -mrb_task_disable_irq(void) -{ - /* TODO: Platform-specific interrupt disable */ -} - -void -mrb_task_hal_idle_cpu(mrb_state *mrb) -{ - (void)mrb; - /* TODO: Platform-specific idle/sleep */ -} - -void -mrb_task_hal_final(mrb_state *mrb) -{ - (void)mrb; - /* TODO: Platform-specific cleanup */ -} -#endif - /* * Task class methods */ @@ -1303,7 +722,6 @@ mrb_task_s_new(mrb_state *mrb, mrb_value self) /* Insert into ready queue */ mrb_task_disable_irq(); q_insert_task(mrb, t); - task_count_update(mrb, MRB_TASK_STATUS_DORMANT, MRB_TASK_STATUS_READY); mrb_task_enable_irq(); /* Trigger context switch if this task has higher priority than current */ @@ -1685,12 +1103,10 @@ mrb_task_terminate(mrb_state *mrb, mrb_value self) mrb_task_disable_irq(); /* Move to dormant queue */ - uint8_t old_status = t->status; q_delete_task(mrb, t); t->status = MRB_TASK_STATUS_DORMANT; t->c.status = MRB_TASK_STOPPED; q_insert_task(mrb, t); - task_count_update(mrb, old_status, MRB_TASK_STATUS_DORMANT); mrb_task_enable_irq(); @@ -1735,7 +1151,6 @@ mrb_task_join(mrb_state *mrb, mrb_value self) current->reason = MRB_TASK_REASON_JOIN; current->join = t; q_insert_task(mrb, current); - task_count_update(mrb, MRB_TASK_STATUS_READY, MRB_TASK_STATUS_WAITING); mrb_task_enable_irq(); /* Trigger context switch */