Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 220 → Rev 221

/shark/trunk/ports/first/first-sync.c
0,0 → 1,196
//=====================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) contract management
// S.Ha.R.K. Implementation
//=====================================================================
 
#include "fsf_contract.h"
 
#include "cbsstar.h"
#include "posixstar.h"
#include "edfstar.h"
 
#include <stdlib.h>
 
//#define FSF_DEBUG
 
extern int cbsstar_level;
 
int
fsf_create_synchobject(fsf_synch_object_handle_t *synch_handle)
{
if (!synch_handle) return FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE;
 
iq_init(&synch_handle->threads, NULL, 0);
synch_handle->events = 0;
 
return 0;
 
}
 
int
fsf_signal_synchobject(fsf_synch_object_handle_t *synch_handle)
{
 
PID p;
 
if (!synch_handle) return FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE;
if ((p = iq_getfirst(&synch_handle->threads)) != NIL)
task_activate(p);
else
synch_handle->events++;
 
return 0;
 
}
 
int
fsf_destroy_synchobject(fsf_synch_object_handle_t *synch_handle)
{
 
if (!synch_handle) return FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE;
 
while (iq_getfirst(&synch_handle->threads) != NIL);
synch_handle->events = 0;
 
return 0;
 
}
 
int fsf_schedule_next_timed_job
(const struct timespec *at_absolute_time,
struct timespec *next_budget,
struct timespec *next_period,
bool *was_deadline_missed,
bool *was_budget_overran)
{
 
TIME T,Q;
int budget, local_scheduler_level, scheduler_id;
 
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_pid(cbsstar_level, exec_shadow);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_pid(cbsstar_level, exec_shadow);
 
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
budget = POSIXSTAR_getbudget(local_scheduler_level, exec_shadow);
break;
case FSF_SCHEDULER_EDF:
budget = EDFSTAR_getbudget(local_scheduler_level, exec_shadow);
break;
case FSF_SCHEDULER_RM:
default:
budget = -1;
break;
}
 
if (budget == -1) return FSF_ERR_INVALID_SERVER;
 
if (next_budget != NULL && next_period != NULL) {
 
CBSSTAR_getbudgetinfo(cbsstar_level, &Q, &T, budget);
#ifdef FSF_DEBUG
kern_printf("(budget %d Q=%d T=%d)",budget,(int)Q,(int)T);
#endif
 
next_budget->tv_sec = Q / 1000000;
next_budget->tv_nsec = (Q % 1000000) * 1000;
next_period->tv_sec = T / 1000000;
next_period->tv_nsec = (T % 1000000) * 1000;
 
}
 
if (was_deadline_missed != NULL) *was_deadline_missed = false;
if (was_budget_overran != NULL)
*was_budget_overran = (bool)CBSSTAR_was_budget_overran(cbsstar_level,budget);
 
if (at_absolute_time != NULL)
kern_event_post(at_absolute_time, (void (*)(void *))&task_activate, (void *)(exec_shadow));
 
#ifdef FSF_DEBUG
if (at_absolute_time != NULL)
kern_printf("(Next act s%d:us%d)",(int)at_absolute_time->tv_sec,(int)at_absolute_time->tv_nsec/1000);
else
kern_printf("(End Cycle %d)",exec_shadow);
#endif
 
task_endcycle();
 
return 0;
 
}
 
int
fsf_schedule_next_event_triggered_job
(fsf_synch_object_handle_t *synch_handle,
struct timespec *next_budget,
struct timespec *next_period,
bool *was_deadline_missed,
bool *was_budget_overran)
{
 
TIME T,Q;
int budget, local_scheduler_level, scheduler_id;
 
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_pid(cbsstar_level, exec_shadow);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_pid(cbsstar_level, exec_shadow);
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
budget = POSIXSTAR_getbudget(local_scheduler_level, exec_shadow);
break;
case FSF_SCHEDULER_EDF:
budget = EDFSTAR_getbudget(local_scheduler_level, exec_shadow);
break;
case FSF_SCHEDULER_RM:
default:
budget = -1;
break;
}
 
if (budget == -1) return FSF_ERR_INVALID_SERVER;
 
if (next_budget != NULL && next_period != NULL) {
 
CBSSTAR_getbudgetinfo(cbsstar_level, &Q, &T, budget);
#ifdef FSF_DEBUG
kern_printf("(budget %d Q=%d T=%d)",budget,(int)Q,(int)T);
#endif
 
next_budget->tv_sec = Q / 1000000;
next_budget->tv_nsec = (Q % 1000000) * 1000;
next_period->tv_sec = T / 1000000;
next_period->tv_nsec = (T % 1000000) * 1000;
 
}
 
if (was_deadline_missed != NULL) *was_deadline_missed = false;
if (was_budget_overran != NULL)
*was_budget_overran = (bool)CBSSTAR_was_budget_overran(cbsstar_level,budget);
 
if (synch_handle->events > 0) {
task_activate(exec_shadow);
synch_handle->events--;
} else
iq_insertlast(exec_shadow,&synch_handle->threads);
 
#ifdef FSF_DEBUG
kern_printf("(Synch_Handle Events %d)",synch_handle->events);
#endif
 
task_endcycle();
 
return 0;
 
}
/shark/trunk/ports/first/include/fsf_contract.h
0,0 → 1,558
//====================================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) contract management
// S.Ha.R.K. Implementation
//=====================================================================
 
#include <time.h>
#include <sys/boolean.h>
#include <sys/types.h>
 
#include "fsf_configuration_parameters.h"
#include "fsf_opaque_types.h"
 
#ifndef _FSF_CONTRACT_H_
#define _FSF_CONTRACT_H_
 
//////////////////////////////////////////////////////////////////
// BASIC TYPES AND CONSTANTS
//////////////////////////////////////////////////////////////////
 
typedef enum {FSF_BOUNDED, FSF_INDETERMINATE} fsf_workload_t;
 
typedef enum {FSF_CONTINUOUS, FSF_DISCRETE} fsf_granularity_t;
typedef struct {
struct timespec budget; // Execution time
struct timespec period; // Period
} fsf_utilization_value_t;
 
typedef struct {
int size; // = 0
fsf_utilization_value_t unit[FSF_MAX_N_UTILIZATION_VALUES];
} fsf_utilization_set_t;
 
typedef unsigned long fsf_preemption_level_t; // range 1..2**32-1
 
typedef struct {
struct timespec wcet; // Execution time
fsf_preemption_level_t plevel; // Preemption_Level, range 1..2**32-1
} fsf_critical_section_data_t;
 
typedef struct {
int size; // = 0
fsf_critical_section_data_t section[FSF_MAX_N_CRITICAL_SECTIONS];
} fsf_critical_sections_t;
 
typedef int fsf_scheduler_id_t;
 
#define FSF_SCHEDULER_POSIX 0
#define FSF_SCHEDULER_EDF 1
#define FSF_SCHEDULER_RM 2
 
// Constants for assigning default values
#define FSF_DEFAULT_WORKLOAD FSF_INDETERMINATE
#define FSF_DEFAULT_GRANULARITY FSF_CONTINUOUS
#define FSF_DEFAULT_QUALITY 0
#define FSF_DEFAULT_IMPORTANCE 1
#define FSF_DEFAULT_D_EQUALS_T false
#define FSF_DEFAULT_DEADLINE {0,0}
#define FSF_DEFAULT_SCHEDULER FSF_SCHEDULER_POSIX
 
// Constants for omitting the assignment of values to specific arguments
// in calls to initialization functions
#define FSF_NULL_CRITICAL_SECTIONS (fsf_critical_sections_t *)NULL
#define FSF_NULL_UTILIZATION_SET (fsf_utilization_set_t *)NULL
#define FSF_NULL_DEADLINE (struct timespec *)NULL
#define FSF_NULL_SIGNAL 0
 
 
// Error codes
#define FSF_ERR_NOT_INITIALIZED 2003001
#define FSF_ERR_TOO_MANY_TASKS 2003002
#define FSF_ERR_ALREADY_INITIALIZED 2003003
#define FSF_ERR_BAD_ARGUMENT 2003004
#define FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE 2003005
#define FSF_ERR_NO_RENEGOTIATION_REQUESTED 2003006
#define FSF_ERR_CONTRACT_REJECTED 2003007
#define FSF_ERR_TOO_MANY_SERVERS 2003008
#define FSF_ERR_BIND_THREAD 2003009
#define FSF_ERR_UNBIND_THREAD 2003010
#define FSF_ERR_CREATE_THREAD 2003011
#define FSF_ERR_SERVER_USED 2003012
#define FSF_ERR_INVALID_SERVER 2003013
#define FSF_ERR_CREATE_SERVER 2003014
 
//////////////////////////////////////////////////////////////
// CONTRACT PARAMETERS
//////////////////////////////////////////////////////////////
 
// Contract parameters type; it is an opaque type
typedef FSF_CONTRACT_PARAMETERS_T_OPAQUE fsf_contract_parameters_t;
 
int
fsf_initialize_contract(fsf_contract_parameters_t *contract);
 
//Description: The operation receives a pointer to a contract parameters
//object and initializes it, setting it to the default values.
// budget_min => {0,0};
// period_max => {0,0};
// budget_max => {0,0};
// period_min => {0,0};
// workload => DEFAULT_WORKLOAD;
// d_equals_t => DEFAULT_D_EQUALS_T; (false or true)
// deadline => DEFAULT_DEADLINE;
// budget_overrun_sig_notify => 0; (signal number)
// budget_overrun_sig_value => {0, NULL};
// deadline_miss_sig_notify => 0; (signal number)
// deadline_miss_sig_value => {0, NULL};
//
// granularity => DEFAULT_GRANULARITY;
// utilization_set; => size = 0
// quality => DEFAULT_QUALITY; (range 0..100)
// importance => DEFAULT_IMPORTANCE; (range 1..5)
//
// preemption_level => 0; (range 1..2**32-1)
// critical_sections; => size = 0
int
fsf_set_contract_basic_parameters
(fsf_contract_parameters_t *contract,
const struct timespec *budget_min,
const struct timespec *period_max,
const struct timespec *budget_max,
const struct timespec *period_min,
fsf_workload_t workload);
 
//Description: The operation updates the specified contract parameters
//object by setting its budget, period, and workload to the specified
//input parameters. (Note: the workload is a basic parameter because
//bounded tasks are triggered by the scheduler (see the Timed Schedule
//Next Job operation, later), while indeterminate tasks are not;
//therefore, their programming model is quite different).
 
int
fsf_get_contract_basic_parameters
(const fsf_contract_parameters_t *contract,
struct timespec *budget_min,
struct timespec *period_max,
struct timespec *budget_max,
struct timespec *period_min,
fsf_workload_t *workload);
 
//Description: This operation obtains from the specified contract parameters
//object its budget, period, and workload, and copies them to the places
//pointed to by the corresponding input parameters.
 
int
fsf_set_contract_timing_requirements
(fsf_contract_parameters_t *contract,
bool d_equals_t,
const struct timespec *deadline,
int budget_overrun_sig_notify,
union sigval budget_overrun_sig_value,
int deadline_miss_sig_notify,
union sigval deadline_miss_sig_value);
 
//Description: The operation updates the specified contract parameters
//object. d_equals_t is used as a boolean, deadline must be
//NULL_DEADLINE if d_equals_t is true, budget_overrun_sig_notify or
//deadline_miss_sig_notify may be NULL_SIGNAL (no notification) or any
//posix signal. budget_overrun_sig_value and deadline_miss_sig_value
//are the values to be delivered with the signal.
 
int
fsf_get_contract_timing_requirements
(const fsf_contract_parameters_t *contract,
bool *d_equals_t,
struct timespec *deadline,
int *budget_overrun_sig_notify,
union sigval *budget_overrun_sig_value,
int *deadline_miss_sig_notify,
union sigval *deadline_miss_sig_value);
 
//Description: The operation obtains the corresponding input
//parameters from the specified contract parameters object. If
//d_equals_t is true, the deadline will not be updated.
 
int
fsf_set_contract_reclamation_parameters
(fsf_contract_parameters_t *contract,
fsf_granularity_t granularity,
const fsf_utilization_set_t *utilization_set,
int quality,
int importance);
 
//Description: The operation updates the specified contract parameters
//object by setting its granularity, utilization set, quality, and
//importance to the specified input parameters.
 
int
fsf_get_contract_reclamation_parameters
(const fsf_contract_parameters_t *contract,
fsf_granularity_t *granularity,
fsf_utilization_set_t *utilization_set,
int *quality,
int *importance);
 
//Description: The operation obtains from the specified contract parameters
//object its granularity, utilization set, quality, and importance. Then
//copies them to the places pointed to by the specified input parameters.
//Only the utilization_values of the utilization_set that are in use, are
//copied (according to its size field).
 
int
fsf_set_contract_synchronization_parameters
(fsf_contract_parameters_t *contract,
fsf_preemption_level_t preemption_level,
const fsf_critical_sections_t *critical_sections);
 
//Description: The operation updates the specified contract parameters
//object by setting its preemption level and critical sections to the
//specified input parameters.
 
int
fsf_get_contract_synchronization_parameters
(const fsf_contract_parameters_t *contract,
fsf_preemption_level_t *preemption_level,
fsf_critical_sections_t *critical_sections);
 
//Description: The operation obtains from the specified contract
//parameters object its preemption level and critical sections, and
//copies them to the places pointed to by the specified input
//parameters. Only those critical_section_data records that are in use
//in the critical_sections structure are copied (according to its size
//field).
 
int
fsf_set_local_scheduler_parameter
(fsf_contract_parameters_t *contract,
fsf_scheduler_id_t local_scheduler_id);
 
int
fsf_get_local_scheduler_parameter
(const fsf_contract_parameters_t *contract,
fsf_scheduler_id_t *local_scheduler_id);
 
//////////////////////////////////////////////////////////////
// SYNCHRONIZATION OBJECTS
//////////////////////////////////////////////////////////////
 
//An abstract synchronization object is defined by the application.
//This object can be used by an application to wait for an event to
//arrive by invoking the Event Triggered Schedule Next Job operation.
//It can also be used to signal the event either causing a waiting
//server to wake up, or the event to be queued if no server is waiting
//for it. It is defined by the following opaque type and has the
//following operations:
 
typedef FSF_SYNCH_OBJECT_HANDLE_T_OPAQUE fsf_synch_object_handle_t;
int
fsf_create_synchobject(fsf_synch_object_handle_t *synch_handle);
 
//Description: This operation creates and initializes a
//synchronization object variable managed by the scheduler, and
//returns a handle to it in the variable pointed to by synch_handle.
int
fsf_signal_synchobject(fsf_synch_object_handle_t *synch_handle);
 
//Description: If one or more servers are waiting upon the specified
//synchronization object one of them is awakened; if not, the event is
//queued at the synchronization object.
 
int
fsf_destroy_synchobject(fsf_synch_object_handle_t *synch_handle);
 
//This operation destroys the synchronization object (created by a
//previous call to fsf_create_synchobject) that is referenced by the
//synch_handle variable. After calling this operation, the
//synch_handle variable can not be used until it is initialized again
//by a call to fsf_create_synchobject.
 
 
///////////////////////////////////////////////////////////////
// CONTRACT NEGOCIATION OPERATIONS
///////////////////////////////////////////////////////////////
 
// Server Id type, that identifies a server created to manage a
// given contract
 
typedef int fsf_server_id_t;
 
// The following type references a function that may become
// a thread's code
 
typedef void * (*fsf_thread_code_t) (void *);
 
// Negotiate contract functions: The following functions are used to
// create servers for a contract parameters specification and also to
// assign one or more threads to a server (Note: the current
// implementation only supports one thread per server; this limitation
// will be removed in the next phase of the project)
 
// The first time that any of these operations is called, it creates
// all the internal management structures that are necessary for the
// FIRST Scheduling Framework to operate properly.
 
int
fsf_negotiate_contract
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server);
 
//Description: The operation negotiates a contract for a new
//server. If the on-line admission test is enabled it determines
//whether the contract can be admitted or not based on the current
//contracts established in the system. Then it creates the server and
//recalculates all necessary parameters for the contracts already
//present in the system. This is a potentially blocking operation; it
//returns when the system has either rejected the contract, or
//admitted it and made it effective. It returns zero and places the
//server identification number in the location pointed to by the
//server input parameter if accepted, or an error if rejected. No
//thread is bound to the newly created server, which will be idle
//until a thread is bound to it. This operation can only be executed
//by threads that are already bound to an active server and therefore
//are being scheduled by the fsf scheduler.
 
int
fsf_negotiate_contract_for_new_thread
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server,
pthread_t *thread,
pthread_attr_t *attr,
fsf_thread_code_t thread_code,
void *arg,
void *rt_arg);
 
//Description: This operation negotiates a contract for a new server,
//creates a thread and binds it to the server. If the contract is
//accepted, the operation creates a thread with the arguments thread,
//attr, thread_code and arg as they are defined for the
//pthread_create() POSIX function call, and attaches it to the fsf
//scheduler. Then, it binds the created thread to the new server. It
//returns zero and puts the server identification number in the
//location pointed to by the server input parameter. The attr
//parameter is overwritten as necessary to introduce the adequate
//scheduling policy and priority, according to the preemption level
//given in the contract and the fsf_priority_map() function defined by
//the user. If the contract is rejected, the thread is not created and
//the corresponding error is returned.
 
int
fsf_negotiate_contract_for_myself
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server,
void *rt_arg);
 
//Description: This operation negotiates a contract for a new
//server, and binds the calling thread to it. If the contract is
//accepted it returns zero and copies the server identification
//number in the location pointed to by the server input parameter.
//If it is rejected, an error is returned.
 
//Implementation dependent issue: In order to allow the usage of
//application defined schedulers, the calling thread must not have the
//SCHED_APP scheduling policy and at the same time be attached to an
//application scheduler different than the fsf scheduler; in such case,
//an error is returned. After a successful call the calling thread
//will have the SCHED_APP scheduling policy and will be attached to
//the fsf scheduler.
 
int
fsf_bind_thread_to_server
(fsf_server_id_t server,
pthread_t thread,
void *rt_arg);
 
//Description: This operation associates a thread with a server, which
//means that it starts consuming the server's budget and is executed
//according to the contract established for that server. If the thread
//is already bound to another server, it is effectively unbound from
//it and bound to the specified one.
 
//Implementation dependent issue: In order to allow the usage of
//application defined schedulers, the given thread must not have the
//scheduling policy SCHED_APP and at the same time be attached to an
//application scheduler different than the fsf scheduler.
 
//FIRST project development issue: In this phase of the project, only
//one thread is allowed to be bound to a server, sharing a server by
//multiple threads is planned to be allowed in the next phase of
//the project.
 
int
fsf_unbind_thread_from_server (pthread_t thread);
 
//Description: This operation unbinds a thread from a server.
//Since threads with no server associated are not allow to execute,
//they remain in a dormant state until they are either eliminated or
//bound again.
 
//Implementation dependent issue: in the implementation with an
//application scheduler, the thread is still attached to the fsf
//scheduler, but suspended.
 
int
fsf_get_server
(fsf_server_id_t *server,
pthread_t thread);
 
//Description: This operation returns the server associated with a
//thread. It returns an error if the thread does not exist, it is not
//under the control of the scheduling framework, or is not bound.
 
int
fsf_cancel_contract (fsf_server_id_t *server);
 
//Description: The operation eliminates the specified server and
//recalculates all necessary parameters for the contracts remaining in
//the system. This is a potentially blocking operation; it returns when
//the system has made the changes effective.
 
int
fsf_renegotiate_contract
(const fsf_contract_parameters_t *new_contract,
fsf_server_id_t server);
 
//Description: The operation renegotiates a contract for an existing
//server. If the on-line admission test is enabled it determines
//whether the contract can be admitted or not based on the current
//contracts established in the system. If it cannot be admitted, the
//old contract remains in effect and an error is returned. If it can
//be admitted, it recalculates all necessary parameters for the
//contracts already present in the system anr returns zero. This is a
//potentially blocking operation; it returns when the system has
//either rejected the new contract, or admitted it and made it
//effective.
 
int
fsf_request_contract_renegotiation
(const fsf_contract_parameters_t *new_contract,
fsf_server_id_t server,
int sig_notify,
union sigval sig_value);
 
//Description: The operation enqueues a renegotiate operation for an
//existing server, and returns immediately. The renegotiate operation
//is performed asynchronously, as soon as it is practical; meanwhile
//the system operation will continue normally. When the renegotiation
//is made, if the on-line admission test is enabled it determines
//whether the contract can be admitted or not based on the current
//contracts established in the system. If it cannot be admitted, the
//old contract remains in effect. If it can be admitted, it
//recalculates all necessary parameters for the contracts already
//present in the system. When the operation is completed, notification
//is made to the caller, if requested, via a signal. The status of the
//operation (in progress, admitted, rejected) can be checked with the
//get_renegotiation_status operation. The argument sig_notify can be
//NULL_SIGNAL (no notification), or any posix signal; and in this case
//sig_value is to be sent with the signal.
 
typedef enum {FSF_IN_PROGRESS,
FSF_REJECTED,
FSF_ADMITTED} fsf_renegotiation_status_t;
 
int
fsf_get_renegotiation_status
(fsf_server_id_t server,
fsf_renegotiation_status_t *renegotiation_status);
 
//Description: The operation reports on the status of the last
//renegotiation operation enqueued for the specified server. It is
//callable even after notification of the completion of such operation,
//if requested.
 
int
fsf_request_change_quality_and_importance
(fsf_server_id_t server,
int new_importance,
int new_quality);
 
//Description: The operation enqueues a request to change the quality and
//importance parameters of the specified server, and returns immediately.
//The change operation is performed as soon as it is practical;
//meanwhile the system operation will continue normally.
 
 
////////////////////////////////////////////////////////////
// SCHEDULING BOUNDED WORKLOADS
////////////////////////////////////////////////////////////
 
int
fsf_schedule_next_timed_job
(const struct timespec *at_absolute_time,
struct timespec *next_budget,
struct timespec *next_period,
bool *was_deadline_missed,
bool *was_budget_overran);
 
//Description: This operation is invoked by threads associated with
//bounded workload servers to indicate that a job has been completed
//(and that the scheduler may reassign the unused capacity of the
//current job to other servers), and also when the first job require
//to be scheduled. The system will activate the job at the specified
//absolute time, and will then use the scheduling rules to determine
//when the job can run, at which time the call returns. Upon return,
//the system reports the current period and budget for the current
//job, whether the deadline of the previous job was missed or not,
//and whether the budget of the previous job was overrun or not.
 
 
int
fsf_schedule_next_event_triggered_job
(fsf_synch_object_handle_t *synch_handle,
struct timespec *next_budget,
struct timespec *next_period,
bool *was_deadline_missed,
bool *was_budget_overran);
 
//Description: This operation is invoked by threads associated with
//bounded workload servers to indicate that a job has been completed
//(and that the scheduler may reassign the unused capacity of the
//current job to other servers), and also when the first job require
//to be scheduled. If the specified synchronization object has events
//queued, one of them is dequeued; otherwise the server will wait upon
//the specified synchronization object until it is signalled. Then, the
//system will use the scheduling rules to determine when the job can run
//and the call will return at that time. Upon return, the system reports
//the current period and budget for the current job, whether the deadline
//of the previous job was missed or not, and whether the budget of the
//previous job was overrun or not.
 
 
//////////////////////////////////////////////////////////////
// OBTAINING INFORMATION FROM THE SCHEDULER
//////////////////////////////////////////////////////////////
 
int
fsf_get_available_capacity (fsf_server_id_t server, float *capacity);
 
//Description: This operation returns the current spare capacity (in
//percentage of processor or network utilization), currently assigned
//to the importance level of the specified server.
 
int
fsf_get_total_quality (fsf_server_id_t server, int *total_quality);
//Description: This operation returns the sum of the quality parameters
//for all servers in the system of importance level equal to that of
//the specified server.
 
int
fsf_is_admission_test_enabled();
//Description: Returns true if the system is configured with the
//on-line admission test enabled, or false otherwise.
 
 
#endif // _FSF_CONTRACT_H_
/shark/trunk/ports/first/include/fsf_opaque_types.h
0,0 → 1,75
//=======================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) contract management opaque types
// S.Ha.R.K. Implementation
//=======================================================================
// Implementation dependent definitions
 
#ifndef _FSF_OPAQUE_TYPES_H_
#define _FSF_OPAQUE_TYPES_H_
 
#include <kernel/iqueue.h>
 
#define FSF_CONTRACT_PARAMETERS_T_OPAQUE struct { \
\
struct timespec budget_min; \
struct timespec period_max; \
struct timespec budget_max; \
struct timespec period_min; \
fsf_workload_t workload; \
\
fsf_scheduler_id_t local_scheduler_id; \
\
bool d_equals_t; \
struct timespec deadline; \
int budget_overrun_sig_notify; \
union sigval budget_overrun_sig_value; \
int deadline_miss_sig_notify; \
union sigval deadline_miss_sig_value; \
\
fsf_granularity_t granularity; \
fsf_utilization_set_t utilization_set; \
int quality; \
int importance; \
\
fsf_preemption_level_t preemption_level; \
fsf_critical_sections_t critical_sections; \
\
}
 
//Default values for fsf_contract_parameters_t:
// budget_min => {0,0};
// period_max => {0,0};
// budget_max => {0,0};
// period_min => {0,0};
// workload => DEFAULT_WORKLOAD;
// d_equals_t => DEFAULT_D_EQUALS_T; (false or true)
// deadline => DEFAULT_DEADLINE;
// budget_overrun_sig_notify => 0; (signal number)
// budget_overrun_sig_value => {0, NULL};
// deadline_miss_sig_notify => 0; (signal number)
// deadline_miss_sig_value => {0, NULL};
//
// granularity => DEFAULT_GRANULARITY;
// utilization_set; => size = 0
// quality => DEFAULT_QUALITY; (range 0..100)
// importance => DEFAULT_IMPORTANCE; (range 1..5)
//
// preemption_level => 0; (range 1..2**32-1)
// critical_sections; => size = 0
 
 
#define FSF_SYNCH_OBJECT_HANDLE_T_OPAQUE struct { \
IQUEUE threads; \
int events; \
}
 
#endif // _FSF_OPAQUE_TYPES_H_
/shark/trunk/ports/first/include/posixstar.h
0,0 → 1,153
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
 
/**
------------
CVS : $Id: posixstar.h,v 1.1 2003-09-10 15:56:28 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2003-09-10 15:56:28 $
------------
 
This file contains the scheduling module compatible with POSIX
specifications
 
Title:
POSIX version 1
 
Task Models Accepted:
NRT_TASK_MODEL - Non-Realtime Tasks
weight field is ignored
slice field is used to set the slice of a task, if it is !=0
policy field is ignored
inherit field is ignored
 
Description:
This module schedule his tasks following the POSIX specifications...
 
A task can be scheduled in a Round Robin way or in a FIFO way.
The tasks have also a priority field.
 
The slices can be different one task from one another.
 
The module can SAVE or SKIP activations
 
Exceptions raised:
XUNVALID_GUEST
This level doesn't support guests. When a guest operation
is called, the exception is raised.
 
Restrictions & special features:
- if specified, it creates at init time a task,
called "Main", attached to the function __init__().
- There must be only one module in the system that creates a task
attached to the function __init__().
- The level tries to guarantee that a RR task uses a "full" timeslice
before going to the queue tail. "full" means that a task can execute
a maximum time of slice+sys_tick due to the approx. done by
the Virtual Machine. If a task execute more time than the slice,
the next time it execute less...
 
**/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __POSIXSTAR_H__
#define __POSIXSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
//#define POSIXSTAR_DEBUG
 
/*+ Const: +*/
#define POSIXSTAR_MINIMUM_SLICE 1000 /*+ Minimum Timeslice +*/
#define POSIXSTAR_MAXIMUM_SLICE 500000 /*+ Maximum Timeslice +*/
 
typedef struct {
int command;
void *param;
} POSIXSTAR_command_message;
 
#define POSIXSTAR_SET_NEW_LEVEL 0
 
/*+ Registration function:
TIME slice the slice for the Round Robin queue
int createmain 1 if the level creates the main task 0 otherwise
struct multiboot_info *mb used if createmain specified
 
returns the level number at which the module has been registered.
+*/
LEVEL POSIXSTAR_register_level(int master, TIME slice, int prioritylevels);
 
int POSIXSTAR_setbudget(LEVEL l, PID p, int budget);
int POSIXSTAR_getbudget(LEVEL l, PID p);
 
int POSIXSTAR_budget_has_thread(LEVEL l, int budget);
 
/*+ this function forces the running task to go to his queue tail,
then calls the scheduler and changes the context
(it works only on the POSIX level) +*/
int POSIXSTAR_sched_yield(LEVEL l);
 
/* the following functions have to be called with interruptions DISABLED! */
 
/*+ this function returns the maximum level allowed for the POSIX level +*/
int POSIXSTAR_get_priority_max(LEVEL l);
 
/*+ this function returns the default timeslice for the POSIX level +*/
int POSIXSTAR_rr_get_interval(LEVEL l);
 
/*+ this functions returns some paramaters of a task;
policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
priority must be in the range [0..prioritylevels]
returns ENOSYS or ESRCH if there are problems +*/
int POSIXSTAR_getschedparam(LEVEL l, PID p, int *policy, int *priority);
 
/*+ this functions sets paramaters of a task +*/
int POSIXSTAR_setschedparam(LEVEL l, PID p, int policy, int priority);
 
#endif
 
/*
MANCANO
13.3.6 GETPRIORITYMin da mettere a 0
*/
/shark/trunk/ports/first/include/comm_message.h
0,0 → 1,13
#ifndef __COMMAND_MESSAGE_H__
#define __COMMAND_MESSAGE_H__
 
typedef struct {
int command;
void *param;
} STD_command_message;
 
#define STD_SET_NEW_LEVEL 0
#define STD_SET_NEW_MODEL 1
#define STD_ACTIVATE_TASK 2
 
#endif
/shark/trunk/ports/first/include/cbsstar.h
0,0 → 1,182
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
 
/*
------------
CVS : $Id: cbsstar.h,v 1.1 2003-09-10 15:56:28 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2003-09-10 15:56:28 $
------------
 
This file contains the budget support for the multiapplication
scheduling algorithm proposed in the framework of the FIRST Project
 
Title:
CBSSTAR
 
Task Models Accepted:
None!
 
Guest Models Accepted:
BUDGET_TASK_MODEL - A task that is attached to a budget
int b; --> the number of the budget which the task is attached to
 
Description:
This module schedule its tasks following the CBS scheme.
Every task is inserted using the guest calls.
The module defines a limited set of budgets that the application
can use. Every guest task will use a particular budget; FIFO
scheduling is used inside a budget to schedule more than one ready
task attached to the same budget.
 
The tasks are inserted in an EDF level (or similar) with a JOB_TASK_MODEL,
and the CBS level expects that the task is scheduled with the absolute
deadline passed in the model.
 
This module tries to implement a simplified version of the guest
task interface:
- To insert a guest task, use guest_create
- When a task is dispatched, use guest_dispatch
- When a task have to be suspended, you have to use:
-> preemption: use guest_epilogue
-> synchronization, end: use guest_end
Remember: no check is done on the budget number passed with the model!!!
 
Exceptions raised:
XUNVALID_TASK
This level doesn't support normal tasks, but just guest tasks.
When a task operation is called, an exception is raised.
 
Restrictions & special features:
- This level doesn't manage the main task.
- At init time we have to specify:
. guarantee check
(when all task are created the system will check that the task_set
will not use more than the available bandwidth)
- A function to return the used bandwidth of the level is provided.
 
- A function is provided to allocate a buffer.
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __CBSSTAR_H__
#define __CBSSTAR_H__
 
#include <kernel/kern.h>
 
//#include <ll/ll.h>
//#include <kernel/config.h>
//#include <sys/types.h>
//#include <kernel/types.h>
//#include <modules/codes.h>
 
/* -----------------------------------------------------------------------
BUDGET_TASK_MODEL: a model for guest tasks
----------------------------------------------------------------------- */
 
#define BUDGET_PCLASS 0x0600
typedef struct {
TASK_MODEL t;
int b;
} BUDGET_TASK_MODEL;
 
#define budget_task_default_model(m,buf) \
task_default_model((m).t, BUDGET_PCLASS), \
(m).b = (buf);
 
 
 
/* some constants for registering the Module in the right place */
#define CBSSTAR_LEVELNAME "CBSSTAR"
#define CBSSTAR_LEVEL_CODE 106
#define CBSSTAR_LEVEL_VERSION 1
 
typedef struct {
int command;
void *param;
} CBSSTAR_command_message;
 
typedef struct {
int budget;
TIME T,Q;
} CBSSTAR_mod_budget;
 
/* Registration function:
int N Maximum number of budgets allocated for the applications
LEVEL master the level that must be used as master level for the
CBS tasks
*/
LEVEL CBSSTAR_register_level(int n, LEVEL master);
 
/* Allocates a budget to be used for an application.
Input parameters:
Q The budget
T The period of the budget
Return value:
0..N The ID of the budget
-1 no more free budgets
-2 The budgets allocated locally to this module have bandwidth > 1
-3 wrong LEVEL id
*/
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T, LEVEL local_scheduler_level, int scheduler_id);
 
int CBSSTAR_removebudget(LEVEL l, int budget);
 
int CBSSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, int budget);
 
int CBSSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, int budget);
 
int CBSSTAR_was_budget_overran(LEVEL l, int budget);
 
int CBSSTAR_is_active(LEVEL l, int budget);
 
int CBSSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget);
 
int CBSSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p);
 
int CBSSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget);
 
int CBSSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p);
 
#endif
/shark/trunk/ports/first/include/posix.h
0,0 → 1,155
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
 
/**
------------
CVS : $Id: posix.h,v 1.1 2003-09-10 15:56:28 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2003-09-10 15:56:28 $
------------
 
This file contains the scheduling module compatible with POSIX
specifications
 
Title:
POSIX version 1
 
Task Models Accepted:
NRT_TASK_MODEL - Non-Realtime Tasks
weight field is ignored
slice field is used to set the slice of a task, if it is !=0
policy field is ignored
inherit field is ignored
 
Description:
This module schedule his tasks following the POSIX specifications...
 
A task can be scheduled in a Round Robin way or in a FIFO way.
The tasks have also a priority field.
 
The slices can be different one task from one another.
 
The module can SAVE or SKIP activations
 
Exceptions raised:
XUNVALID_GUEST
This level doesn't support guests. When a guest operation
is called, the exception is raised.
 
Restrictions & special features:
- if specified, it creates at init time a task,
called "Main", attached to the function __init__().
- There must be only one module in the system that creates a task
attached to the function __init__().
- The level tries to guarantee that a RR task uses a "full" timeslice
before going to the queue tail. "full" means that a task can execute
a maximum time of slice+sys_tick due to the approx. done by
the Virtual Machine. If a task execute more time than the slice,
the next time it execute less...
 
**/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __POSIX_H__
#define __POSIX_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
#include "ll/sys/cdefs.h"
 
__BEGIN_DECLS
 
extern TASK __init__(void *arg);
 
 
 
/*+ Const: +*/
#define POSIX_MINIMUM_SLICE 1000 /*+ Minimum Timeslice +*/
#define POSIX_MAXIMUM_SLICE 500000 /*+ Maximum Timeslice +*/
 
#define POSIX_MAIN_YES 1 /*+ The level creates the main +*/
#define POSIX_MAIN_NO 0 /*+ The level does'nt create the main +*/
 
 
/*+ Registration function:
TIME slice the slice for the Round Robin queue
int createmain 1 if the level creates the main task 0 otherwise
struct multiboot_info *mb used if createmain specified
 
returns the level number at which the module has been registered.
+*/
LEVEL POSIX_register_level(TIME slice,
int createmain,
struct multiboot_info *mb,
int prioritylevels);
 
/*+ this function forces the running task to go to his queue tail,
then calls the scheduler and changes the context
(it works only on the POSIX level) +*/
int POSIX_sched_yield(LEVEL l);
 
/* the following functions have to be called with interruptions DISABLED! */
 
/*+ this function returns the maximum level allowed for the POSIX level +*/
int POSIX_get_priority_max(LEVEL l);
 
/*+ this function returns the default timeslice for the POSIX level +*/
int POSIX_rr_get_interval(LEVEL l);
 
/*+ this functions returns some paramaters of a task;
policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
priority must be in the range [0..prioritylevels]
returns ENOSYS or ESRCH if there are problems +*/
int POSIX_getschedparam(LEVEL l, PID p, int *policy, int *priority);
 
/*+ this functions sets paramaters of a task +*/
int POSIX_setschedparam(LEVEL l, PID p, int policy, int priority);
 
__END_DECLS
#endif
 
/*
MANCANO
13.3.6 GETPRIORITYMin da mettere a 0
*/
/shark/trunk/ports/first/include/edfstar.h
0,0 → 1,145
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: edfstar.h,v 1.1 2003-09-10 15:56:28 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2003-09-10 15:56:28 $
------------
 
Title:
EDFSTAR
 
Task Models Accepted:
HARD_TASK_MODEL - Hard Tasks (only Periodic)
wcet field and mit field must be != 0. They are used to set the wcet
and period of the tasks.
periodicity field can be only PERIODIC
drel field is ignored
Guest Models Accepted:
JOB_TASK_MODEL - a single guest task activation
Identified by an absolute deadline and a period.
period field is ignored
 
Description:
 
This module schedule his tasks following the classic EDF
scheme. This module is derived from the EDFACT Scheduling Module.
 
This module can not stay alone: when it have to schedule a task, it
simply inserts it into another master module using a
BUDGET_TASK_MODEL.
 
No Task guarantee is performed at all.
The tasks scheduled are only periodic.
All the task are put in a queue and the scheduling is based on the
deadline value.
If a task miss a deadline a counter is incremented.
If a task exausts the wcet a counter is incremented
No ZOMBIE support!!!!!!
 
Exceptions raised:
XUNVALID_GUEST XUNVALID_TASK
some primitives are not implemented:
task_sleep, task_delay, guest_endcycle, guest_sleep, guest_delay
 
XACTIVATION
If a task is actiated through task_activate or guest_activate more than
one time
Restrictions & special features:
- This level doesn't manage the main task.
- Functions to return and reset the nact, wcet and dline miss
counters are provided
 
**/
 
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#ifndef __EDFSTAR_H__
#define __EDFSTAR_H__
 
#include <ll/ll.h>
#include <kernel/config.h>
#include <sys/types.h>
#include <kernel/types.h>
 
 
typedef struct {
int command;
void *param;
} EDFSTAR_command_message;
 
/* flags... */
#define EDFSTAR_ENABLE_GUARANTEE 1 /* Task Guarantee enabled */
#define EDFSTAR_ENABLE_ALL 1
 
#define EDFSTAR_FAILED_GUARANTEE 8 /* used in the module, unsettabl
in EDF_register_level... */
 
 
 
#define EDFSTAR_LEVELNAME "EDFSTAR base"
#define EDFSTAR_LEVEL_CODE 166
#define EDFSTAR_LEVEL_VERSION 1
 
 
/* Registration function:
int budget The budget used by this module (see CBSSTAR.h)
int master The master module used by EDFSTAR
*/
LEVEL EDFSTAR_register_level(int master);
 
/* returns respectively the number of dline, wcet or nact; -1 if error */
int EDFSTAR_get_dline_miss(PID p);
int EDFSTAR_get_wcet_miss(PID p);
int EDFSTAR_get_nact(PID p);
 
/* resets respectively the number of dline, wcet miss; -1 if error */
int EDFSTAR_reset_dline_miss(PID p);
int EDFSTAR_reset_wcet_miss(PID p);
 
int EDFSTAR_getbudget(LEVEL l, PID p);
int EDFSTAR_setbudget(LEVEL l, PID p, int budget);
 
#endif
 
/shark/trunk/ports/first/include/fsf_configuration_parameters.h
0,0 → 1,47
//=======================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) configuration parameters
// S.Ha.R.K. Implementation
//=======================================================================
 
///////////////////////////////////////////////////////////////////
// Definitions required to configure the fsf scheduling algorithms.
 
#include <sys/boolean.h>
 
#ifndef _FSF_CONFIGURATION_PARAMETERS_H_
#define _FSF_CONFIGURATION_PARAMETERS_H_
 
 
// This symbol specifies whether the scheduler will make a
// schedulability of the requested contract or not
#define FSF_ADMISSION_TEST_IS_ENABLED false
 
 
// Tune these values for optimizing the amount of memory used by
// the implementation
 
// Maximum number of accepted contracts (servers)
#define FSF_MAX_N_SERVERS 10
 
// Maximum number of threads that may be scheduled by the framework
#define FSF_MAX_N_THREADS 10
 
// Maximum number of critical sections that can be stored in a
// contract parameters object
#define FSF_MAX_N_CRITICAL_SECTIONS 10
 
// Maximum number of utilization values (pairs of budget and period)
// that can be stored in a contract parameters object
#define FSF_MAX_N_UTILIZATION_VALUES 5
 
#define FSF_MAX_N_BIND_THREAD 1
 
#endif
/shark/trunk/ports/first/first-contract.c
0,0 → 1,254
//=====================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) contract management
// S.Ha.R.K. Implementation
//=====================================================================
 
#include "fsf_contract.h"
 
int fsf_initialize_contract
(fsf_contract_parameters_t *contract)
{
struct timespec default_deadline = FSF_DEFAULT_DEADLINE;
 
/* Check */
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
/* Set to default value */
NULL_TIMESPEC(&contract->budget_min);
NULL_TIMESPEC(&contract->budget_max);
NULL_TIMESPEC(&contract->period_min);
NULL_TIMESPEC(&contract->period_max);
 
contract->workload = FSF_DEFAULT_WORKLOAD;
 
contract->local_scheduler_id = FSF_DEFAULT_SCHEDULER;
 
contract->d_equals_t = FSF_DEFAULT_D_EQUALS_T;
 
TIMESPEC_ASSIGN(&contract->deadline,&default_deadline);
 
contract->budget_overrun_sig_notify = 0;
memset(&contract->budget_overrun_sig_value,0,sizeof(union sigval));
 
contract->deadline_miss_sig_notify = 0;
memset(&contract->deadline_miss_sig_value,0,sizeof(union sigval));
 
contract->granularity = FSF_DEFAULT_GRANULARITY;
contract->utilization_set.size = 0;
contract->quality = FSF_DEFAULT_QUALITY;
contract->importance = FSF_DEFAULT_IMPORTANCE;
 
contract->preemption_level = 0;
contract->critical_sections.size = 0;
return 0;
 
}
int fsf_set_contract_basic_parameters
(fsf_contract_parameters_t *contract,
const struct timespec *budget_min,
const struct timespec *period_max,
const struct timespec *budget_max,
const struct timespec *period_min,
fsf_workload_t workload)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
if (budget_min) TIMESPEC_ASSIGN(&contract->budget_min,budget_min);
if (period_max) TIMESPEC_ASSIGN(&contract->period_max,period_max);
if (budget_max) TIMESPEC_ASSIGN(&contract->budget_max,budget_max);
if (period_min) TIMESPEC_ASSIGN(&contract->period_min,period_min);
 
contract->workload = workload;
 
return 0;
}
 
int fsf_get_contract_basic_parameters
(const fsf_contract_parameters_t *contract,
struct timespec *budget_min,
struct timespec *period_max,
struct timespec *budget_max,
struct timespec *period_min,
fsf_workload_t *workload)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
TIMESPEC_ASSIGN(budget_min,&contract->budget_min);
TIMESPEC_ASSIGN(period_max,&contract->period_max);
TIMESPEC_ASSIGN(budget_max,&contract->budget_max);
TIMESPEC_ASSIGN(period_min,&contract->period_min);
 
*workload = contract->workload;
 
return 0;
 
}
 
int fsf_set_contract_timing_requirements
(fsf_contract_parameters_t *contract,
bool d_equals_t,
const struct timespec *deadline,
int budget_overrun_sig_notify,
union sigval budget_overrun_sig_value,
int deadline_miss_sig_notify,
union sigval deadline_miss_sig_value)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
contract->d_equals_t = d_equals_t;
 
if (deadline) TIMESPEC_ASSIGN(&contract->deadline,deadline);
 
contract->budget_overrun_sig_notify = budget_overrun_sig_notify;
contract->budget_overrun_sig_value = budget_overrun_sig_value;
contract->deadline_miss_sig_notify = deadline_miss_sig_notify;
contract->deadline_miss_sig_value = deadline_miss_sig_value;
 
return 0;
 
}
 
int fsf_get_contract_timing_requirements
(const fsf_contract_parameters_t *contract,
bool *d_equals_t,
struct timespec *deadline,
int *budget_overrun_sig_notify,
union sigval *budget_overrun_sig_value,
int *deadline_miss_sig_notify,
union sigval *deadline_miss_sig_value)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
*d_equals_t = contract->d_equals_t;
TIMESPEC_ASSIGN(deadline,&contract->deadline);
*budget_overrun_sig_notify = contract->budget_overrun_sig_notify;
*budget_overrun_sig_value = contract->budget_overrun_sig_value;
*deadline_miss_sig_notify = contract->deadline_miss_sig_notify;
*deadline_miss_sig_value = contract->deadline_miss_sig_value;
 
return 0;
 
}
 
int fsf_set_contract_reclamation_parameters
(fsf_contract_parameters_t *contract,
fsf_granularity_t granularity,
const fsf_utilization_set_t *utilization_set,
int quality,
int importance)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
contract->granularity = granularity;
 
if (utilization_set) memcpy(&contract->utilization_set,utilization_set,sizeof(fsf_utilization_set_t));
contract->quality = quality;
contract->importance = importance;
 
return 0;
 
}
int fsf_get_contract_reclamation_parameters
(const fsf_contract_parameters_t *contract,
fsf_granularity_t *granularity,
fsf_utilization_set_t *utilization_set,
int *quality,
int *importance)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
*granularity = contract->granularity;
memcpy(utilization_set,&contract->utilization_set,sizeof(fsf_utilization_set_t));
*quality = contract->quality;
*importance = contract->importance;
return 0;
 
}
 
int fsf_set_contract_synchronization_parameters
(fsf_contract_parameters_t *contract,
fsf_preemption_level_t preemption_level,
const fsf_critical_sections_t *critical_sections)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
contract->preemption_level = preemption_level;
 
if (critical_sections) memcpy(&contract->critical_sections,critical_sections,sizeof(fsf_critical_sections_t));
 
return 0;
 
}
int
fsf_get_contract_synchronization_parameters
(const fsf_contract_parameters_t *contract,
fsf_preemption_level_t *preemption_level,
fsf_critical_sections_t *critical_sections)
{
if (!contract) return FSF_ERR_NOT_INITIALIZED;
*preemption_level = contract->preemption_level;
memcpy(critical_sections,&contract->critical_sections,sizeof(fsf_critical_sections_t));
return 0;
 
}
 
int
fsf_set_local_scheduler_parameter
(fsf_contract_parameters_t *contract,
fsf_scheduler_id_t local_scheduler_id)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
contract->local_scheduler_id = local_scheduler_id;
 
return 0;
 
}
 
int
fsf_get_local_scheduler_parameter
(const fsf_contract_parameters_t *contract,
fsf_scheduler_id_t *local_scheduler_id)
{
 
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
*local_scheduler_id = contract->local_scheduler_id;
 
return 0;
 
}
 
 
 
/shark/trunk/ports/first/modules/cbsstar.c
0,0 → 1,688
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
* Copyright (C) 2002 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "cbsstar.h"
 
/*
* DEBUG stuffs begin
*/
//#define CBSSTAR_DEBUG
#ifdef CBSSTAR_DEBUG
 
static __inline__ void fake_printf(char *fmt, ...) {}
 
#define cbsstar_printf kern_printf
#define cbsstar_printf2 kern_printf
#define cbsstar_printf3 kern_printf
 
//#define cbsstar_printf fake_printf
//#define cbsstar_printf2 fake_printf
//#define cbsstar_printf3 fake_printf
 
#endif
/*
* DEBUG stuffs end
*/
 
/* this structure contains the status for a single budget */
struct budget_struct {
TIME Q; /* budget */
TIME T; /* period */
 
struct timespec dline; /* deadline */
int dline_timer; /* oslib event for budget reactivation*/
int avail; /* current budget */
LEVEL l; /* Current CBSSTAR level */
int loc_sched_id; /* Local scheduler id */
LEVEL loc_sched_level; /* Local scheduler level */
PID current; /* the task currently put in execution */
int flags;
int overran; /* overran flag */
 
IQUEUE tasks; /* a FIFO queue for the tasks handled
using the budget */
 
};
 
#define CBSSTAR_NOACTIVE 0
#define CBSSTAR_ACTIVE 1
#define CBSSTAR_INIT 2
 
typedef struct {
level_des l; /* the standard level descriptor */
 
struct budget_struct *b; /* the budgets! */
int n; /* the maximum index for the budgets */
int freebudgets; /* number of free budgets; starts from n */
 
int tb[MAX_PROC]; /* link task->budget (used in guest_end) */
 
bandwidth_t U; /*+ the used bandwidth by the server +*/
 
int cap_lev;
 
LEVEL scheduling_level;
 
} CBSSTAR_level_des;
 
 
static void CBSSTAR_deadline_timer_hardreservation(void *a)
{
struct budget_struct *b = a;
PID p;
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(CS:HrdRes:");
#endif
 
b->dline_timer = NIL;
b->overran = 0;
 
/* we modify the deadline according to rule 4 ... */
/* there is a while because if the wcet is << than the system tick
we need to postpone the deadline many times */
b->avail += b->Q;
if (b->avail > b->Q) b->avail = b->Q;
if (b->avail > 0) b->flags = CBSSTAR_ACTIVE;
 
/* avail may be <0 because a task executed via a shadow fo many time
b->current == NIL only if the prec task was finished and there
was not any other task to be put in the ready queue
... we are now activating the next task */
if (b->current == NIL && b->flags) {
if (iq_query_first(&(b->tasks)) != NIL) {
CBSSTAR_level_des *lev;
JOB_TASK_MODEL job;
p = iq_getfirst(&b->tasks);
#ifdef CBSSTAR_DEBUG
cbsstar_printf("%d",p);
#endif
 
kern_gettime(&b->dline);
ADDUSEC2TIMESPEC(b->T, &b->dline);
 
b->current = p;
 
lev = (CBSSTAR_level_des *)(level_table[b->l]);
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
event_need_reschedule();
 
}
} else
if (b->current != NIL && b->avail > 0) {
#ifdef CBSSTAR_DEBUG
cbsstar_printf("#");
#endif
}
if (b->flags == CBSSTAR_NOACTIVE && b->dline_timer != NIL) {
kern_gettime(&b->dline);
ADDUSEC2TIMESPEC(b->T, &b->dline);
b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
}
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
 
}
 
static void CBSSTAR_activation(CBSSTAR_level_des *lev,
PID p,
struct timespec *acttime)
{
JOB_TASK_MODEL job;
struct budget_struct *b = &lev->b[lev->tb[p]];
/* we have to check if the deadline and the wcet are correct before
activating a new task or an old task... */
 
/* check 1: if the deadline is before than the actual scheduling time */
 
/* check 2: if ( avail_time >= (cbs_dline - acttime)* (wcet/period) )
(rule 7 in the CBS article!) */
TIME t;
struct timespec t2,t3;
 
t = (b->T * b->avail) / b->Q;
t3.tv_sec = t / 1000000;
t3.tv_nsec = (t % 1000000) * 1000;
 
SUBTIMESPEC(&b->dline, acttime, &t2);
if (/* 1 */ TIMESPEC_A_LT_B(&b->dline, acttime) ||
/* 2 */ TIMESPEC_A_GT_B(&t3, &t2) ) {
TIMESPEC_ASSIGN(&b->dline, acttime);
ADDUSEC2TIMESPEC(b->T, &b->dline);
}
/* and the capacity */
if (b->flags == CBSSTAR_INIT) {
b->avail = b->Q;
b->flags = CBSSTAR_ACTIVE;
}
 
/* record the current task inserted in the master module */
b->current = p;
 
/* reset overran flag */
b->overran = 0;
 
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
 
}
 
static void CBSSTAR_account_capacity(CBSSTAR_level_des *lev, PID p)
{
struct timespec ty;
TIME tx;
struct budget_struct *b = &lev->b[lev->tb[p]];
TIME t;
struct timespec t2,t3, acttime;
 
if (lev->cap_lev != NIL && b->current == p) {
kern_event_delete(lev->cap_lev);
lev->cap_lev = NIL;
}
 
kern_gettime(&acttime);
 
t = (b->T * b->avail) / b->Q;
t3.tv_sec = t / 1000000;
t3.tv_nsec = (t % 1000000) * 1000;
 
SUBTIMESPEC(&b->dline, &acttime, &t2);
SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
tx = TIMESPEC2USEC(&ty);
lev->b[lev->tb[p]].avail -= tx;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf2("(CS:Cap p%d av=%d)", p, lev->b[lev->tb[p]].avail);
#endif
 
if (lev->b[lev->tb[p]].avail <= 0 || TIMESPEC_A_GT_B(&t3, &t2)) {
lev->b[lev->tb[p]].avail = 0;
lev->b[lev->tb[p]].flags = CBSSTAR_NOACTIVE;
}
 
if (TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
/* we modify the deadline ... */
b->overran = 1;
TIMESPEC_ASSIGN(&b->dline, &schedule_time);
ADDUSEC2TIMESPEC(b->T, &b->dline);
}
 
if (b->flags == CBSSTAR_NOACTIVE && b->dline_timer == NIL) {
b->dline_timer=kern_event_post(&b->dline, CBSSTAR_deadline_timer_hardreservation, b);
}
}
 
 
/* The on-line guarantee is enabled only if the appropriate flag is set... */
static int CBSSTAR_public_guarantee(LEVEL l, bandwidth_t *freebandwidth)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(CS:Gua)");
#endif
 
if (*freebandwidth >= lev->U) {
*freebandwidth -= lev->U;
return 1;
}
else
return 0;
}
 
static void capacity_handler(void *l)
{
CBSSTAR_level_des *lev = l;
lev->cap_lev = NIL;
event_need_reschedule();
}
 
static int CBSSTAR_private_eligible(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct budget_struct *b = &lev->b[lev->tb[p]];
JOB_TASK_MODEL job;
 
/* we have to check if the deadline and the wcet are correct...
if the CBSSTAR level schedules in background with respect to others
levels, there can be the case in witch a task is scheduled by
schedule_time > CBSSTAR_deadline; in this case (not covered in the
article because if there is only the standard scheduling policy
this never apply) we reassign the deadline */
if (b->current == p) {
if ( TIMESPEC_A_LT_B(&b->dline, &schedule_time)) {
if (lev->cap_lev!=NIL) {
kern_event_delete(lev->cap_lev);
lev->cap_lev=NIL;
}
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
/* we modify the deadline ... */
b->overran = 1;
TIMESPEC_ASSIGN(&b->dline, &schedule_time);
ADDUSEC2TIMESPEC(b->T, &b->dline);
 
/* and the capacity */
b->avail = b->Q;
b->flags = CBSSTAR_ACTIVE;
 
if (b->dline_timer!=NIL) {
kern_event_delete(b->dline_timer);
b->dline_timer=NIL;
}
/* and, finally, we reinsert the task in the master level */
job_task_default_model(job, b->dline);
job_task_def_noexc(job);
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&job);
return -1;
}
}
 
return 0;
 
}
 
static void CBSSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
{
/* A task has been activated for some reason. Basically, the task is
inserted in the queue if the queue is empty, otherwise the task is
inserted into the master module, and an oslib event is posted. */
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
BUDGET_TASK_MODEL *budget;
 
if (m->pclass != BUDGET_PCLASS ||
(m->level != 0 && m->level != l)) {
kern_raise(XINVALID_TASK, p);
return;
}
budget = (BUDGET_TASK_MODEL *)m;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(CS:PriIns:%d:%d", p, budget->b);
#endif
if (budget->b == -1)
return;
 
lev->tb[p] = budget->b;
 
if (lev->b[budget->b].current == NIL && lev->b[budget->b].flags ) {
/* This is the first task in the budget,
the task have to be inserted into the master module */
struct timespec t;
kern_gettime(&t);
CBSSTAR_activation(lev,p,&t);
} else {
/* The budget is not empty, another task is already into the
master module, so the task is inserted at the end of the budget
queue */
iq_insertlast(p,&lev->b[budget->b].tasks);
}
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf(")");
#endif
 
}
 
static void CBSSTAR_private_extract(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
#ifdef CBSSTAR_DEBUG
kern_printf("(CS:Ext:%d)", p);
#endif
 
/* a task is removed from execution for some reasons. It must be
that it is the first in its budget queue (only the first task in
a budget queue is put into execution!) */
 
/* remove the task from execution (or from the ready queue) */
if (lev->b[lev->tb[p]].current == p) {
 
CBSSTAR_account_capacity(lev,p);
/* remove the task from the master module */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
 
/* check if the buffer has someone else to schedule */
if (iq_query_first(&lev->b[lev->tb[p]].tasks) == NIL) {
/* the buffer has no tasks! */
lev->b[lev->tb[p]].current = NIL;
}
else if (lev->b[lev->tb[p]].flags) {
/* if so, insert the new task into the master module */
PID n;
struct timespec t;
kern_gettime(&t);
n = iq_getfirst(&lev->b[lev->tb[p]].tasks);
CBSSTAR_activation(lev,n,&t); // it modifies b[lev->tb[p]].current
}
else
lev->b[lev->tb[p]].current=NIL;
 
}
else {
iq_extract(p, &lev->b[lev->tb[p]].tasks);
}
}
 
static void CBSSTAR_private_dispatch(LEVEL l, PID p, int nostop)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct timespec ty;
 
#ifdef CBSSTAR_DEBUG
kern_printf("(CS:Dsp:%d)", p);
#endif
 
/* the current task (that is the only one inserted in the master module
for the corresponding budget) is dispatched. Note that the current
task is not inserted in any FIFO queue, so the task does not have to
be extracted! */
 
/* ... then, we dispatch it to the master level */
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
 
/* ...and finally, we have to post a capacity event */
if (!nostop) {
TIMESPEC_ASSIGN(&ty, &schedule_time);
ADDUSEC2TIMESPEC(lev->b[lev->tb[p]].avail,&ty);
lev->cap_lev = kern_event_post(&ty,capacity_handler, lev);
}
}
 
static void CBSSTAR_private_epilogue(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
struct budget_struct *b = &lev->b[lev->tb[p]];
 
#ifdef CBSSTAR_DEBUG
kern_printf("(CS:Epi:%d)",p);
#endif
 
if (p==b->current) {
CBSSTAR_account_capacity(lev,p);
 
// L'evento di capacità va cancellato perchè sarà ripristinato nella successiva dispatch
/* we have to check if the capacity is still available */
if (b->flags) {
/* there is capacity available, maybe it is simply a preemption;
the task have to return to the ready queue */
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
} else {
/* we kill the current activation */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, p);
 
iq_insertfirst(p, &b->tasks);
 
b->current = NIL;
}
}
 
}
 
/* Registration functions }*/
 
/*+ Registration function:
int flags the init flags ... see CBSSTAR.h +*/
LEVEL CBSSTAR_register_level(int n, LEVEL master)
{
LEVEL l; /* the level that we register */
CBSSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
kern_printf("CBSSTAR_register_level\n");
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(CBSSTAR_level_des));
 
lev = (CBSSTAR_level_des *)level_table[l];
 
/* fill the standard descriptor */
lev->l.private_insert = CBSSTAR_private_insert;
lev->l.private_extract = CBSSTAR_private_extract;
lev->l.private_eligible = CBSSTAR_private_eligible;
lev->l.private_dispatch = CBSSTAR_private_dispatch;
lev->l.private_epilogue = CBSSTAR_private_epilogue;
 
lev->l.public_guarantee = CBSSTAR_public_guarantee;
 
/* fill the CBSSTAR descriptor part */
lev->b = (struct budget_struct *)kern_alloc(sizeof(struct budget_struct)*n);
 
for (i=0; i<n; i++) {
lev->b[i].Q = 0;
lev->b[i].T = 0;
NULL_TIMESPEC(&lev->b[i].dline);
lev->b[i].dline_timer = NIL;
lev->b[i].avail = 0;
lev->b[i].current = -1;
lev->b[i].flags = CBSSTAR_INIT;
lev->b[i].l=l;
iq_init(&lev->b[i].tasks, &freedesc, 0);
}
 
lev->n = n;
lev->freebudgets = 0;
 
for (i=0; i<MAX_PROC; i++)
lev->tb[i] = NIL;
 
lev->U = 0;
lev->cap_lev = NIL;
lev->scheduling_level = master;
 
return l;
 
}
 
int CBSSTAR_setbudget(LEVEL l, TIME Q, TIME T, LEVEL local_scheduler_level, int scheduler_id)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
int r;
 
#ifdef CBSSTAR_DEBUG
cbsstar_printf("(CS:SetBud)");
#endif
 
for (r = 0; r < lev->n; r++)
if (lev->b[r].Q == 0) break;
 
if (r != lev->n) {
bandwidth_t b;
b = (MAX_BANDWIDTH / T) * Q;
/* really update lev->U, checking an overflow... */
if (Q< T && MAX_BANDWIDTH - lev->U > b) {
lev->U += b;
lev->freebudgets++;
lev->b[r].Q = Q;
lev->b[r].T = T;
 
lev->b[r].loc_sched_id = scheduler_id;
lev->b[r].loc_sched_level = local_scheduler_level;
return r;
}
else
return -2;
}
else
return -1;
}
 
int CBSSTAR_removebudget(LEVEL l, int budget)
{
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
bandwidth_t b;
b = (MAX_BANDWIDTH / lev->b[budget].T) * lev->b[budget].Q;
 
lev->U -= b;
 
lev->b[budget].Q = 0;
lev->b[budget].T = 0;
NULL_TIMESPEC(&lev->b[budget].dline);
lev->b[budget].dline_timer = NIL;
lev->b[budget].avail = 0;
lev->b[budget].current = -1;
lev->b[budget].flags = CBSSTAR_INIT;
iq_init(&lev->b[budget].tasks, &freedesc, 0);
 
return 0;
 
}
 
int CBSSTAR_adjust_budget(LEVEL l, TIME Q, TIME T, int budget)
{
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
lev->b[budget].Q = Q;
lev->b[budget].T = T;
 
return 0;
 
}
 
int CBSSTAR_getbudgetinfo(LEVEL l, TIME *Q, TIME *T, int budget)
{
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
*Q = lev->b[budget].Q;
*T = lev->b[budget].T;
 
return 0;
 
}
 
int CBSSTAR_was_budget_overran(LEVEL l, int budget)
{
 
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
return lev->b[budget].overran;
 
}
 
int CBSSTAR_is_active(LEVEL l, int budget)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
return lev->b[budget].flags;
 
}
 
int CBSSTAR_get_local_scheduler_level_from_budget(LEVEL l, int budget)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
return lev->b[budget].loc_sched_level;
 
}
 
int CBSSTAR_get_local_scheduler_level_from_pid(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
return lev->b[lev->tb[p]].loc_sched_level;
 
}
 
int CBSSTAR_get_local_scheduler_id_from_budget(LEVEL l, int budget)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
return lev->b[budget].loc_sched_id;
 
}
 
int CBSSTAR_get_local_scheduler_id_from_pid(LEVEL l, PID p)
{
CBSSTAR_level_des *lev = (CBSSTAR_level_des *)(level_table[l]);
 
return lev->b[lev->tb[p]].loc_sched_id;
 
}
 
/shark/trunk/ports/first/modules/posix.c
0,0 → 1,539
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* Massimiliano Giorgi <massy@gandalf.sssup.it>
* Luca Abeni <luca@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARR2ANTY; without even the implied waRR2anty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#include <posix.h>
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
#include <kernel/trace.h>
 
#include <comm_message.h>
 
//#define POSIX_DEBUG
 
/*+ Status used in the level +*/
#define POSIX_READY MODULE_STATUS_BASE
 
#define POSIX_CHANGE_LEVEL 1
 
/*+ the level redefinition for the Round Robin level +*/
typedef struct {
level_des l; /*+ the standard level descriptor +*/
 
int nact[MAX_PROC]; /*+ number of pending activations +*/
int priority[MAX_PROC]; /*+ priority of each task +*/
 
IQUEUE *ready; /*+ the ready queue array +*/
 
int slice; /*+ the level's time slice +*/
 
struct multiboot_info *multiboot; /*+ used if the level have to insert
the main task +*/
int maxpriority; /*+ the priority are from 0 to maxpriority
(i.e 0 to 31) +*/
 
int yielding; /*+ equal to 1 when a sched_yield is called +*/
 
int flag[MAX_PROC];
 
int new_level[MAX_PROC];
int new_slice[MAX_PROC];
int new_control[MAX_PROC];
 
} POSIX_level_des;
 
/* This is not efficient but very fair :-)
The need of all this stuff is because if a task execute a long time
due to (shadow!) priority inheritance, then the task shall go to the
tail of the queue many times... */
static PID POSIX_public_scheduler(LEVEL l)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
PID p;
 
int prio;
 
prio = lev->maxpriority;
 
for (;;) {
p = iq_query_first(&lev->ready[prio]);
if (p == NIL) {
if (prio) {
prio--;
continue;
}
else
return NIL;
}
 
if ((proc_table[p].control & CONTROL_CAP) &&
(proc_table[p].avail_time <= 0)) {
proc_table[p].avail_time += proc_table[p].wcet;
iq_extract(p,&lev->ready[prio]);
iq_insertlast(p,&lev->ready[prio]);
}
else
return p;
}
}
 
static int POSIX_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
NRT_TASK_MODEL *nrt;
 
if (m->pclass != NRT_PCLASS) return -1;
if (m->level != 0 && m->level != l) return -1;
 
nrt = (NRT_TASK_MODEL *)m;
 
/* the task state is set at SLEEP by the general task_create */
 
/* I used the wcet field because using wcet can account if a task
consume more than the timeslice... */
 
if (nrt->inherit == NRT_INHERIT_SCHED &&
proc_table[exec_shadow].task_level == l) {
/* We inherit the scheduling properties if the scheduling level
*is* the same */
lev->priority[p] = lev->priority[exec_shadow];
proc_table[p].avail_time = proc_table[exec_shadow].avail_time;
proc_table[p].wcet = proc_table[exec_shadow].wcet;
 
proc_table[p].control = (proc_table[p].control & ~CONTROL_CAP) |
(proc_table[exec_shadow].control & CONTROL_CAP);
lev->nact[p] = (lev->nact[exec_shadow] == -1) ? -1 : 0;
}
else {
lev->priority[p] = nrt->weight;
if (nrt->slice) {
proc_table[p].avail_time = nrt->slice;
proc_table[p].wcet = nrt->slice;
}
else {
proc_table[p].avail_time = lev->slice;
proc_table[p].wcet = lev->slice;
}
if (nrt->policy == NRT_RR_POLICY)
proc_table[p].control |= CONTROL_CAP;
if (nrt->arrivals == SAVE_ARRIVALS)
lev->nact[p] = 0;
else
lev->nact[p] = -1;
}
 
lev->flag[p] = 0;
 
return 0; /* OK */
}
 
static void POSIX_public_dispatch(LEVEL l, PID p, int nostop)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
/* the task state is set EXE by the scheduler()
we extract the task from the ready queue
NB: we can't assume that p is the first task in the queue!!! */
iq_extract(p, &lev->ready[lev->priority[p]]);
}
 
static void POSIX_public_epilogue(LEVEL l, PID p)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
/* Change task level */
if (lev->flag[p] & POSIX_CHANGE_LEVEL) {
 
STD_command_message msg;
 
proc_table[p].status = SLEEP;
proc_table[p].task_level = lev->new_level[p];
msg.command = STD_ACTIVATE_TASK;
level_table[lev->new_level[p]] -> public_message(lev->new_level[p],p,&msg);
 
return;
 
}
 
if (lev->yielding) {
lev->yielding = 0;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
}
/* check if the slice is finished and insert the task in the coPOSIXect
qqueue position */
else if (proc_table[p].control & CONTROL_CAP &&
proc_table[p].avail_time <= 0) {
proc_table[p].avail_time += proc_table[p].wcet;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
}
else
iq_insertfirst(p,&lev->ready[lev->priority[p]]);
 
proc_table[p].status = POSIX_READY;
}
 
static void POSIX_public_activate(LEVEL l, PID p)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed...) */
if (proc_table[p].status != SLEEP) {
if (lev->nact[p] != -1)
lev->nact[p]++;
return;
}
 
/* Insert task in the correct position */
proc_table[p].status = POSIX_READY;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
}
 
static void POSIX_public_unblock(LEVEL l, PID p)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
/* Similar to POSIX_task_activate, but we don't check in what state
the task is */
 
/* Insert task in the coPOSIXect position */
proc_table[p].status = POSIX_READY;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
}
 
static void POSIX_public_block(LEVEL l, PID p)
{
/* Extract the running task from the level
. we have already extract it from the ready queue at the dispatch time.
. the capacity event have to be removed by the generic kernel
. the wcet don't need modification...
. the state of the task is set by the calling function
 
So, we do nothing!!!
*/
}
 
static int POSIX_public_message(LEVEL l, PID p, void *m)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
STD_command_message *msg;
NRT_TASK_MODEL *nrt;
 
/* Task Endcycle */
switch ((long)(m)) {
case (long)(NULL):
if (lev->nact[p] > 0) {
/* continue!!!! */
lev->nact[p]--;
iq_insertfirst(p,&lev->ready[lev->priority[p]]);
proc_table[p].status = POSIX_READY;
} else
proc_table[p].status = SLEEP;
 
jet_update_endcycle(); /* Update the Jet data... */
trc_logevent(TRC_ENDCYCLE,&exec_shadow); /* tracer stuff */
break;
 
/* Task Disable */
case (long)(1):
 
break;
 
default:
 
msg = (STD_command_message *)m;
 
switch(msg->command) {
case STD_SET_NEW_LEVEL:
lev->flag[p] |= POSIX_CHANGE_LEVEL;
lev->new_level[p] = (int)(msg->param);
 
break;
case STD_SET_NEW_MODEL:
 
nrt = (NRT_TASK_MODEL *)(msg->param);
 
lev->priority[p] = nrt->weight;
if (nrt->slice) {
lev->new_slice[p] = nrt->slice;
} else {
lev->new_slice[p] = 0;
}
if (nrt->policy == NRT_RR_POLICY)
lev->new_control[p] |= CONTROL_CAP;
if (nrt->arrivals == SAVE_ARRIVALS)
lev->nact[p] = 0;
else
lev->nact[p] = -1;
lev->flag[p] = 0;
 
break;
 
case STD_ACTIVATE_TASK:
 
if (lev->new_slice[p]) {
proc_table[p].avail_time = lev->new_slice[p];
proc_table[p].wcet = lev->new_slice[p];
} else {
proc_table[p].avail_time = lev->slice;
proc_table[p].wcet = lev->slice;
}
 
proc_table[p].control = lev->new_control[p];
 
POSIX_public_activate(l,p);
 
break;
}
 
break;
 
}
return 0;
}
 
static void POSIX_public_end(LEVEL l, PID p)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
lev->nact[p] = -1;
 
/* then, we insert the task in the free queue */
proc_table[p].status = FREE;
iq_priority_insert(p,&freedesc);
}
 
/* Registration functions */
 
/*+ This init function install the "main" task +*/
static void POSIX_call_main(void *l)
{
LEVEL lev;
PID p;
NRT_TASK_MODEL m;
void *mb;
 
lev = (LEVEL)l;
 
nrt_task_default_model(m);
nrt_task_def_level(m,lev); /* with this we are sure that the task aPOSIXives
to the coPOSIXect level */
 
mb = ((POSIX_level_des *)level_table[lev])->multiboot;
nrt_task_def_arg(m,mb);
nrt_task_def_usemath(m);
nrt_task_def_nokill(m);
nrt_task_def_ctrl_jet(m);
nrt_task_def_weight(m,0);
nrt_task_def_policy(m,NRT_RR_POLICY);
nrt_task_def_inherit(m,NRT_EXPLICIT_SCHED);
 
p = task_create("Main", __init__, (TASK_MODEL *)&m, NULL);
 
if (p == NIL)
kern_printf("\nPanic!!! can't create main task...\n");
 
POSIX_public_activate(lev,p);
}
 
 
/*+ Registration function:
TIME slice the slice for the Round Robin queue
int createmain 1 if the level creates the main task 0 otherwise
struct multiboot_info *mb used if createmain specified +*/
LEVEL POSIX_register_level(TIME slice,
int createmain,
struct multiboot_info *mb,
int prioritylevels)
{
LEVEL l; /* the level that we register */
POSIX_level_des *lev; /* for readableness only */
PID i; /* a counter */
int x; /* a counter */
 
kern_printf("POSIX_register_level\n");
 
l = level_alloc_descriptor(sizeof(POSIX_level_des));
 
lev = (POSIX_level_des *)level_table[l];
 
/* fill the standard descriptor */
lev->l.public_scheduler = POSIX_public_scheduler;
lev->l.public_create = POSIX_public_create;
lev->l.public_end = POSIX_public_end;
lev->l.public_dispatch = POSIX_public_dispatch;
lev->l.public_epilogue = POSIX_public_epilogue;
lev->l.public_activate = POSIX_public_activate;
lev->l.public_unblock = POSIX_public_unblock;
lev->l.public_block = POSIX_public_block;
lev->l.public_message = POSIX_public_message;
 
/* fill the POSIX descriptor part */
for (i = 0; i < MAX_PROC; i++) {
lev->nact[i] = -1;
lev->new_level[i] = 0;
lev->new_slice[i] = 0;
lev->new_control[i] = 0;
}
 
lev->maxpriority = prioritylevels -1;
 
lev->ready = (IQUEUE *)kern_alloc(sizeof(IQUEUE) * prioritylevels);
 
for (x = 0; x < prioritylevels; x++)
iq_init(&lev->ready[x], &freedesc, 0);
 
if (slice < POSIX_MINIMUM_SLICE) slice = POSIX_MINIMUM_SLICE;
if (slice > POSIX_MAXIMUM_SLICE) slice = POSIX_MAXIMUM_SLICE;
lev->slice = slice;
 
lev->multiboot = mb;
 
if (createmain)
sys_atrunlevel(POSIX_call_main,(void *) l, RUNLEVEL_INIT);
 
return l;
}
 
/*+ this function forces the running task to go to his queue tail;
(it works only on the POSIX level) +*/
int POSIX_sched_yield(LEVEL l)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
if (proc_table[exec_shadow].task_level != l)
return -1;
 
proc_table[exec_shadow].context = kern_context_save();
lev->yielding = 1;
scheduler();
kern_context_load(proc_table[exec_shadow].context);
return 0;
}
 
/*+ this function returns the maximum level allowed for the POSIX level +*/
int POSIX_get_priority_max(LEVEL l)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
return lev->maxpriority;
}
 
/*+ this function returns the default timeslice for the POSIX level +*/
int POSIX_rr_get_interval(LEVEL l)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
return lev->slice;
}
 
/*+ this functions returns some paramaters of a task;
policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
priority must be in the range [0..prioritylevels]
returns ENOSYS or ESRCH if there are problems +*/
int POSIX_getschedparam(LEVEL l, PID p, int *policy, int *priority)
{
if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
return ESRCH;
 
if (proc_table[p].task_level != l)
return ENOSYS;
 
if (proc_table[p].control & CONTROL_CAP)
*policy = NRT_RR_POLICY;
else
*policy = NRT_FIFO_POLICY;
 
*priority = ((POSIX_level_des *)(level_table[l]))->priority[p];
 
return 0;
}
 
/*+ this functions sets paramaters of a task +*/
int POSIX_setschedparam(LEVEL l, PID p, int policy, int priority)
{
POSIX_level_des *lev = (POSIX_level_des *)(level_table[l]);
 
if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
return ESRCH;
 
if (proc_table[p].task_level != l)
return ENOSYS;
 
if (policy == SCHED_RR)
proc_table[p].control |= CONTROL_CAP;
else if (policy == SCHED_FIFO)
proc_table[p].control &= ~CONTROL_CAP;
else
return EINVAL;
 
if (lev->priority[p] != priority) {
if (proc_table[p].status == POSIX_READY) {
iq_extract(p,&lev->ready[lev->priority[p]]);
lev->priority[p] = priority;
iq_insertlast(p,&lev->ready[priority]);
}
else
lev->priority[p] = priority;
}
 
return 0;
}
 
 
 
/shark/trunk/ports/first/modules/edfstar.c
0,0 → 1,792
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/**
------------
CVS : $Id: edfstar.c,v 1.1 2003-09-10 15:56:28 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2003-09-10 15:56:28 $
------------
**/
 
/*
* Copyright (C) 2001 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "edfstar.h"
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
#include <kernel/trace.h>
 
 
#define EDFSTAR_CHANGE_LEVEL 1
 
/* for iqueues */
/* #include "iqueue.h" Now iqueues are the only queue type available
into the kernel */
#include <kernel/iqueue.h>
 
/* for BUDGET_TASK_MODEL */
#include "cbsstar.h"
#include <comm_message.h>
 
/*
* DEBUG stuffs begin
*/
 
#define EDFSTAR_DEBUG
 
#ifdef EDFSTAR_DEBUG
 
static __inline__ fake_printf(char *fmt, ...) {}
 
//#define edfstar_printf fake_printf
//#define edfstar_printf2 fake_printf
//#define edfstar_printf3 fake_printf
 
#define edfstar_printf kern_printf
#define edfstar_printf2 kern_printf
#define edfstar_printf3 kern_printf
#endif
 
/*
* DEBUG stuffs end
*/
 
/* Status used in the level */
#define EDFSTAR_READY MODULE_STATUS_BASE /* - Ready status */
#define EDFSTAR_IDLE MODULE_STATUS_BASE+4 /* to wait the deadline */
 
/* flags */
#define EDFSTAR_FLAG_NORAISEEXC 2
 
/* the level redefinition for the Earliest Deadline First level */
typedef struct {
level_des l; /* the standard level descriptor */
 
TIME period[MAX_PROC]; /* The task periods; the deadlines are
stored in the priority field */
int deadline_timer[MAX_PROC];
/* The task deadline timers */
 
struct timespec deadline_timespec[MAX_PROC];
 
int dline_miss[MAX_PROC]; /* Deadline miss counter */
int wcet_miss[MAX_PROC]; /* Wcet miss counter */
 
int nact[MAX_PROC]; /* Wcet miss counter */
 
int flag[MAX_PROC];
/* used to manage the JOB_TASK_MODEL and the
periodicity */
 
IQUEUE ready; /* the ready queue */
 
PID activated; /* the task that has been inserted into the
master module */
 
int budget[MAX_PROC];
 
int scheduling_level;
 
int new_level[MAX_PROC];
int wcet[MAX_PROC]; /* save the wcet fields */
 
} EDFSTAR_level_des;
 
static void EDFSTAR_check_preemption(EDFSTAR_level_des *lev)
{
PID first;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:chk)");
#endif
 
if ((first = iq_query_first(&lev->ready)) != lev->activated) {
if (lev->activated != NIL)
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, lev->activated);
 
lev->activated = first;
 
if (first != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget[first]);
 
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, first, (TASK_MODEL *)&b);
}
}
}
 
static void EDFSTAR_timer_deadline(void *par);
 
static void EDFSTAR_internal_activate(EDFSTAR_level_des *lev, PID p,
struct timespec *t)
{
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:iact)");
#endif
 
ADDUSEC2TIMESPEC(lev->period[p], t);
 
*iq_query_timespec(p, &lev->ready) = *t;
lev->deadline_timespec[p] = *t;
 
/* Insert task in the correct position */
proc_table[p].status = EDFSTAR_READY;
iq_timespec_insert(p,&lev->ready);
 
/* needed because when there is a wcet miss I disable CONTROL_CAP */
proc_table[p].control |= CONTROL_CAP;
 
/* check for preemption */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_timer_deadline(void *par)
{
PID p = (PID) par;
EDFSTAR_level_des *lev;
 
#ifdef EDFSTAR_DEBUG
// edfstar_printf("(E:tdl ");
#endif
 
lev = (EDFSTAR_level_des *)level_table[proc_table[p].task_level];
 
switch (proc_table[p].status) {
case EDFSTAR_IDLE:
#ifdef EDFSTAR_DEBUG
// edfstar_printf2("I%d",p);
#endif
/* set the request time */
EDFSTAR_internal_activate(lev,p,iq_query_timespec(p, &lev->ready));
 
event_need_reschedule();
break;
 
default:
//#ifdef EDFSTAR_DEBUG
kern_printf("(E:Dl:%d)",p);
//#endif
/* else, a deadline miss occurred!!! */
lev->dline_miss[p]++;
 
/* the task is into another state */
lev->nact[p]++;
 
/* Set the deadline timer */
ADDUSEC2TIMESPEC(lev->period[p], &lev->deadline_timespec[p]);
}
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFSTAR_timer_deadline,
(void *)p);
 
#ifdef EDFSTAR_DEBUG
// edfstar_printf(")");
#endif
}
 
static void EDFSTAR_timer_guest_deadline(void *par)
{
PID p = (PID) par;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:gdl)");
#endif
 
kern_raise(XDEADLINE_MISS,p);
}
 
static int EDFSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* if the EDFSTAR_task_create is called, then the pclass must be a
valid pclass. */
HARD_TASK_MODEL *h;
 
if (m->pclass != HARD_PCLASS) return -1;
if (m->level != 0 && m->level != l) return -1;
h = (HARD_TASK_MODEL *)m;
if (!h->wcet || !h->mit || h->periodicity != PERIODIC) return -1;
/* now we know that m is a valid model */
 
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:tcr)");
#endif
 
lev->period[p] = h->mit;
 
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
/* Enable wcet check */
proc_table[p].avail_time = h->wcet;
proc_table[p].wcet = h->wcet;
proc_table[p].control |= CONTROL_CAP;
 
return 0; /* OK, also if the task cannot be guaranteed... */
}
 
static int EDFSTAR_public_eligible(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf2("(E:eli)");
#endif
 
return level_table[ lev->scheduling_level ]->
private_eligible(lev->scheduling_level,p);
}
 
static void EDFSTAR_public_dispatch(LEVEL l, PID p, int nostop)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:dis)");
 
edfstar_printf3("(%d %d)",
iq_query_timespec(p, &lev->ready)->tv_nsec/1000000,
schedule_time.tv_nsec/1000000);
#endif
 
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static int EDFSTAR_change_level(LEVEL l, PID p)
{
 
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* Change task level */
if (lev->flag[p] & EDFSTAR_CHANGE_LEVEL) {
STD_command_message msg;
proc_table[p].status = SLEEP;
iq_extract(p,&lev->ready);
if (lev->deadline_timer[p] != -1)
kern_event_delete(lev->deadline_timer[p]);
EDFSTAR_check_preemption(lev);
lev->nact[p] = 0;
lev->budget[p] = -1;
proc_table[p].task_level = lev->new_level[p];
/* Send change level command to local scheduler */
 
msg.command = STD_ACTIVATE_TASK;
msg.param = NULL;
 
level_table[ lev->new_level[p] ]->public_message(lev->new_level[p],p,&msg);
return 1;
 
}
 
return 0;
 
}
 
static void EDFSTAR_public_epilogue(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:epi ");
#endif
 
if (EDFSTAR_change_level(l, p)) return;
 
/* check if the wcet is finished... */
if (proc_table[p].avail_time <= 0 && proc_table[p].control&CONTROL_CAP) {
/* wcet finished: disable wcet event and count wcet miss */
#ifdef EDFSTAR_DEBUG
edfstar_printf2("W%d",p);
#endif
proc_table[p].control &= ~CONTROL_CAP;
lev->wcet_miss[p]++;
}
#ifdef EDFSTAR_DEBUG
edfstar_printf(")");
#endif
 
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = EDFSTAR_READY;
}
 
static void EDFSTAR_public_activate(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
struct timespec t;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:act:%d)",p);
#endif
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed... */
if (proc_table[p].status != SLEEP) {
/* a periodic task cannot be activated when it is already active */
kern_raise(XACTIVATION,p);
return;
}
 
kern_gettime(&t);
 
EDFSTAR_internal_activate(lev,p, &t);
 
/* Set the deadline timer */
lev->deadline_timer[p] = kern_event_post(&lev->deadline_timespec[p],
EDFSTAR_timer_deadline,
(void *)p);
 
}
 
static void EDFSTAR_public_unblock(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ins)");
#endif
 
/* Insert task in the correct position */
proc_table[p].status = EDFSTAR_READY;
iq_timespec_insert(p,&lev->ready);
 
/* and check for preemption! */
EDFSTAR_check_preemption(lev);
}
 
static void EDFSTAR_public_block(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ext)");
#endif
 
/* the task is blocked on a synchronization primitive. we have to
remove it from the master module -and- from the local queue! */
iq_extract(p,&lev->ready);
 
/* and finally, a preemption check! (it will also call guest_end) */
EDFSTAR_check_preemption(lev);
}
 
static int EDFSTAR_public_message(LEVEL l, PID p, void *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
struct timespec temp;
STD_command_message *msg;
HARD_TASK_MODEL *h;
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:ecy ");
#endif
 
switch ((long)(m)) {
 
/* Task EndCycle */
case (long)(NULL):
 
/* we call guest_end directly here because the same task may
be reinserted in the queue before calling the preemption check! */
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level,p);
lev->activated = NIL;
iq_extract(p,&lev->ready);
/* we reset the capacity counters... */
proc_table[p].avail_time = proc_table[p].wcet;
if (lev->flag[p] & EDFSTAR_CHANGE_LEVEL) {
STD_command_message msg;
 
lev->nact[p] = 0;
 
lev->budget[p] = -1;
proc_table[p].task_level = lev->new_level[p];
/* Send change level command to local scheduler */
 
msg.command = STD_ACTIVATE_TASK;
msg.param = NULL;
 
level_table[ lev->new_level[p] ]->public_message(lev->new_level[p],p,&msg);
 
return 0;
}
if (lev->nact[p] > 0) {
#ifdef EDFSTAR_DEBUG
edfstar_printf2("E%d",p);
#endif
/* Pending activation: reactivate the thread!!! */
lev->nact[p]--;
/* see also EDFSTAR_timer_deadline */
kern_gettime(&temp);
EDFSTAR_internal_activate(lev,p, &temp);
/* check if the deadline has already expired */
temp = *iq_query_timespec(p, &lev->ready);
if (TIMESPEC_A_LT_B(&temp, &schedule_time)) {
/* count the deadline miss */
lev->dline_miss[p]++;
kern_event_delete(lev->deadline_timer[p]);
}
} else {
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("e%d",p);
#endif
/* the task has terminated his job before it consume the wcet. All OK! */
proc_table[p].status = EDFSTAR_IDLE;
/* and finally, a preemption check! */
EDFSTAR_check_preemption(lev);
/* when the deadline timer fire, it recognize the situation and set
correctly all the stuffs (like reactivation, etc... ) */
}
#ifdef EDFSTAR_DEBUG
edfstar_printf(")");
#endif
jet_update_endcycle(); /* Update the Jet data... */
trc_logevent(TRC_ENDCYCLE,&exec_shadow); /* tracer stuff */
break;
 
default:
 
msg = (STD_command_message *)m;
switch(msg->command) {
case STD_SET_NEW_MODEL:
/* if the EDFSTAR_task_create is called, then the pclass must be a
valid pclass. */
h=(HARD_TASK_MODEL *)(msg->param);
/* now we know that m is a valid model */
lev->wcet[p]=h->wcet;
lev->period[p] = h->mit;
lev->flag[p] = 0;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
break;
 
case STD_SET_NEW_LEVEL:
lev->flag[p] |= EDFSTAR_CHANGE_LEVEL;
lev->new_level[p] = (int)(msg->param);
 
break;
 
case STD_ACTIVATE_TASK:
/* Enable wcet check */
proc_table[p].avail_time = lev->wcet[p];
proc_table[p].wcet = lev->wcet[p];
proc_table[p].control |= CONTROL_CAP;
EDFSTAR_public_activate(l, p);
break;
 
}
}
return 0;
}
 
static void EDFSTAR_public_end(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
edfstar_printf("(E:end)");
#endif
 
iq_extract(p,&lev->ready);
 
/* we finally put the task in the ready queue */
proc_table[p].status = FREE;
iq_insertfirst(p,&freedesc);
if (lev->deadline_timer[p] != -1) {
kern_event_delete(lev->deadline_timer[p]);
}
 
/* and finally, a preemption check! (it will also call guest_end) */
EDFSTAR_check_preemption(lev);
}
 
/* Guest Functions
These functions manages a JOB_TASK_MODEL, that is used to put
a guest task in the EDFSTAR ready queue. */
 
static void EDFSTAR_private_insert(LEVEL l, PID p, TASK_MODEL *m)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
JOB_TASK_MODEL *job;
 
if (m->pclass != JOB_PCLASS || (m->level != 0 && m->level != l) ) {
kern_raise(XINVALID_TASK, p);
return;
}
 
job = (JOB_TASK_MODEL *)m;
 
/* if the EDFSTAR_guest_create is called, then the pclass must be a
valid pclass. */
 
*iq_query_timespec(p, &lev->ready) = job->deadline;
lev->deadline_timer[p] = -1;
lev->dline_miss[p] = 0;
lev->wcet_miss[p] = 0;
lev->nact[p] = 0;
 
if (job->noraiseexc)
lev->flag[p] |= EDFSTAR_FLAG_NORAISEEXC;
else {
lev->flag[p] &= ~EDFSTAR_FLAG_NORAISEEXC;
lev->deadline_timer[p] = kern_event_post(iq_query_timespec(p, &lev->ready),
EDFSTAR_timer_guest_deadline,
(void *)p);
}
 
lev->period[p] = job->period;
 
/* Insert task in the correct position */
iq_timespec_insert(p,&lev->ready);
proc_table[p].status = EDFSTAR_READY;
 
/* check for preemption */
EDFSTAR_check_preemption(lev);
 
/* there is no bandwidth guarantee at this level, it is performed
by the level that inserts guest tasks... */
}
 
static void EDFSTAR_private_dispatch(LEVEL l, PID p, int nostop)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
level_table[ lev->scheduling_level ]->
private_dispatch(lev->scheduling_level,p,nostop);
}
 
static void EDFSTAR_private_epilogue(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
/* the task has been preempted. it returns into the ready queue... */
level_table[ lev->scheduling_level ]->
private_epilogue(lev->scheduling_level,p);
 
proc_table[p].status = EDFSTAR_READY;
}
 
static void EDFSTAR_private_extract(LEVEL l, PID p)
{
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
#ifdef EDFSTAR_DEBUG
//kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
 
iq_extract(p, &lev->ready);
 
/* we remove the deadline timer, because the slice is finished */
if (lev->deadline_timer[p] != NIL) {
#ifdef EDFSTAR_DEBUG
// kern_printf("EDFSTAR_guest_end: dline timer %d\n",lev->deadline_timer[p]);
#endif
kern_event_delete(lev->deadline_timer[p]);
lev->deadline_timer[p] = NIL;
}
 
/* and finally, a preemption check! (it will also call guest_end() */
EDFSTAR_check_preemption(lev);
}
 
/* Registration functions */
 
/* Registration function:
int flags the init flags ... see EDFSTAR.h */
 
LEVEL EDFSTAR_register_level(int master)
{
LEVEL l; /* the level that we register */
EDFSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
 
#ifdef EDFSTAR_DEBUG
printk("EDFSTAR_register_level\n");
#endif
 
/* request an entry in the level_table */
l = level_alloc_descriptor(sizeof(EDFSTAR_level_des));
 
lev = (EDFSTAR_level_des *)level_table[l];
 
printk(" lev=%d\n",(int)lev);
 
/* fill the standard descriptor */
lev->l.private_insert = EDFSTAR_private_insert;
lev->l.private_extract = EDFSTAR_private_extract;
lev->l.private_dispatch = EDFSTAR_private_dispatch;
lev->l.private_epilogue = EDFSTAR_private_epilogue;
 
lev->l.public_guarantee = NULL;
lev->l.public_eligible = EDFSTAR_public_eligible;
lev->l.public_create = EDFSTAR_public_create;
lev->l.public_end = EDFSTAR_public_end;
lev->l.public_dispatch = EDFSTAR_public_dispatch;
lev->l.public_epilogue = EDFSTAR_public_epilogue;
lev->l.public_activate = EDFSTAR_public_activate;
lev->l.public_unblock = EDFSTAR_public_unblock;
lev->l.public_block = EDFSTAR_public_block;
lev->l.public_message = EDFSTAR_public_message;
 
/* fill the EDFSTAR descriptor part */
for(i=0; i<MAX_PROC; i++) {
lev->period[i] = 0;
lev->deadline_timer[i] = -1;
lev->flag[i] = 0;
lev->dline_miss[i] = 0;
lev->wcet_miss[i] = 0;
lev->nact[i] = 0;
lev->budget[i] = NIL;
lev->wcet[i] = 0;
}
 
iq_init(&lev->ready, NULL, IQUEUE_NO_PRIORITY);
lev->activated = NIL;
 
lev->scheduling_level = master;
 
return l;
}
 
int EDFSTAR_get_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
return lev->dline_miss[p];
}
 
int EDFSTAR_get_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
return lev->wcet_miss[p];
}
 
int EDFSTAR_get_nact(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
return lev->nact[p];
}
 
int EDFSTAR_reset_dline_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
lev->dline_miss[p] = 0;
return 0;
}
 
int EDFSTAR_reset_wcet_miss(PID p)
{
LEVEL l = proc_table[p].task_level;
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
lev->wcet_miss[p] = 0;
return 0;
}
 
int EDFSTAR_setbudget(LEVEL l, PID p, int budget)
{
 
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
lev->budget[p] = budget;
 
return 0;
 
}
 
int EDFSTAR_getbudget(LEVEL l, PID p)
{
 
EDFSTAR_level_des *lev = (EDFSTAR_level_des *)(level_table[l]);
 
return lev->budget[p];
 
}
/shark/trunk/ports/first/modules/posixstar.c
0,0 → 1,656
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Trimarchi Michael <trimarchi@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARR2ANTY; without even the implied waRR2anty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
 
#include <ll/stdio.h>
#include <ll/string.h>
#include <kernel/model.h>
#include <kernel/descr.h>
#include <kernel/var.h>
#include <kernel/func.h>
#include <kernel/trace.h>
#include "posixstar.h"
#include "cbsstar.h"
#include "comm_message.h"
 
//#define POSIXSTAR_DEBUG
 
/*+ Status used in the level +*/
#define POSIXSTAR_READY MODULE_STATUS_BASE
 
#define POSIXSTAR_CHANGE_LEVEL 1
 
/*+ the level redefinition for the Round Robin level +*/
typedef struct {
level_des l; /*+ the standard level descriptor +*/
 
int nact[MAX_PROC]; /*+ number of pending activations +*/
int priority[MAX_PROC]; /*+ priority of each task +*/
 
IQUEUE *ready; /*+ the ready queue array +*/
 
int slice; /*+ the level's time slice +*/
 
// the multiboot is not usefull for this module
// struct multiboot_info *multiboot; /*+ used if the level have to insert
// the main task +*/
 
int maxpriority; /*+ the priority are from 0 to maxpriority
(i.e 0 to 31) +*/
 
int yielding; /*+ equal to 1 when a sched_yield is called +*/
 
int budget[MAX_PROC];
 
PID activated;
int scheduling_level;
int flag[MAX_PROC];
 
int new_level[MAX_PROC];
int new_slice[MAX_PROC];
int new_control[MAX_PROC];
} POSIXSTAR_level_des;
 
/* the private scheduler choice a task and insert in cbsstar module */
/* This is not efficient but very fair :-)
The need of all this stuff is because if a task execute a long time
due to (shadow!) priority inheritance, then the task shall go to the
tail of the queue many times... */
 
static void POSIXSTAR_private_scheduler(POSIXSTAR_level_des * lev)
{
/* the old posix scheduler select the private job for CBS */
PID p = NIL;
 
int prio;
 
prio = lev->maxpriority;
for (;;) {
p = iq_query_first(&lev->ready[prio]);
if (p == NIL) {
if (prio) {
prio--;
continue;
}
else {
p=NIL;
break;
}
}
 
if ((proc_table[p].control & CONTROL_CAP) &&
(proc_table[p].avail_time <= 0)) {
if (proc_table[p].avail_time<=0)
proc_table[p].avail_time += proc_table[p].wcet;
iq_extract(p,&lev->ready[prio]);
iq_insertlast(p,&lev->ready[prio]);
}
else {
break;
}
}
 
if (p!=lev->activated) {
if (lev->activated != NIL ) {
level_table[ lev->scheduling_level ]->
private_extract(lev->scheduling_level, lev->activated);
}
lev->activated = p;
if (p != NIL) {
BUDGET_TASK_MODEL b;
budget_task_default_model(b, lev->budget[p]);
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:SchAct:%d:%d)",p,lev->budget[p]);
#endif
level_table[ lev->scheduling_level ]->
private_insert(lev->scheduling_level, p, (TASK_MODEL *)&b);
}
}
}
 
static int POSIXSTAR_public_eligible(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
if (p==lev->activated) {
return level_table[ lev->scheduling_level ]->
private_eligible(lev->scheduling_level,p);
}
return 0;
}
 
static int POSIXSTAR_public_create(LEVEL l, PID p, TASK_MODEL *m)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
NRT_TASK_MODEL *nrt;
 
/* DEBUG */
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:Crt:%d)",p);
#endif
 
if (m->pclass != NRT_PCLASS) return -1;
if (m->level != 0 && m->level != l) return -1;
 
nrt = (NRT_TASK_MODEL *)m;
 
/* the task state is set at SLEEP by the general task_create */
 
/* I used the wcet field because using wcet can account if a task
consume more than the timeslice... */
 
if (nrt->inherit == NRT_INHERIT_SCHED &&
proc_table[exec_shadow].task_level == l) {
/* We inherit the scheduling properties if the scheduling level
*is* the same */
lev->priority[p] = lev->priority[exec_shadow];
proc_table[p].avail_time = proc_table[exec_shadow].avail_time;
proc_table[p].wcet = proc_table[exec_shadow].wcet;
 
proc_table[p].control = (proc_table[p].control & ~CONTROL_CAP) |
(proc_table[exec_shadow].control & CONTROL_CAP);
lev->nact[p] = (lev->nact[exec_shadow] == -1) ? -1 : 0;
}
else {
if (nrt->weight<=lev->maxpriority)
lev->priority[p] = nrt->weight;
else lev->priority[p]=lev->maxpriority;
if (nrt->slice) {
proc_table[p].avail_time = nrt->slice;
proc_table[p].wcet = nrt->slice;
}
else {
proc_table[p].avail_time = lev->slice;
proc_table[p].wcet = lev->slice;
}
if (nrt->policy == NRT_RR_POLICY) {
proc_table[p].control |= CONTROL_CAP;
}
if (nrt->arrivals == SAVE_ARRIVALS)
lev->nact[p] = 0;
else
lev->nact[p] = -1;
}
 
return 0; /* OK */
}
 
static void POSIXSTAR_public_dispatch(LEVEL l, PID p, int nostop)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* the task state is set EXE by the scheduler()
we extract the task from the ready queue
NB: we can't assume that p is the first task in the queue!!! */
 
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:Dsp:%d)",p);
#endif
if (p==lev->activated)
level_table[lev->scheduling_level]->private_dispatch(lev->scheduling_level, p, nostop);
 
}
 
static void POSIXSTAR_public_epilogue(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:Epi:%d)",p);
#endif
 
/* Change task level */
if (lev->flag[p] & POSIXSTAR_CHANGE_LEVEL) {
STD_command_message msg;
proc_table[p].status = SLEEP;
iq_extract(p,&lev->ready[lev->priority[p]]);
POSIXSTAR_private_scheduler(lev);
lev->budget[p] = -1;
proc_table[p].task_level = lev->new_level[p];
msg.command = STD_ACTIVATE_TASK;
level_table[lev->new_level[p]] -> public_message(lev->new_level[p],p,&msg);
return;
}
if (p==lev->activated) {
if (lev->yielding) {
lev->yielding = 0;
iq_extract(p,&lev->ready[lev->priority[p]]);
iq_insertlast(p,&lev->ready[lev->priority[p]]);
}
/* check if the slice is finished and insert the task in the coPOSIXect
qqueue position */
else if (proc_table[p].control & CONTROL_CAP &&
proc_table[p].avail_time <= 0) {
iq_extract(p,&lev->ready[lev->priority[p]]);
iq_insertlast(p,&lev->ready[lev->priority[p]]);
POSIXSTAR_private_scheduler(lev);
if (p==lev->activated)
level_table[lev->scheduling_level]->private_epilogue(lev->scheduling_level,p);
}
else {
 
level_table[lev->scheduling_level]->private_epilogue(lev->scheduling_level,p);
 
POSIXSTAR_private_scheduler(lev);
 
}
proc_table[p].status = POSIXSTAR_READY;
}
}
 
static void POSIXSTAR_internal_activate(POSIXSTAR_level_des *lev, PID p)
{
 
/* Insert task in the correct position */
proc_table[p].status = POSIXSTAR_READY;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
 
}
 
static void POSIXSTAR_public_activate(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* Test if we are trying to activate a non sleeping task */
/* save activation (only if needed...) */
if (proc_table[p].status != SLEEP) {
if (lev->nact[p] != -1)
lev->nact[p]++;
return;
}
 
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:Act:%d)",p);
#endif
POSIXSTAR_internal_activate(lev, p);
POSIXSTAR_private_scheduler(lev);
 
}
 
 
static void POSIXSTAR_public_unblock(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* Similar to POSIX_task_activate, but we don't check in what state
the task is */
 
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:UnBlk:%d)",p);
#endif
/* Insert task in the coPOSIXect position */
proc_table[p].status = POSIXSTAR_READY;
iq_insertlast(p,&lev->ready[lev->priority[p]]);
POSIXSTAR_private_scheduler(lev);
 
}
 
static void POSIXSTAR_public_block(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
/* Extract the running task from the level
. we have already extract it from the ready queue at the dispatch time.
. the capacity event have to be removed by the generic kernel
. the wcet don't need modification...
. the state of the task is set by the calling function
 
So, we do nothing!!!
*/
 
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:Blk:%d)", p);
#endif
iq_extract(p,&lev->ready[lev->priority[p]]);
if (p==lev->activated) lev->activated = NIL;
POSIXSTAR_private_scheduler(lev);
}
 
static int POSIXSTAR_public_message(LEVEL l, PID p, void *m)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
STD_command_message *msg;
NRT_TASK_MODEL *nrt;
 
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:Msg:%d)",p);
#endif
 
switch ((long)(m)) {
 
/* Task EndCycle */
case (long)(NULL):
 
if (lev->nact[p] > 0) {
/* continue!!!! */
lev->nact[p]--;
iq_extract(p,&lev->ready[lev->priority[p]]);
iq_insertfirst(p,&lev->ready[lev->priority[p]]);
proc_table[p].status = POSIXSTAR_READY;
}
else {
proc_table[p].status = SLEEP;
iq_extract(p,&lev->ready[lev->priority[p]]);
}
 
jet_update_endcycle(); /* Update the Jet data... */
trc_logevent(TRC_ENDCYCLE,&exec_shadow); /* tracer stuff */
POSIXSTAR_private_scheduler(lev);
 
break;
 
/* Task Disable */
case (long)(1):
 
break;
 
default:
 
msg = (STD_command_message *)m;
 
switch(msg->command) {
case STD_SET_NEW_LEVEL:
lev->flag[p] |= POSIXSTAR_CHANGE_LEVEL;
lev->new_level[p] = (int)(msg->param);
 
break;
case STD_SET_NEW_MODEL:
 
nrt = (NRT_TASK_MODEL *)(msg->param);
 
lev->priority[p] = nrt->weight;
if (nrt->slice) {
lev->new_slice[p] = nrt->slice;
} else {
lev->new_slice[p] = 0;
}
if (nrt->policy == NRT_RR_POLICY)
lev->new_control[p] |= CONTROL_CAP;
if (nrt->arrivals == SAVE_ARRIVALS)
lev->nact[p] = 0;
else
lev->nact[p] = -1;
lev->flag[p] = 0;
 
break;
case STD_ACTIVATE_TASK:
 
if (lev->new_slice[p]) {
proc_table[p].avail_time = lev->new_slice[p];
proc_table[p].wcet = lev->new_slice[p];
} else {
proc_table[p].avail_time = lev->slice;
proc_table[p].wcet = lev->slice;
}
 
proc_table[p].control = lev->new_control[p];
 
POSIXSTAR_public_activate(l,p);
 
break;
}
 
}
 
return 0;
 
}
 
static void POSIXSTAR_public_end(LEVEL l, PID p)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
#ifdef POSIXSTAR_DEBUG
kern_printf("(PS:End:%d)", p);
#endif
 
lev->nact[p] = -1;
 
/* then, we insert the task in the free queue */
proc_table[p].status = FREE;
iq_priority_insert(p,NULL);
POSIXSTAR_private_scheduler(lev);
 
}
 
/* Registration functions */
 
/*+ Registration function:
TIME slice the slice for the Round Robin queue +*/
LEVEL POSIXSTAR_register_level(int master, TIME slice,
int prioritylevels)
{
LEVEL l; /* the level that we register */
POSIXSTAR_level_des *lev; /* for readableness only */
PID i; /* a counter */
int x; /* a counter */
 
#ifdef POSIXSTRA_DEBUG
kern_printf("POSIXSTAR_register_level\n");
#endif
l = level_alloc_descriptor(sizeof(POSIXSTAR_level_des));
 
lev = (POSIXSTAR_level_des *)level_table[l];
 
lev->l.public_create = POSIXSTAR_public_create;
lev->l.public_end = POSIXSTAR_public_end;
lev->l.public_dispatch = POSIXSTAR_public_dispatch;
lev->l.public_epilogue = POSIXSTAR_public_epilogue;
lev->l.public_activate = POSIXSTAR_public_activate;
lev->l.public_unblock = POSIXSTAR_public_unblock;
lev->l.public_block = POSIXSTAR_public_block;
lev->l.public_message = POSIXSTAR_public_message;
lev->l.public_eligible = POSIXSTAR_public_eligible;
 
/* fill the POSIX descriptor part */
for (i = 0; i < MAX_PROC; i++) {
lev->nact[i] = -1;
lev->budget[i] = -1;
lev->flag[i] = 0;
lev->new_level[i] = 0;
lev->new_slice[i] = 0;
lev->new_control[i] = 0;
 
}
 
lev->maxpriority = prioritylevels - 1;
 
lev->ready = (IQUEUE *)kern_alloc(sizeof(IQUEUE) * prioritylevels);
 
for (x = 0; x < prioritylevels; x++)
iq_init(&lev->ready[x], NULL, 0);
 
if (slice < POSIXSTAR_MINIMUM_SLICE) slice = POSIXSTAR_MINIMUM_SLICE;
if (slice > POSIXSTAR_MAXIMUM_SLICE) slice = POSIXSTAR_MAXIMUM_SLICE;
lev->slice = slice;
lev->activated = NIL;
lev->scheduling_level = master;
return l;
 
}
 
int POSIXSTAR_setbudget(LEVEL l, PID p, int budget)
{
 
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
lev->budget[p] = budget;
 
return 0;
 
}
 
int POSIXSTAR_getbudget(LEVEL l, PID p)
{
 
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
return lev->budget[p];
 
}
 
int POSIXSTAR_budget_has_thread(LEVEL l, int budget)
{
 
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
int i;
 
for(i = 0; i< MAX_PROC; i++)
if (lev->budget[i] == budget) return 1;
 
return 0;
 
}
 
/*+ this function forces the running task to go to his queue tail;
(it works only on the POSIX level) +*/
int POSIXSTAR_sched_yield(LEVEL l)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
if (proc_table[exec_shadow].task_level != l)
return -1;
 
proc_table[exec_shadow].context = kern_context_save();
lev->yielding = 1;
scheduler();
kern_context_load(proc_table[exec_shadow].context);
return 0;
}
 
/*+ this function returns the maximum level allowed for the POSIX level +*/
int POSIXSTAR_get_priority_max(LEVEL l)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
return lev->maxpriority;
}
 
/*+ this function returns the default timeslice for the POSIX level +*/
int POSIXSTAR_rr_get_interval(LEVEL l)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
return lev->slice;
}
 
/*+ this functions returns some paramaters of a task;
policy must be NRT_RR_POLICY or NRT_FIFO_POLICY;
priority must be in the range [0..prioritylevels]
returns ENOSYS or ESRCH if there are problems +*/
int POSIXSTAR_getschedparam(LEVEL l, PID p, int *policy, int *priority)
{
if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
return ESRCH;
 
if (proc_table[p].task_level != l)
return ENOSYS;
 
if (proc_table[p].control & CONTROL_CAP)
*policy = NRT_RR_POLICY;
else
*policy = NRT_FIFO_POLICY;
 
*priority = ((POSIXSTAR_level_des *)(level_table[l]))->priority[p];
 
return 0;
}
 
/*+ this functions sets paramaters of a task +*/
int POSIXSTAR_setschedparam(LEVEL l, PID p, int policy, int priority)
{
POSIXSTAR_level_des *lev = (POSIXSTAR_level_des *)(level_table[l]);
 
if (p<0 || p>= MAX_PROC || proc_table[p].status == FREE)
return ESRCH;
 
if (proc_table[p].task_level != l)
return ENOSYS;
 
if (policy == SCHED_RR)
proc_table[p].control |= CONTROL_CAP;
else if (policy == SCHED_FIFO)
proc_table[p].control &= ~CONTROL_CAP;
else
return EINVAL;
 
if (lev->priority[p] != priority) {
if (proc_table[p].status == POSIXSTAR_READY) {
iq_extract(p,&lev->ready[lev->priority[p]]);
lev->priority[p] = priority;
iq_insertlast(p,&lev->ready[priority]);
}
else
lev->priority[p] = priority;
}
 
return 0;
}
 
/shark/trunk/ports/first/first-server.c
0,0 → 1,415
//=====================================================================
// FFFFFFIII RRRRR SSTTTTTTT
// FF IIR RR SS
// FF IR SS
// FFFFFF RRRR SSSSST
// FF FI RRR SS
// FF II RRR SS
// FF IIIIIR RS
//
// Basic FSF(FIRST Scheduling Framework) contract management
// S.Ha.R.K. Implementation
//=====================================================================
 
#include "fsf_contract.h"
#include "cbsstar.h"
#include "posixstar.h"
#include "edfstar.h"
#include "posix.h"
#include "comm_message.h"
 
#include <pthread.h>
#include <stdlib.h>
 
#define FSF_DEBUG
 
int cbsstar_level;
int posix_level;
 
/* Convert the contract specification to
* budget parameters
*/
int set_CBSSTAR_budget_from_contract
(const fsf_contract_parameters_t *contract,
int *budget)
{
 
int local_scheduler_level = 0;
 
switch (contract->local_scheduler_id) {
case FSF_SCHEDULER_POSIX:
local_scheduler_level = POSIXSTAR_register_level(cbsstar_level,5000,32);
break;
case FSF_SCHEDULER_EDF:
local_scheduler_level = EDFSTAR_register_level(cbsstar_level);
break;
case FSF_SCHEDULER_RM:
break;
}
*budget = CBSSTAR_setbudget(cbsstar_level,
TIMESPEC2USEC(&(contract->budget_min)),
TIMESPEC2USEC(&(contract->period_max)),
local_scheduler_level,contract->local_scheduler_id);
 
return 0;
 
}
 
int adjust_CBSSTAR_budget_from_contract
(const fsf_contract_parameters_t *contract,
int budget)
{
 
CBSSTAR_adjust_budget(cbsstar_level,
TIMESPEC2USEC(&(contract->budget_min)),
TIMESPEC2USEC(&(contract->period_max)),
budget);
 
return 0;
 
}
 
/* Admission Test function */
int add_contract(const fsf_contract_parameters_t *contract)
{
 
return 0;
 
}
 
int link_contract_to_server(const fsf_contract_parameters_t *contract,
fsf_server_id_t server)
{
 
return 0;
 
}
 
int remove_contract(fsf_server_id_t server)
{
 
return 0;
 
}
 
 
int fsf_negotiate_contract
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server)
{
/* Check if contract is initialized */
if (!contract) return FSF_ERR_NOT_INITIALIZED;
 
/* Admission Test */
if (FSF_ADMISSION_TEST_IS_ENABLED)
if (add_contract(contract))
return FSF_ERR_CONTRACT_REJECTED;
 
/* SERVER = BUDGET */
set_CBSSTAR_budget_from_contract(contract,server);
 
#ifdef FSF_DEBUG
kern_printf("(New Server %d)",*server);
#endif
 
if (*server >= 0)
link_contract_to_server(contract,*server);
else
return FSF_ERR_CREATE_SERVER;
 
return 0;
 
}
 
int fsf_bind_thread_to_server
(fsf_server_id_t server,
pthread_t thread,
void *rt_arg)
{
 
STD_command_message *msg;
int local_scheduler_level,scheduler_id;
 
/* Move thread from the posix module to local scheduler */
 
#ifdef FSF_DEBUG
kern_printf("(Bind thread = %d to Server = %d)",thread,server);
#endif
 
/* Check if server and thread exsist */
if (server == -1 || thread == -1)
return FSF_ERR_BIND_THREAD;
 
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_budget(cbsstar_level,server);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_budget(cbsstar_level,server);
 
/* Check if thread is already bind */
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
if (POSIXSTAR_getbudget(local_scheduler_level,thread) != -1)
return FSF_ERR_BIND_THREAD;
 
/* Set server on local scheduler */
POSIXSTAR_setbudget(local_scheduler_level,thread,(int)(server));
 
/* Send change level command to posix level */
msg = (STD_command_message *)malloc(sizeof(STD_command_message));
 
msg->command = STD_SET_NEW_MODEL;
msg->param = (void *)(rt_arg);
level_table[local_scheduler_level]->public_message(local_scheduler_level,thread,msg);
 
msg->command = STD_SET_NEW_LEVEL;
msg->param = (void *)(local_scheduler_level);
task_message(msg,thread,0);
free(msg);
 
break;
case FSF_SCHEDULER_EDF:
 
if (EDFSTAR_getbudget(local_scheduler_level,thread) != -1)
return FSF_ERR_BIND_THREAD;
 
/* Set server on local scheduler */
EDFSTAR_setbudget(local_scheduler_level,thread,(int)(server));
 
/* Send change level command to posix level */
msg = (STD_command_message *)malloc(sizeof(STD_command_message));
 
msg->command = STD_SET_NEW_MODEL;
msg->param = (void *)(rt_arg);
level_table[local_scheduler_level]->public_message(local_scheduler_level,thread,msg);
 
msg->command = STD_SET_NEW_LEVEL;
msg->param = (void *)(local_scheduler_level);
task_message(msg,thread,0);
free(msg);
 
break;
case FSF_SCHEDULER_RM:
default:
return FSF_ERR_BIND_THREAD;
break;
}
 
return 0;
}
 
int fsf_unbind_thread_from_server
(pthread_t thread)
{
 
int local_scheduler_level, scheduler_id;
 
/* Move thread from the local scheduler module to posix level */
 
#ifdef FSF_DEBUG
kern_printf("(UnBind thread = %d)",thread);
#endif
 
/* Check if thread exsists */
if (thread == -1)
return FSF_ERR_UNBIND_THREAD;
 
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_pid(cbsstar_level,thread);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_pid(cbsstar_level,thread);
 
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
/* Check if it is bind to a server */
if (POSIXSTAR_getbudget(local_scheduler_level,thread) == -1)
return FSF_ERR_UNBIND_THREAD;
else {
STD_command_message *msg;
NRT_TASK_MODEL nrt;
 
nrt_task_default_model(nrt);
nrt_task_def_save_arrivals(nrt);
 
/* Send change level command to local scheduler */
msg = (STD_command_message *)malloc(sizeof(STD_command_message));
 
msg->command = STD_SET_NEW_MODEL;
msg->param = (void *)(&nrt);
level_table[posix_level]->public_message(posix_level,thread,msg);
 
msg->command = STD_SET_NEW_LEVEL;
msg->param = (void *)(posix_level);
task_message(msg,thread,0);
 
free(msg);
}
break;
case FSF_SCHEDULER_EDF:
 
if (EDFSTAR_getbudget(local_scheduler_level,thread) == -1)
return FSF_ERR_UNBIND_THREAD;
else {
STD_command_message *msg;
NRT_TASK_MODEL nrt;
 
nrt_task_default_model(nrt);
nrt_task_def_save_arrivals(nrt);
 
/* Send change level command to local scheduler */
msg = (STD_command_message *)malloc(sizeof(STD_command_message));
 
msg->command = STD_SET_NEW_MODEL;
msg->param = (void *)(&nrt);
level_table[posix_level]->public_message(posix_level,thread,msg);
 
msg->command = STD_SET_NEW_LEVEL;
msg->param = (void *)(posix_level);
task_message(msg,thread,0);
 
free(msg);
}
break;
 
case FSF_SCHEDULER_RM:
break;
}
 
return 0;
 
}
 
int fsf_negotiate_contract_for_new_thread
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server,
pthread_t *thread,
pthread_attr_t *attr,
fsf_thread_code_t thread_code,
void *arg,
void *rt_arg)
 
{
 
int error;
 
/* Create server */
error = fsf_negotiate_contract(contract, server);
if (error) return error;
 
/* Create pthread */
if (pthread_create(thread, attr, thread_code, arg))
return FSF_ERR_CREATE_THREAD;
 
/* Bind thread to server */
error = fsf_bind_thread_to_server(*server, *thread, rt_arg);
if (error) return error;
 
return 0;
 
}
 
int fsf_negotiate_contract_for_myself
(const fsf_contract_parameters_t *contract,
fsf_server_id_t *server,
void *rt_arg)
{
 
int error;
 
/* Create server */
error = fsf_negotiate_contract(contract, server);
if (error) return error;
 
/* Bind current thread to server */
error = fsf_bind_thread_to_server(*server, exec_shadow, rt_arg);
if (error) return error;
 
return 0;
 
}
 
int fsf_get_server
(fsf_server_id_t *server,
pthread_t thread)
{
int local_scheduler_level, scheduler_id;
 
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_pid(cbsstar_level,thread);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_pid(cbsstar_level, thread);
 
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
return POSIXSTAR_getbudget(local_scheduler_level,thread);
case FSF_SCHEDULER_EDF:
case FSF_SCHEDULER_RM:
return -1;
}
 
return -1;
 
}
 
int fsf_cancel_contract
(fsf_server_id_t *server)
{
 
int local_scheduler_level, scheduler_id;
 
#ifdef FSF_DEBUG
kern_printf("(Remove server %d)",*server);
#endif
 
/* Check server id */
if (*server < 0)
return FSF_ERR_INVALID_SERVER;
 
local_scheduler_level = CBSSTAR_get_local_scheduler_level_from_budget(cbsstar_level,*server);
scheduler_id = CBSSTAR_get_local_scheduler_id_from_budget(cbsstar_level,*server);
 
switch (scheduler_id) {
case FSF_SCHEDULER_POSIX:
/* Check if some thread use the server */
if(POSIXSTAR_budget_has_thread(local_scheduler_level,*server))
return FSF_ERR_SERVER_USED;
break;
case FSF_SCHEDULER_EDF:
case FSF_SCHEDULER_RM:
break;
}
 
CBSSTAR_removebudget(cbsstar_level,*server);
 
level_free_descriptor(local_scheduler_level);
 
remove_contract(*server);
 
*server = -1;
 
return 0;
 
}
 
int fsf_renegotiate_contract
(const fsf_contract_parameters_t *new_contract,
fsf_server_id_t server)
{
 
#ifdef FSF_DEBUG
kern_printf("(Renegotiate for server %d)",server);
#endif
 
if (!new_contract)
return FSF_ERR_NOT_INITIALIZED;
 
if (server < 0)
return FSF_ERR_INVALID_SERVER;
 
return adjust_CBSSTAR_budget_from_contract(new_contract,server);
 
}
/shark/trunk/ports/first/makefile
0,0 → 1,22
# The Frame Buffer Device
 
ifndef BASE
BASE=../..
endif
 
include $(BASE)/config/config.mk
 
LIBRARY = first
 
OBJS_PATH = $(BASE)/ports/first
 
FIRST = first-contract.o first-server.o first-sync.o \
./modules/cbsstar.o ./modules/posixstar.o ./modules/posix.o \
./modules/edfstar.o
 
OBJS = $(FIRST)
 
C_OPT += -I./include -I. -I..
 
include $(BASE)/config/lib.mk
 
/shark/trunk/ports/makefile
1,5 → 1,5
 
dirs := $(filter-out CVS cvs makefile, $(wildcard *))
dirs := $(filter-out CVS cvs mesa fftw makefile, $(wildcard *))
p_all := $(addprefix prefixall_, $(dirs))
p_install := $(addprefix prefixinstall_, $(dirs))
p_clean := $(addprefix prefixclean_, $(dirs))