/*
 *  pthread/qnx.h
 *
 *  Copyright by QNX Software Systems Limited 1995-1996. All rights reserved.
 */
#ifndef __NEUTRINO_H_INCLUDED
#define __NEUTRINO_H_INCLUDED

#ifndef __LIMITS_H_INCLUDED
 #include <limits.h>
#endif

#ifndef __TYPES_H_INCLUDED
 #include <sys/types.h>
#endif

#ifndef _SCHED_H_INCLUDED
 #include <sys/sched.h>
#endif

#ifndef _TIME_H_INCLUDED
 #include <time.h>
#endif

#ifndef _SIGNAL_H_INCLUDED
 #include <signal.h>
#endif

#ifndef _LIMITS_H_INCLUDED
 #include <limits.h>
#endif

#if __WATCOMC__ > 1000
#pragma pack(push,1);
#else
#pragma pack(1);
#endif

typedef struct {
    void *ss_sp;
    size_t ss_size;
} tstack_t;

#ifdef __cplusplus
extern "C" {
#endif
struct _sync;
typedef struct _sync sync_t;

/*
 * Define the states of a thread
 * THREAD.state
 */

#include <sys/kernel.h>
#include <sys/proc_msg.h>

#define STATE_INIT              -1
#define STATE_DEAD              0
#define STATE_READY             1
#define STATE_SEND_BLOCKED      2
#define STATE_RECEIVE_BLOCKED   3
#define STATE_REPLY_BLOCKED     4
#define STATE_HELD              5
#define STATE_SIGNAL_BLOCKED    6
#define STATE_WAIT_BLOCKED      7
#define STATE_SEM_BLOCKED       8
#define STATE_CONDVAR		9
#define STATE_MUTEX		10
#define STATE_JOIN		11


#define PTHREAD_STACK_MIN 0x1000

#define PTHREAD_STYPE_MASK				0x180
#define PTHREAD_STACK_MAPPED				0x080
#define PTHREAD_STACK_MALLOCED				0x100

#define _NTO_TIMEOUT_RECEIVE		(1<<STATE_RECEIVE)
#define _NTO_TIMEOUT_SEND			(1<<STATE_SEND)
#define _NTO_TIMEOUT_REPLY			(1<<STATE_REPLY)
#define _NTO_TIMEOUT_WAITPAGE		(1<<STATE_WAITPAGE)
#define _NTO_TIMEOUT_SIGSUSPEND		(1<<STATE_SIGSUSPEND)
#define _NTO_TIMEOUT_SIGWAITINFO	(1<<STATE_SIGWAITINFO)
#define _NTO_TIMEOUT_NANOSLEEP		(1<<STATE_NANOSLEEP)
#define _NTO_TIMEOUT_MUTEX			(1<<STATE_MUTEX)
#define _NTO_TIMEOUT_CONDVAR		(1<<STATE_CONDVAR)
#define _NTO_TIMEOUT_JOIN			(1<<STATE_JOIN)
#define _NTO_TIMEOUT_INTR			(1<<STATE_INTR)
#define _NTO_TIMEOUT_SEM			(1<<STATE_SEM)


/*
 Thread Control commands
*/
#define _NTO_TCTL_IO			1
#define _NTO_TCTL_THREADS_HOLD	2
#define _NTO_TCTL_THREADS_CONT	3
#define _NTO_TCTL_RUNMASK		4
#define _NTO_TCTL_ALIGN_FAULT	5

/*
 Define flags of a timeout
 The first n bits are reserved for (1L << thp->state)
*/
#define _NTO_TIMEOUT_MASK		((1 << STATE_MAX) - 1)
#define _NTO_TIMEOUT_ACTIVE		(1 << STATE_MAX)
#define _NTO_TIMEOUT_IMMEDIATE	(1<<STATE_MAX+1)

struct _thread_local_storage;
typedef struct _thread_local_storage *TID;
typedef struct _thread_local_storage *tid_t;

/*
// owner
//  -1       Static initalized mutex which is auto created on SyncWait
//  -2       Destroyed mutex
//  -3       Named semaphore (the count is used as an fd)
*/
struct _sync {
	int		count;		/* Count for recursive mutexs and semaphores */
	int		owner;		/* Thread id (valid for mutex only) */
	tid_t		waiters;
	struct _sync	*next;
	union {
	    struct {
		int		ceiling;
		}		mutex;
	    } un;
	};

typedef struct _sync_attr {
	int		protocol;
	int		flags;
	int		prioceiling;	/* Not implemented */
	} sync_attr_t;

struct _sync_info {
	pid_t	pid;
	tid_t	tid;
	int	count;
	};

typedef struct _timeout {
	int		kind;
	int		flags;
	struct sigevent	notify;
	struct timespec	when;
} timeout_t;

struct _ker_thread_storage {
    int		 status;
    int		 flags;
    tstack_t	 stack;
    tid_t	 tls;
};

extern struct _ker_thread_storage primordial_kthread;

#define PTHREAD_FLAGS(tid)	(*((tid)->kthread ? &(tid)->kthread->flags : &primordial_kthread.flags))
#define PTHREAD_STACK(tid)	(*((tid)->kthread ? &(tid)->kthread->stack : &primordial_kthread.stack))

/*
 Thread local storage. This data is at the top of each threads stack.
*/
struct _thread_local_storage {
	struct _ker_thread_storage	*kthread;
	int				 state;
	void				*(*startfunc)(void *);
	void				*arg;
	pid_t				pid;
	union {
	    pid_t			tid;
	    unsigned			owner;
	};
	pid_t				ptid;
	short				prio : 8;	/* base priority */
	short				curprio : 8;	/* priority */
	short				policy : 8;	/* sched policy */
	short				pad : 8;	/* padding */
	int				numkeys;
	void				**keydata;	/* Indexed by pthread_key_t */
	void				*cleanup;
	int				wakeup_result;
	sync_t				*blocked_on;
	sync_t				*requires;	/* place-holder for a mutex */
	int				required_count;
	void				*status;
	struct _sync			join;
	struct _thread_local_storage	*waitq;
	timer_t				timer;
	timeout_t			timeout;
	void				*thread_data;
	sync_t				*held;
	sigset_t			sigmask;
	siginfo_t			info;
	} ;

#include <sys/magic.h>
extern struct _thread_local_storage	primordial_thread;
#define _TLS	((tid_t)__MAGIC.unknown_sptrs[1] ? \
		(tid_t)__MAGIC.unknown_sptrs[1] : \
		(tid_t)ThreadBootstrap())

/*
 Used to define thread creation attributes.
 */
struct _thread_attr {
	int			flags;
	size_t			stacksize;
	void			*stackaddr;
	void			(*exitfunc)(void *status);
	int			policy;
	struct sched_param	param;
	int			spare[4];
	} ;
	

/* Synchronization manifests and structures.
// Synchronization manifests and structures.
*/

#define _NTO_SYNC_WAITING		(~0u ^ (~0u >> 1))	// On owner
#define _NTO_SYNC_NONRECURSIVE	(~0u ^ (~0u >> 1))	// On count


/*
 * Limits
 */
#define LIMITS_PROCESS		0
#define LIMITS_THREAD		1
#define LIMITS_TIMER		2
#define LIMITS_PULSE		3
#define LIMITS_SYNC			4
#define LIMITS_CONNECT		5
#define LIMITS_CHANNEL		6
#define LIMITS_INTERRUPT	7
#define LIMITS_NUM			8

enum {
	__KER_THREAD_CREATE = _PROC_LAST+1,
	__KER_THREAD_DESTROY,
	__KER_THREAD_DESTROYALL,
	__KER_THREAD_DETACH,
	__KER_THREAD_JOIN,
	__KER_THREAD_CANCEL,

	__KER_TIMER_CREATE,
	__KER_TIMER_DESTROY,
	__KER_TIMER_GETTIME,
	__KER_TIMER_SETTIME,
	__KER_TIMER_GETOVERRUN,
	__KER_TIMER_ALARM,
	__KER_TIMER_TIMEOUT,
	__KER_TIMER_WAIT,

	__KER_SYNC_CREATE,
	__KER_SYNC_DESTROY,
	__KER_SYNC_MUTEX_LOCK,
	__KER_SYNC_MUTEX_UNLOCK,
	__KER_SYNC_CONDVAR_WAIT,
	__KER_SYNC_CONDVAR_SIGNAL,
	__KER_SYNC_SEM_POST,	
	__KER_SYNC_SEM_WAIT,

	__KER_SCHED_GET,
	__KER_SCHED_SET,

	__KER_PROC_EXIT,
	} ;

#define __KER_LAST	__KER_PROC_EXIT

#define TID_ERR	NULL

/*
 * More hacks
 */
extern int _multi_threaded;

#define	SCHED_NOCHANGE	SCHED_OTHER

/*
 * Required for the bootstrap start functions:
 */
#pragma aux REG_FUNC "*" parm [eax edx ecx edx];

int ThreadCreate_r(pid_t pid, void (*func)(void *arg), void *arg, struct _thread_attr *attr);
int ThreadDestroy_r(int tid, int priority, void *status);
int ThreadJoin_r(int tid, void **status);
int ThreadCancel_r(int tid, void (*canstub)(void));

int SchedGet(pid_t pid, int tid, struct sched_param *param);
int SchedGet_r(pid_t pid, int tid, struct sched_param *param);
int SchedSet(pid_t pid, int tid, int algorithm, struct sched_param *param);
int SchedSet_r(pid_t pid, int tid, int algorithm, struct sched_param *param);
int SchedYield(void);
int SchedYield_r(void);

int TimerCreate(clockid_t id, const struct sigevent *notify);
int TimerCreate_r(clockid_t id, const struct sigevent *notify);
int TimerDestroy_r(timer_t id);
int TimerGettime_r(timer_t id, struct itimerspec *itime);
int TimerSettime_r(timer_t id, int flags, const struct itimerspec *itime, struct itimerspec *otime);
int TimerGetoverrun_r(timer_t id);

int TimerTimeout_r(int flags, const struct sigevent *notify, const struct timespec *ntime,
							struct timespec *otime);

int SyncCreate_r(sync_t *sync, struct _sync_attr *attr);
int SyncDestroy_r(sync_t *sync);
int SyncMutexLock_r(sync_t *sync);
int SyncMutexUnlock_r(sync_t *sync);
int SyncCondvarWait_r(sync_t *sync, sync_t *mutex);
int SyncCondvarSignal_r(sync_t *sync, int all);
int SyncSemPost_r(sync_t *sync);
int SyncSemWait_r(sync_t *sync, int tryto);

ulong_t		_ebp(void);
#pragma aux _ebp = "mov eax,ebp" parm nomemory [] \
		modify nomemory exact [eax] value [eax];

void		ldebp(ulong_t ebp);
#pragma aux ldebp = "mov ebp,eax" \
		parm nomemory [eax] \
		modify exact nomemory [ ];

#ifdef __cplusplus
};
#endif

#if __WATCOMC__ > 1000
#pragma pack(pop);
#else
#pragma pack();
#endif

#endif
