Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

/*
 * 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: descr.h,v 1.1.1.1 2002-03-29 14:12:51 pj Exp $

 File:        $File$
 Revision:    $Revision: 1.1.1.1 $
 Last update: $Date: 2002-03-29 14:12:51 $
 ------------

Kernel main data structures

This file declare:

- the descriptors
  - cleanup handlers
  - levels
  - mutexes
  - mutex attributes
  - resource levels


**/


/*
 * 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 __KERNEL_DESCR_H__
#define __KERNEL_DESCR_H__


#include <ll/ll.h>
#include <kernel/model.h>
#include <kernel/types.h>
#include <limits.h>

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  CLEANUP HANDLER STRUCTURES

  Derived directly from posix standard, B.18.2.3
  This structure implements the task cleanup functions queue...
  look at kern.c!

  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

struct _task_handler_rec {
  void (*f)(void *);
  void *a;
  struct _task_handler_rec *next;
};



struct condition_struct;

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  GENERAL TASK DESCRIPTOR

  In this type definition there is all the basic information for
  handling a task in the system.

  All the informations scheduler-dependent (like deadline, priority,
  and so on) are put in the level module files.
  In any case, a priority field is inserted to simplify the implementation
  of most of the scheduling algorithms
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


typedef struct {
        DWORD   task_ID;      /*+ progressive task counter ID +*/
        LEVEL   task_level;   /*+ the "real" level that owns the task     +*/

        CONTEXT context;      /*+ Context area pointer (see vm.h)         +*/
        BYTE    *stack;       /*+ Pointer to stack area base              +*/
        TASK    (*body)();    /*+ Pointer to the code of the task
                                  (starting address)                      +*/

        char    name[MAX_TASKNAME]; /*+ Text identifing the process name  +*/

        WORD    status;       /*+ actual task status
                                  (it could be EXE, SLEEP, IDLE, ...)     +*/

        WORD    pclass;       /*+ The code number of the task model used  +*/
        WORD    group;        /*+ 0 if task is single, else group id      +*/
        WORD    stacksize;    /*+ Task stack size                         +*/
        DWORD   control;      /*+ Control task operating mode
                                 Refer to the TASK_MODEL type for its use +*/


        int     frozen_activations; /*+ number of frozen activation;
                                        see kern.c, task_block_activations
                                        see model.h,flag in control field +*/


        /* sigset_t!!! */
        int sigmask;          /*+ The task signal mask                    +*/
        int sigpending;       /*+ The signal pending mask                 +*/
        int sigwaiting;       /*+ The signal waiting mask                 +*/

        struct timespec request_time;
                              /*+ Last request time for the task          +*/
        int     avail_time;   /*+ the time the task can execute before a
                                  timer fire. see also the control field
                                  and bits related in model.h             +*/


        PID     shadow;       /*+ Shadow task                             +*/

        struct _task_handler_rec *cleanup_stack;
                              /*+ The cleanup stack                       +*/

        QUEUE   next,prev;    /*+ Next/Prev Index in the queue            +*/

        int     errnumber;

        /* Job Execution Time fields */
        TIME    jet_table[JET_TABLE_DIM];
                              /*+ Execution time of the last
                                  activations of the task.                +*/

        int     jet_tvalid;   /*+ number of valid entry in the jet_table  +*/
        int     jet_curr;     /*+ Current entry in the jet_table          +*/
        TIME    jet_max;      /*+ Maximum Execution time since task_create
                                  or last jet_delstat                     +*/

        TIME    jet_sum;      /*+ Mean Execution time since task_create
                                  or last jet_delstat                     +*/

        TIME    jet_n;        /*+ Number of instances on witch the mean
                                  time have to be computed                +*/


        /* task_join fields */
        PID waiting_for_me;   /*+ the task that waits my dead,
                                  NIL if there aren't                     +*/

        void *return_value;   /*+ task return value                       +*/

        /* task specific data (it uses directly POSIX constant) */
        void *keys[PTHREAD_KEYS_MAX];

        /* condition variable field */
        struct condition_struct *cond_waiting;
                              /*+ the condition on that the task is
                                  waiting +*/


        /* stuff used in most algorithms; they are not used directly in
         * the generic kernel, with exclusion of delay_timer that is used
         * also in cond_timedwait
         */

        DWORD   priority;     /*+ A priority field                        +*/
        struct timespec timespec_priority; /*+ Another priority field     +*/
        int     delay_timer;  /*+ A field useful to store the delay timer +*/

        int     wcet;         /*+ a worst case time execution             +*/


} proc_des;


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  LEVEL DESCRIPTOR

  In this type definition there is all the basic information for
  handling a scheduling level in the system.

  All the informations that depends on the particular module are put
  in the level module files.

  The initialization of a level is splitted in two parts:
  - the registration -> called before the system initialization, typically
                        AFTER the resource registration
  - the level_init   -> called during the system initialization,
                        BEFORE the resource_init(s)


  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


typedef struct {
  char level_name[MAX_LEVELNAME]; /*+ for statistical pourposes          +*/
  WORD level_code;              /*+ level identification code            +*/
  BYTE level_version;           /*+ level version                        +*/

  /* LEVEL CALLS */
  int (*level_accept_task_model)(LEVEL l, TASK_MODEL *m);
                                /*+ models that a task can manage. returns
                                    0 if the level can manage the model,
                                    -1 if not                            +*/


  int (*level_accept_guest_model)(LEVEL l, TASK_MODEL *m);
                                /*+ models that a task can manage as guest
                                    tasks. returns
                                    0 if the level can manage the model,
                                    -1 if not                            +*/


 // void (*level_init)();       /*+ initialization of the level module   +*/
 // void (*level_end)();        /*+ level termination (at system end...  +*/
  void (*level_status)(LEVEL l);/*+ print level statistics...            +*/

  PID  (*level_scheduler)(LEVEL l);
                                /*+ the level scheduler returns a task
                                    chosen among those belonging to the
                                    level                                +*/


  int (*level_guarantee)(LEVEL l, bandwidth_t *freebandwidth);
                                /*+ 0 if the level is guaranteed, -1 if not
                                    no guarantee if (*f)()=null
                                    the function updates the parameter
                                    (see guarantee() )                   +*/


  /* TASK CALLS */
  int  (*task_create)(LEVEL l, PID p, TASK_MODEL *m);
                                /*+ the task p is created into the level
                                    returns 0->ok, -1->error             +*/

  void (*task_detach)(LEVEL l, PID p);
                                /*+ there is an error in the task_create
                                    after the task call task_create.
                                    The function delete all the informations
                                    about the task in the level.
                                    For the resources levels there is the
                                    res_detach: res_detach is called also
                                    when killing a task                  +*/

  int (*task_eligible)(LEVEL l, PID p);
                                /*+ correctness control when a task is
                                    chosen by a level scheduler (used with
                                    aperiodic servers) 0->ok, -1->no     +*/

  void (*task_dispatch)(LEVEL l, PID p, int nostop);
                                /*+ a task go in the EXEC status (called
                                    by dispatch() )                      +*/

  void (*task_epilogue)(LEVEL l, PID p);
                                /*+ a task has finished the current slice+*/

  void (*task_activate)(LEVEL l, PID p);
                                /*+ the task is activated...             +*/

  void (*task_insert)(LEVEL l, PID p);
                                /*+ opposite to task_extract             +*/
  void (*task_extract)(LEVEL l, PID p);
                                /*+ remove the task from the "ready" (if any)
                                    queue                                +*/


  void (*task_endcycle)(LEVEL l, PID p);
                                /*+ the (periodic) task finish the cycle +*/
  void (*task_end)(LEVEL l, PID p);
                                /*+ the task is killed; we have to remove
                                    it from the level queues, test if it
                                    is in the exec state, etc... it can
                                    modify the state of the task (-> FREE,
                                    ZOMBIE...), but
                                    cannot call the scheduler directly (it
                                    is called by the task_makefree.
                                    Note: the task can be in a state
                                    different from those managed by the
                                    level because the task may be blocked.
                                    the res_detach is in any case called
                                    AFTER the task_end.                  +*/


  void (*task_sleep)(LEVEL l, PID p);
                                /*+ this function will fall asleep the
                                    task in the EXE state. +*/



  void (*task_delay)(LEVEL l, PID p,DWORD tickdelay);


  /* guest CALLS:
     these functions are called from an Aperiodic Server Level for the task
     that are inserted in the local queues */

  int  (*guest_create)(LEVEL l, PID p, TASK_MODEL *m);
                                /*+ the task is already created in another
                                    level and it is inserted in the current
                                    level; returns 0->ok, -1->error      +*/

  void (*guest_detach)(LEVEL l, PID p);
                                /*+ there is an error in a task creation
                                    of a task made by an aperiodic server
                                    The function delete all the informations
                                    about the task in the level.         +*/

  void (*guest_dispatch)(LEVEL l, PID p, int nostop);
                                /*+ a task belonging to another level but
                                    inserted in the current level go in the
                                    EXEC status (called by dispatch() )  +*/

  void (*guest_epilogue)(LEVEL l, PID p);
                                /*+ a task has finished the current slice+*/

  void (*guest_activate)(LEVEL l, PID p);
                                /*+ the task is activated...             +*/

  void (*guest_insert)(LEVEL l, PID p);
                                /*+ remove the task from the "ready" (if any)
                                    queue                                +*/

  void (*guest_extract)(LEVEL l, PID p);
                                /*+ opposite to guest_insert             +*/


  void (*guest_endcycle)(LEVEL l, PID p);
                                /*+ the task finish the cycle +*/
  void (*guest_end)(LEVEL l, PID p);
                                /*+ the task is killed                   +*/

  void (*guest_sleep)(LEVEL l, PID p);
  void (*guest_delay)(LEVEL l, PID p, TIME tickdelay);

} level_des;


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  RESOURCE DESCRIPTOR

  In this type definition there is all the basic information for
  handling a resource module in the system.

  All the informations protocol-dependent (like ceiling, task that use
  a particular resource, and so on) are put in the resource module files.

  In general, the initialization of a resource module is splitted in two
  parts:
  - the registration   -> tipically done with a finction called
                          XXX_register_module. It is called before the
                          system initialization, in
                          the function __kernel_register_levels__().
  - the initialization -> called during the system initialization,
                          This is done posting some init functions with
                          the sys_at_init()
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


typedef struct {
  char res_name[MAX_MODULENAME];/*+ for statistical pourposes            +*/
  WORD res_code;                /*+ resource module identification code  +*/
  BYTE res_version;             /*+ resource module version              +*/

  int rtype;                    /*+ resource module extented interface
                                    code (see model.h)                   +*/


  void (*resource_status)();    /*+ print resource protocol statistics...+*/

  int  (*level_accept_resource_model)(RLEVEL l, RES_MODEL *r);
                                /*+ this function is called when the process
                                    is created. it returns 0 if the RES_MODEL
                                    can be managed by the level,-1 if not+*/


  void (*res_register)(RLEVEL l, PID p, RES_MODEL *r);
                                /*+ When the system knows that a resource
                                    model can be registered by a level,
                                    it calls this function. It registers all
                                    the information about the task and the
                                    model. +*/


  void (*res_detach)(RLEVEL l, PID p);
                                /*+ this function is called when the task
                                    is killed or some error is occurred
                                    in the task_create. It have to unlink
                                    the task from the module... If the task
                                    is already unlinked from the protocol
                                    no action is done                    +*/

} resource_des;







/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  MUTEX DESCRIPTOR

  In this type definition there is all the basic fields for
  handling a mutex in the system

  Many of the informations protocol-dependent (like ceiling, and so on)
  are put in the resource module or are pointef by the field opt.

  The opt field is used because in this way a mutex can be allocated in
  a dynamic way (in this case opt points to a dynamically allocated
  structure) or in a static way (in this case opt can be an index or a
  pointer to a static structure)
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

typedef struct {
  RLEVEL mutexlevel;  /*+ protocol used by the mutex. +*/
  int use;            /*+ the mutex is used in a condition wait... +*/
  void *opt;
} mutex_t;


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  MUTEX RESOURCE DESCRIPTOR

  This object is a resource_des object with a set of functions used to
  implement the mutex behaviour.

  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

typedef struct {
  resource_des r;

  int  (*level_accept_mutexattr)(RLEVEL l, const mutexattr_t *a);
                                /*+ this function is called when a mutex
                                    is created. it returns 0 if the
                                    mutexattr_t
                                    can be managed by the level,-1 if not+*/


  int (*init)   (RLEVEL l, mutex_t *m, const mutexattr_t *a);
  int (*destroy)(RLEVEL l, mutex_t *m);
  int (*lock)   (RLEVEL l, mutex_t *m);
  int (*trylock)(RLEVEL l, mutex_t *m);
  int (*unlock) (RLEVEL l, mutex_t *m);

} mutex_resource_des;

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  CONDITION VARIABLE DESCRIPTOR

  This is the condition variable descriptor.
  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/


typedef struct condition_struct {
  QUEUE waiters; /*+ queue for tasks waiting on the condition +*/
  mutex_t *used_for_waiting;
} cond_t;


#endif /* __TYPE_H__ */