enum { Nproc = 8, Nres = 8, Ntask = 8, Maxtasks = 20, Maxresources = 20, Maxsteps = Maxtasks * 2 * 100, /* 100 periods of maximum # of tasks */ /* Edf.flags field */ Verbose = 0x1, Useblocking = 0x2, }; typedef vlong Time; typedef uvlong Ticks; typedef struct Task Task; typedef struct Resource Resource; typedef struct Edf Edf; typedef struct Taskq Taskq; enum Edfstate { EdfUnused, /* task structure not in use */ EdfExpelled, /* in initialization, not yet admitted */ EdfAdmitted, /* admitted, but not started */ EdfIdle, /* admitted, but no member processes */ EdfAwaitrelease, /* released, but too early (on qwaitrelease) */ EdfReleased, /* released, but not yet scheduled (on qreleased) */ EdfRunning, /* one of this task's procs is running (on stack) */ EdfExtra, /* one of this task's procs is running in extra time (off stack) */ EdfPreempted, /* the running proc was preempted */ EdfBlocked, /* none of the procs are runnable as a result of sleeping */ EdfDeadline, /* none of the procs are runnable as a result of scheduling */ }; typedef enum Edfstate Edfstate; struct Edf { /* time intervals */ Ticks D; /* Deadline */ Ticks Delta; /* Inherited deadline */ Ticks T; /* period */ Ticks C; /* Cost */ Ticks S; /* Slice: time remaining in this period */ /* times */ Ticks r; /* (this) release time */ Ticks d; /* (this) deadline */ Ticks t; /* Start of next period, t += T at release */ /* for schedulability testing */ Ticks testDelta; int testtype; /* Release or Deadline */ Ticks testtime; Task * testnext; /* other */ Edfstate state; }; struct Task { QLock; Edf; Ticks scheduled; Schedq runq; /* Queue of runnable member procs */ Proc * procs[Nproc]; /* List of member procs; may contain holes */ int nproc; /* number of them */ Resource* res[Nres]; /* List of resources; may contain holes */ int nres; /* number of them */ char *user; /* mallocated */ Dirtab dir; int flags; /* e.g., Verbose */ Task *rnext; }; struct Taskq { Lock; Task* head; int (*before)(Task*, Task*); /* ordering function for queue (nil: fifo) */ }; struct Resource { char * name; Task * tasks[Ntask]; /* may contain holes */ int ntasks; Ticks Delta; /* for schedulability testing */ Ticks testDelta; }; extern Lock edftestlock; /* for atomic admitting/expelling */ extern Task tasks[Maxtasks]; /* may contain holes */ extern int ntasks; extern Resource resources[Maxresources]; /* may contain holes */ extern int nresources; extern Lock edflock; extern Taskq qwaitrelease; extern Taskq qreleased; extern Taskq qextratime; extern Taskq edfstack[]; extern int edf_stateupdate; extern void (*devrt)(Task *, Ticks, int); extern char * edf_statename[]; #pragma varargck type "T" Time #pragma varargck type "U" Ticks /* Interface: */ void edf_preempt(Task*); /* Stop current task, administrate run time, leave on stack */ void edf_deadline(Proc*); /* Remove current task from edfstack, schedule its next release */ void edf_release(Task*); /* Release a task */ void edf_schedule(Task *); /* Run a released task: remove from qrelease, push onto edfstack */ char * edf_admit(Task*); void edf_expel(Task*); void edf_bury(Proc*); /* Proc dies, update Task membership */ void edf_sched(Task*); /* Figure out what to do with task (after a state change) */ int isedf(Proc*); /* Proc must be edf scheduled */ void edf_stop(Proc*); /* Just event generation; should probably be done differently */ int edf_anyready(void); void edf_ready(Proc*); Proc * edf_runproc(void); void edf_block(Proc*); /* Edf proc has blocked, do the admin */ void edf_init(void); int edf_waitlock(Lock*); void edf_releaselock(Lock*); Time ticks2time(Ticks); Ticks time2ticks(Time);