/* $Revision: 1.2 $ */

#ifndef _KERN_H_
#define _KERN_H_

#include "cpu.h"

#define MAX_PRIORITY_GROUPS 		32
#define MAX_PRIORITIES_PER_GROUP 	MAX_PRIORITY_GROUPS
#define PRI_TO_GROUP_INDEX(pri)		(((pri) >> 5) & 0x1f)
#define PRI_TO_PRI_INDEX(pri)		((pri) & 0x1f)

#define MIN_PRIORITY 			0
#define MAX_PRIORITY ((MAX_PRIORITY_GROUPS * MAX_PRIORITIES_PER_GROUP) - 1)

#define TICKS_PER_SECOND 100 

#ifndef ASM_LANGUAGE
struct tcb {
  context_t       tcb_context;
  char           *tcb_name;
  int             (*tcb_main) ();
  int             (*restart) ();
  int             tcb_stkbeg;
  int             tcb_stkend;
  int             tcb_stksiz;
  int             tcb_group_index;
  int             tcb_pri_index;
  int             tcb_stat;
  int             tcb_arg;
  char           *tcb_stdio_buf;
  int             tcb_wait ;
  struct tcb     *tcb_next;	/* linked list */
  struct tcb     *tcb_previous;	/* linked list */
};
typedef struct tcb tcb_t;

extern tcb_t * cur_task;

struct sem {
	u_int           sem_gindex;
	u_int           sem_pindex[MAX_PRIORITIES_PER_GROUP];
	int             sem_count;
};

typedef struct sem sem_t;

extern int             idle_task(void);
extern void            kern_init(void);
extern void            task_main(void);
extern void            restart(tcb_t * tcb);
extern tcb_t * 		spawn( char *name, char *stack,
			      int (*code) (), int stksiz, int priority, int arg);
extern int             ready(tcb_t * task);
extern int             suspend(tcb_t * task);
extern tcb_t          *pick(sem_t * sem);
/* extern void            reschedule(context_t * trap_context) __attribute__ ((noreturn)); */
extern void            reschedule(context_t * trap_context);
extern void            yield(void);
extern void            exec(tcb_t * task);
/* extern void            finish(tcb_t * task) __attribute__ ((noreturn)); */
/* extern void            exit(int code) __attribute__ ((noreturn)); */
extern void            finish(tcb_t * task);
extern void            exit(int code);
extern void            ps_print(tcb_t * tcb);
extern u_long          ps(void);

int t_list_in_list( tcb_t * new ) ;
void init_task_list() ;
tcb_t * t_list_get_free_tcb() ;
int t_list_free_tcb( tcb_t * superflous ) ;
int t_list_insert( tcb_t * new ) ;


#endif

/* flag bits used for tcb stat */
#define TASK_INACTIVE		0x0
#define TASK_READY 		0x1
#define TASK_SUSPENDED 		0x2
#define TASK_RUNNING		0x4
#define TASK_STATE_MASK		0x7

#endif
