mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-task: add initial gem structure with api skeleton
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>
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
** task.h - Task scheduler
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
#ifndef MRUBY_TASK_H
|
||||
#define MRUBY_TASK_H
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_USE_TASK_SCHEDULER
|
||||
|
||||
/*
|
||||
* Task status values (bit-mapped)
|
||||
*/
|
||||
enum {
|
||||
MRB_TASKSTATUS_DORMANT = 0x00, /* Not started or finished */
|
||||
MRB_TASKSTATUS_READY = 0x02, /* Ready to run */
|
||||
MRB_TASKSTATUS_RUNNING = 0x03, /* Currently executing */
|
||||
MRB_TASKSTATUS_WAITING = 0x04, /* Waiting for condition */
|
||||
MRB_TASKSTATUS_SUSPENDED = 0x08, /* Manually suspended */
|
||||
};
|
||||
|
||||
/*
|
||||
* Task wait reason
|
||||
*/
|
||||
enum {
|
||||
MRB_TASKREASON_NONE = 0x00, /* No specific reason */
|
||||
MRB_TASKREASON_SLEEP = 0x01, /* Sleeping for time */
|
||||
MRB_TASKREASON_MUTEX = 0x02, /* Waiting for mutex (reserved) */
|
||||
MRB_TASKREASON_JOIN = 0x04, /* Waiting for another task */
|
||||
};
|
||||
|
||||
/*
|
||||
* Task Control Block (TCB)
|
||||
*/
|
||||
typedef struct mrb_tcb {
|
||||
struct mrb_tcb *next; /* Linked list pointer */
|
||||
uint8_t priority; /* Initial priority (0-255, 0=highest) */
|
||||
uint8_t priority_preemption; /* Effective priority for preemption */
|
||||
volatile uint8_t timeslice; /* Remaining time slice ticks */
|
||||
uint8_t status; /* Current status (TASKSTATUS enum) */
|
||||
uint8_t reason; /* Wait reason (TASKREASON enum) */
|
||||
mrb_value name; /* Optional task name */
|
||||
|
||||
union {
|
||||
uint32_t wakeup_tick; /* Tick count to wake up (for sleep) */
|
||||
void *mutex; /* Mutex pointer (reserved) */
|
||||
};
|
||||
const struct mrb_tcb *tcb_join; /* Task being waited on (for join) */
|
||||
|
||||
mrb_value task; /* Ruby Task object reference */
|
||||
mrb_value value; /* Task return value */
|
||||
struct mrb_context c; /* Execution context (stack, callinfo, etc) */
|
||||
} mrb_tcb;
|
||||
|
||||
/*
|
||||
* Task scheduler state (part of mrb_state)
|
||||
*/
|
||||
#define MRB_NUM_TASK_QUEUE 4
|
||||
|
||||
typedef struct mrb_task_state {
|
||||
mrb_tcb *queues[MRB_NUM_TASK_QUEUE]; /* Task queues */
|
||||
volatile uint32_t tick; /* Current tick count */
|
||||
volatile uint32_t wakeup_tick; /* Next wakeup tick */
|
||||
volatile mrb_bool switching; /* Context switch pending flag */
|
||||
} mrb_task_state;
|
||||
|
||||
/* Queue indices */
|
||||
#define MRB_TASK_QUEUE_DORMANT 0
|
||||
#define MRB_TASK_QUEUE_READY 1
|
||||
#define MRB_TASK_QUEUE_WAITING 2
|
||||
#define MRB_TASK_QUEUE_SUSPENDED 3
|
||||
|
||||
/* Configuration */
|
||||
#ifndef MRB_TICK_UNIT
|
||||
#define MRB_TICK_UNIT 4 /* Tick period in milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef MRB_TIMESLICE_TICK_COUNT
|
||||
#define MRB_TIMESLICE_TICK_COUNT 3 /* Number of ticks per timeslice */
|
||||
#endif
|
||||
|
||||
#define TASK_STACK_INIT_SIZE 64 /* Initial task stack size */
|
||||
#define TASK_CI_INIT_SIZE 8 /* Initial task callinfo size */
|
||||
|
||||
/*
|
||||
* HAL (Hardware Abstraction Layer) functions
|
||||
* Platform-specific implementations must provide these
|
||||
*/
|
||||
void mrb_task_hal_init(mrb_state *mrb);
|
||||
void mrb_task_enable_irq(void);
|
||||
void mrb_task_disable_irq(void);
|
||||
void mrb_task_hal_idle_cpu(mrb_state *mrb);
|
||||
|
||||
/*
|
||||
* Core task scheduler API
|
||||
*/
|
||||
void mrb_tick(mrb_state *mrb);
|
||||
mrb_value mrb_tasks_run(mrb_state *mrb);
|
||||
|
||||
/*
|
||||
* Task context status values (extends mrb_fiber_state)
|
||||
*/
|
||||
#define MRB_TASK_CREATED (MRB_FIBER_TRANSFERRED + 1)
|
||||
#define MRB_TASK_STOPPED (MRB_FIBER_TRANSFERRED + 2)
|
||||
|
||||
#endif /* MRB_USE_TASK_SCHEDULER */
|
||||
|
||||
#endif /* MRUBY_TASK_H */
|
||||
@@ -0,0 +1,8 @@
|
||||
MRuby::Gem::Specification.new('mruby-task') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.authors = 'mruby developers'
|
||||
spec.summary = 'Cooperative multitasking with preemptive scheduling'
|
||||
|
||||
spec.cc.defines << 'MRB_USE_TASK_SCHEDULER'
|
||||
spec.add_dependency 'mruby-fiber' # Uses same context infrastructure
|
||||
end
|
||||
@@ -0,0 +1,115 @@
|
||||
class Task
|
||||
# Class methods
|
||||
|
||||
# Create a new task with optional name and priority
|
||||
# @param name [String, Symbol, nil] optional task name
|
||||
# @param priority [Integer, nil] task priority (0-255, 0 is highest)
|
||||
# @yield block to execute in the task
|
||||
# @return [Task] the created task
|
||||
def self.new(name: nil, priority: nil, &block)
|
||||
end
|
||||
|
||||
# Get the currently running task
|
||||
# @return [Task] the current task
|
||||
def self.current
|
||||
end
|
||||
|
||||
# Get all tasks in the system
|
||||
# @return [Array<Task>] array of all tasks
|
||||
def self.list
|
||||
end
|
||||
|
||||
# Yield execution to other tasks (cooperative yielding)
|
||||
# @return [nil]
|
||||
def self.pass
|
||||
end
|
||||
|
||||
# Get task scheduler statistics
|
||||
# @return [Task::Stat] scheduler statistics object
|
||||
def self.stat
|
||||
end
|
||||
|
||||
# Find a task by name
|
||||
# @param name [String, Symbol] task name to find
|
||||
# @return [Task, nil] the task if found, nil otherwise
|
||||
def self.get(name)
|
||||
end
|
||||
|
||||
# Instance methods
|
||||
|
||||
# Get the task status
|
||||
# @return [Symbol] one of :DORMANT, :READY, :RUNNING, :WAITING, :SUSPENDED
|
||||
def status
|
||||
end
|
||||
|
||||
# Get the task name
|
||||
# @return [String, Symbol, nil] the task name
|
||||
def name
|
||||
end
|
||||
|
||||
# Set the task name
|
||||
# @param val [String, Symbol] new task name
|
||||
def name=(val)
|
||||
end
|
||||
|
||||
# Get the task priority
|
||||
# @return [Integer] priority value (0-255, 0 is highest)
|
||||
def priority
|
||||
end
|
||||
|
||||
# Set the task priority
|
||||
# @param val [Integer] new priority (0-255, 0 is highest)
|
||||
def priority=(val)
|
||||
end
|
||||
|
||||
# Suspend the task
|
||||
# @return [self]
|
||||
def suspend
|
||||
end
|
||||
|
||||
# Resume a suspended task
|
||||
# @return [self]
|
||||
def resume
|
||||
end
|
||||
|
||||
# Terminate the task
|
||||
# @return [self]
|
||||
def terminate
|
||||
end
|
||||
|
||||
# Wait for the task to complete
|
||||
# @return [self]
|
||||
def join
|
||||
end
|
||||
|
||||
# Task scheduler statistics class
|
||||
class Stat
|
||||
attr_reader :tick, :wakeup_tick, :tasks
|
||||
|
||||
def initialize(tick, wakeup_tick, tasks)
|
||||
@tick = tick
|
||||
@wakeup_tick = wakeup_tick
|
||||
@tasks = tasks
|
||||
end
|
||||
|
||||
def to_s
|
||||
"tick: #{@tick}, wakeup_tick: #{@wakeup_tick}, tasks: #{@tasks.size}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Kernel methods for sleeping
|
||||
|
||||
module Kernel
|
||||
# Sleep for specified duration
|
||||
# @param sec [Integer, Float, nil] seconds to sleep (nil = suspend indefinitely)
|
||||
# @return [Integer, nil] actual sleep time
|
||||
def sleep(sec = nil)
|
||||
end
|
||||
|
||||
# Sleep for specified milliseconds
|
||||
# @param ms [Integer] milliseconds to sleep
|
||||
# @return [nil]
|
||||
def sleep_ms(ms)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
** task.c - Task scheduler
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_USE_TASK_SCHEDULER
|
||||
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/data.h>
|
||||
#include <mruby/error.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/variable.h>
|
||||
#include "../include/task.h"
|
||||
|
||||
/*
|
||||
* Queue helper macros
|
||||
*/
|
||||
#define q_dormant_ (mrb->task.queues[MRB_TASK_QUEUE_DORMANT])
|
||||
#define q_ready_ (mrb->task.queues[MRB_TASK_QUEUE_READY])
|
||||
#define q_waiting_ (mrb->task.queues[MRB_TASK_QUEUE_WAITING])
|
||||
#define q_suspended_ (mrb->task.queues[MRB_TASK_QUEUE_SUSPENDED])
|
||||
#define tick_ (mrb->task.tick)
|
||||
#define wakeup_tick_ (mrb->task.wakeup_tick)
|
||||
#define switching_ (mrb->task.switching)
|
||||
|
||||
/*
|
||||
* Task data type for GC
|
||||
*/
|
||||
static void
|
||||
mrb_task_free(mrb_state *mrb, void *ptr)
|
||||
{
|
||||
/* TODO: Free TCB and associated resources */
|
||||
}
|
||||
|
||||
static const struct mrb_data_type mrb_task_type = {
|
||||
"Task", mrb_task_free,
|
||||
};
|
||||
|
||||
/*
|
||||
* Queue operations
|
||||
*/
|
||||
|
||||
/* Insert task into appropriate queue based on priority */
|
||||
static void
|
||||
q_insert_task(mrb_state *mrb, mrb_tcb *tcb)
|
||||
{
|
||||
/* TODO: Implement priority-based insertion */
|
||||
}
|
||||
|
||||
/* Delete task from its current queue */
|
||||
static void
|
||||
q_delete_task(mrb_state *mrb, mrb_tcb *tcb)
|
||||
{
|
||||
/* TODO: Implement queue deletion */
|
||||
}
|
||||
|
||||
/* Find task in queues */
|
||||
static mrb_tcb*
|
||||
q_find_task(mrb_state *mrb, mrb_tcb *tcb)
|
||||
{
|
||||
/* TODO: Implement task search */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* TCB lifecycle
|
||||
*/
|
||||
|
||||
/* Allocate new TCB */
|
||||
static mrb_tcb*
|
||||
mrb_tcb_new(mrb_state *mrb)
|
||||
{
|
||||
/* TODO: Allocate and initialize TCB */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free TCB and context */
|
||||
static void
|
||||
mrb_tcb_free(mrb_state *mrb, mrb_tcb *tcb)
|
||||
{
|
||||
/* TODO: Free TCB and associated context */
|
||||
}
|
||||
|
||||
/* Initialize task context (stack and callinfo) */
|
||||
static void
|
||||
mrb_task_init_context(mrb_state *mrb, mrb_value task, struct RProc *proc)
|
||||
{
|
||||
/* TODO: Allocate and initialize context similar to Fiber */
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler core
|
||||
*/
|
||||
|
||||
/* Tick handler - called by timer interrupt */
|
||||
void
|
||||
mrb_tick(mrb_state *mrb)
|
||||
{
|
||||
/* TODO: Implement tick handler
|
||||
* - Increment tick counter
|
||||
* - Decrease current task timeslice
|
||||
* - Wake up sleeping tasks
|
||||
* - Set switching flag if needed
|
||||
*/
|
||||
}
|
||||
|
||||
/* Main scheduler loop */
|
||||
mrb_value
|
||||
mrb_tasks_run(mrb_state *mrb)
|
||||
{
|
||||
/* TODO: Implement main scheduler loop
|
||||
* - Get next ready task
|
||||
* - Switch context
|
||||
* - Execute via mrb_vm_exec()
|
||||
* - Handle completion/switching
|
||||
* - Run incremental GC
|
||||
*/
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sleep operations
|
||||
*/
|
||||
|
||||
static void
|
||||
sleep_ms_impl(mrb_state *mrb, mrb_int ms)
|
||||
{
|
||||
/* TODO: Implement sleep
|
||||
* - Move current task to waiting queue
|
||||
* - Set wakeup tick
|
||||
* - Trigger context switch
|
||||
*/
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_f_sleep(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Kernel#sleep */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_f_sleep_ms(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Kernel#sleep_ms */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* Task class methods
|
||||
*/
|
||||
|
||||
static mrb_value
|
||||
mrb_task_s_new(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task.new */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_s_current(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task.current */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_s_list(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task.list */
|
||||
return mrb_ary_new(mrb);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_s_pass(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task.pass */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_s_stat(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task.stat */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_s_get(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task.get */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
/*
|
||||
* Task instance methods
|
||||
*/
|
||||
|
||||
static mrb_value
|
||||
mrb_task_status(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#status */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_name(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#name */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_set_name(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#name= */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_priority(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#priority */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_set_priority(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#priority= */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_suspend(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#suspend */
|
||||
return self;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_resume(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#resume */
|
||||
return self;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_terminate(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#terminate */
|
||||
return self;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_task_join(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* TODO: Implement Task#join */
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
void
|
||||
mrb_mruby_task_gem_init(mrb_state *mrb)
|
||||
{
|
||||
struct RClass *task_class;
|
||||
|
||||
task_class = mrb_define_class(mrb, "Task", mrb->object_class);
|
||||
MRB_SET_INSTANCE_TT(task_class, MRB_TT_DATA);
|
||||
|
||||
/* Class methods */
|
||||
mrb_define_class_method(mrb, task_class, "new", mrb_task_s_new, MRB_ARGS_BLOCK());
|
||||
mrb_define_class_method(mrb, task_class, "current", mrb_task_s_current, MRB_ARGS_NONE());
|
||||
mrb_define_class_method(mrb, task_class, "list", mrb_task_s_list, MRB_ARGS_NONE());
|
||||
mrb_define_class_method(mrb, task_class, "pass", mrb_task_s_pass, MRB_ARGS_NONE());
|
||||
mrb_define_class_method(mrb, task_class, "stat", mrb_task_s_stat, MRB_ARGS_NONE());
|
||||
mrb_define_class_method(mrb, task_class, "get", mrb_task_s_get, MRB_ARGS_REQ(1));
|
||||
|
||||
/* Instance methods */
|
||||
mrb_define_method(mrb, task_class, "status", mrb_task_status, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, task_class, "name", mrb_task_name, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, task_class, "name=", mrb_task_set_name, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, task_class, "priority", mrb_task_priority, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, task_class, "priority=", mrb_task_set_priority, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, task_class, "suspend", mrb_task_suspend, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, task_class, "resume", mrb_task_resume, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, task_class, "terminate", mrb_task_terminate, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, task_class, "join", mrb_task_join, MRB_ARGS_NONE());
|
||||
|
||||
/* Kernel methods */
|
||||
mrb_define_method(mrb, mrb->kernel_module, "sleep", mrb_f_sleep, MRB_ARGS_OPT(1));
|
||||
mrb_define_method(mrb, mrb->kernel_module, "sleep_ms", mrb_f_sleep_ms, MRB_ARGS_REQ(1));
|
||||
}
|
||||
|
||||
void
|
||||
mrb_mruby_task_gem_final(mrb_state *mrb)
|
||||
{
|
||||
/* Cleanup if needed */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Task scheduler not enabled - provide stub */
|
||||
void
|
||||
mrb_mruby_task_gem_init(mrb_state *mrb)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
mrb_mruby_task_gem_final(mrb_state *mrb)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* MRB_USE_TASK_SCHEDULER */
|
||||
Reference in New Issue
Block a user