/* pthread.h */

#ifndef	_PTHREAD_H_
#define	_PTHREAD_H_

#define REG_SAVE_AREA_SIZE ((16 * 4) + (12 * 8) + 4 )
// Large yes but it's a good maximum
#define THREAD_STACK_SIZE (32*1024)

#define PTHREAD_THREADS_MAX (256)

extern int g_thread_system_running;
extern void *g_thread_callback_regs;
extern int g_thread_poll_rate;
extern int g_running_threads;

enum pthread_state
{
	PS_IDLE,
	PS_RUNNING,
	PS_SELECT_WAIT,
	PS_SLEEP_WAIT,
	PS_WAIT_WAIT,
	PS_SIGWAIT,
	PS_JOIN,
	PS_DEAD,
	PS_UNALLOCED,

	PS_STATE_MAX
};

struct pthread
{
	int						thread_type;

	struct pthread			*next;
	enum pthread_state		state;
	char					flags;
	char					pthread_priority;
	void					*ret;

	void * (*start_routine)(void *);
	void					*arg;

	void					*mach_data;		// Space for registers on the context switch
	void					*stack;

	struct pthread			*joined;		/* For joined threads */
};

typedef struct pthread *		pthread_t;

typedef	void * (*pthread_startroutine_t)(void *);
typedef void * pthread_attr_t;

void		pthread_init				(void);
int			pthread_create				(pthread_t *,
											 const pthread_attr_t *,
											 void * (*start_routine)(void *),
											 void *);
void		pthread_exit				(void *);
pthread_t	pthread_self				(void);
int			pthread_equal				(pthread_t, pthread_t);
int			pthread_join				(pthread_t, void **);
int			pthread_detach				(pthread_t);
void		pthread_yield				(void);

int			pthread_kill				(struct pthread *, int);
void		*pthread_signal            (int, void (*)(int));

// For locking other system routines
void pthread_sched_prevent(void);
void pthread_sched_resume(void);

void Thread_Init(pthread_t);
void Thread_Context_Switch(pthread_t);
void Thread_Start_Ticker(pthread_t);
void Thread_Stop_Ticker(pthread_t);
void Thread_Call_Start2(pthread_t thread);
void Thread_Disable_Ints(void);
void Thread_Enable_Ints(void);
int Thread_Lock_System(void);
void Thread_Unlock_System(int);
void Thread_Init_Save_Area(char *);
void Thread_Yield(void);

// Claim the UNIX library stuff support
#define PIPELINE 8             /* pc offset due to pipelining */
#define BRANCH 0xEA000000      /* B instruction */
#define BRANCHLINK 0xEB000000      /* BL instruction */
#define BRANCH_MASK 0x00FFFFFF /* Address mask for B instruction */
#define MAXADDR_CODE (16*1024*1024)
#define OS_SynchroniseCodeAreas 0x6E /* A SWI number */
#define OS_Module 0x1E /* A SWI number */

struct s_ClaimBlock
{
	int space[13];
};

void ThreadClaim_Claim_Routine(void *routine,char *name,void *,void *);

extern char *ThreadClaim_FrontCode;
extern int ThreadClaimSize_FrontCode;

#endif

