This repository has been archived on 2021-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
kaneton/kaneton/core/include/scheduler.h
2013-02-11 22:22:28 +01:00

286 lines
6.7 KiB
C

/*
* ---------- header ----------------------------------------------------------
*
* project kaneton
*
* license kaneton
*
* file /home/mycure/kane...kaneton/kaneton/core/include/scheduler.h
*
* created julien quintard [wed jun 6 13:44:48 2007]
* updated julien quintard [sat feb 5 16:59:18 2011]
*/
#ifndef CORE_SCHEDULER_H
#define CORE_SCHEDULER_H 1
/*
* ---------- dependencies ----------------------------------------------------
*/
#include <core/types.h>
#include <core/error.h>
#include <core/id.h>
#include <machine/machine.h>
/*
* ---------- algorithms ------------------------------------------------------
*/
/*
* the supported scheduler algorithms.
*/
#define SCHEDULER_ALGORITHM_MFQ (1 << 0)
/*
* ---------- macros ----------------------------------------------------------
*/
/*
* the scheduler state either started or stopped.
*/
#define SCHEDULER_STATE_START 1
#define SCHEDULER_STATE_STOP 2
/*
* initial value for the scheduler quantum in milliseconds.
*/
#define SCHEDULER_QUANTUM TIMER_DELAY
/*
* the number of priorities i.e the number of queues.
*/
#define SCHEDULER_NPRIORITIES 60
/*
* timeslice bounds.
*/
#define SCHEDULER_TIMESLICE_HIGH 250
#define SCHEDULER_TIMESLICE_LOW 10
/*
* the timeslice granularity.
*/
#define SCHEDULER_GRANULARITY _scheduler.quantum
/*
* scheduling priorities.
*/
#define SCHEDULER_PRIORITY_HIGH SCHEDULER_NPRIORITIES - 1
#define SCHEDULER_PRIORITY_LOW 0
/*
* ---------- macro functions -------------------------------------------------
*/
/*
* this macro-function computes the thread's high precision character
* by taking into account both the task's and thread's priorities.
*/
#define SCHEDULER_CHARACTER(_id_) \
( \
{ \
o_task* _task_; \
o_thread* _thread_; \
\
assert(thread_get((_id_), &_thread_) == ERROR_OK); \
assert(task_get(_thread_->task, &_task_) == ERROR_OK); \
\
((_task_->priority - TASK_PRIORITY_BACKGROUND_LOW) * \
(_thread_->priority - THREAD_PRIORITY_LOW)); \
} \
)
/*
* this macro-function computes the priority for a giver thread. this
* is a low precision measurement of a thread's priority which is used
* for locating the proper scheduling queue.
*
* indeed, while the character lies in a large range, it is then
* reduced within the range [SCHEDULER_PRIORITY_LOW, SCHEDULER_PRIORITY_HIGH].
*/
#define SCHEDULER_PRIORITY(_thread_) \
( \
{ \
t_priority _character_; \
\
_character_ = SCHEDULER_CHARACTER((_thread_)); \
\
SCHEDULER_PRIORITY_LOW + \
((_character_ * \
(SCHEDULER_PRIORITY_HIGH - SCHEDULER_PRIORITY_LOW)) / \
((TASK_PRIORITY_KERNEL_HIGH - TASK_PRIORITY_BACKGROUND_LOW) * \
(THREAD_PRIORITY_HIGH - THREAD_PRIORITY_LOW))); \
} \
)
/*
* this macro-function takes a number of milliseconds and turns it
* into a valid timeslice according to the scheduler quantum.
*
* for example, with a quantum of 25ms and a given number of 264 milliseconds,
* this macro-function would return 275ms, the upper rounded number.
*/
#define SCHEDULER_SCALE(_timeslice_) \
((((_timeslice_) % SCHEDULER_GRANULARITY) != 0) ? \
(((_timeslice_) + SCHEDULER_GRANULARITY) - \
(_timeslice_) % SCHEDULER_GRANULARITY) \
: (_timeslice_))
/*
* this macro-function computes the timeslice given by the kernel to a
* thread based on its character.
*
* the character basically returns task->priority * thread->priority.
*
* this number is then turned into a timeslice i.e within the timeslice
* range [SCHEDULER_TIMESLICE_LOW, SCHEDULER_TIMESLICE_HIGH].
*
* finally, the timeslice is scaled i.e rounded up in order to fit the
* scheduling unit known as the quantum.
*/
#define SCHEDULER_TIMESLICE(_thread_) \
( \
{ \
t_priority _character_; \
t_timeslice _timeslice_; \
\
_character_ = SCHEDULER_CHARACTER((_thread_)); \
\
_timeslice_ = \
SCHEDULER_TIMESLICE_LOW + \
((_character_ * \
(SCHEDULER_TIMESLICE_HIGH - SCHEDULER_TIMESLICE_LOW)) / \
((TASK_PRIORITY_KERNEL_HIGH - TASK_PRIORITY_BACKGROUND_LOW) * \
(THREAD_PRIORITY_HIGH - THREAD_PRIORITY_LOW))); \
\
SCHEDULER_SCALE(_timeslice_); \
} \
)
/*
* ---------- types -----------------------------------------------------------
*/
/*
* the scheduler object which managers thread candidates for a
* given CPU specified by _cpu_.
*
* the _thread_ attribute represents the currently scheduled thread
* which operates at the priority _priority_. this thread stil has
* _timeslice_ milliseconds of execution time before a context switch
* occurs.
*
* the _state_ attribute represents the scheduler's current state, either
* started or stopped.
*/
typedef struct
{
i_cpu cpu;
i_thread thread;
t_timeslice timeslice;
t_priority priority;
/* FIXME[code to complete] */
t_state state;
machine_data(o_scheduler);
} o_scheduler;
/*
* the scheduler manager's structure which contains the quantum _quantum_
* i.e the smaller unit of execution time, the idle thread's identifier _idle_
* and the sets of schedulers, one scheduler per CPU.
*/
typedef struct
{
t_quantum quantum;
i_thread idle;
i_set schedulers;
machine_data(m_scheduler);
} m_scheduler;
/*
* the scheduler dispatcher.
*/
typedef struct
{
t_error (*scheduler_show)(i_cpu,
mt_margin);
t_error (*scheduler_dump)(void);
t_error (*scheduler_start)(i_cpu);
t_error (*scheduler_stop)(i_cpu);
t_error (*scheduler_quantum)(t_quantum);
t_error (*scheduler_yield)(void);
t_error (*scheduler_elect)(void);
t_error (*scheduler_add)(i_thread);
t_error (*scheduler_remove)(i_thread);
t_error (*scheduler_update)(i_thread);
t_error (*scheduler_initialize)(void);
t_error (*scheduler_clean)(void);
} d_scheduler;
/*
* ---------- prototypes ------------------------------------------------------
*
* ../../core/scheduler/scheduler-mfq.c
*/
/*
* ../../core/scheduler/scheduler-mfq.c
*/
t_error scheduler_start(i_cpu id);
t_error scheduler_stop(i_cpu id);
t_error scheduler_quantum(t_quantum quantum);
t_error scheduler_yield(void);
t_error scheduler_elect(void);
t_error scheduler_add(i_thread id);
t_error scheduler_remove(i_thread id);
t_error scheduler_update(i_thread id);
t_error scheduler_exist(i_cpu id);
t_error scheduler_get(i_cpu id,
o_scheduler** object);
t_error scheduler_current(o_scheduler** scheduler);
t_error scheduler_initialize(void);
t_error scheduler_clean(void);
/*
* eop
*/
#endif