/*************************************************************************\
 * Header file containing types and prototypes for thread-safe versions
 * of UCC libs.  This is not a shipping header file.
\*************************************************************************/
#if !defined(_THREAD_H) && defined(_OS9THREAD)
#define _THREAD_H

#ifndef _PTHREAD_H
#include <pthread.h>
#endif

#ifndef _SEMAPHORE_H
#include <semaphore.h>
#endif

#ifndef _TYPES_H
#include <types.h>
#endif

/* _getdata psects */
enum {
	/* clib.l */
	TD_TMPNAM,
	TD_ASCTIME,
	TD_GMTIME,
	TD_RAND,
	TD_SCANF,
	TD_STRERROR,
	TD_STRFTIME,
	TD_STRTOK,
	TD_TIME,
	TD_SIGNAL,
	TD_LOCALE,

	/* sys_clib.l */
	TD_SYSMKTIME,
	TD_WAITPID,

	/* unix.l */
	TD_ALARM,
	TD_BUILDPATH,
	TD_PWD,
	TD_SELECT,

	/* csl */
	TD_CSLC,
	TD_VSNPRINTF,

	/* more unix.l */
	TD_SETITIMER,
	
	NUM_DATAS			/* number of thread specific data's					*/
};

typedef enum {
	SUSPEND,						/* allow suspension while semaphore/monitor locked */
	UNSUSPEND						/* make unsuspendable before acquisition */
} susp_type;

typedef struct {
	semaphore		sem;			/* ownership semaphore					*/
	process_id		owner;			/* owner id (0 = none)					*/
	u_int32			link;			/* link count (number of locks)			*/
} monitor;

/* Items that need to be seen as one instance per application				*/
typedef struct {
	pthread_once_t 	init;			/* init block for creating data_key		*/
	pthread_key_t	data_key;		/* key for threads to use				*/
	monitor			_niob[32];		/* monitors for _niob array				*/
	semaphore		_environ_lock;	/* semaphore for _environ				*/
	void 			*sig_hands;		/* registered signal handlers list		*/
	semaphore		sig_lock;		/* lock for list of app's handled sigs  */
} global_data;

#define gdata_init		(*(global_data **)_pthread_global_slot(_PTHREAD_CLIB))->init
#define gdata_data_key	(*(global_data **)_pthread_global_slot(_PTHREAD_CLIB))->data_key
#define gdata_niob		(*(global_data **)_pthread_global_slot(_PTHREAD_CLIB))->_niob
#define gdata_environ_lock (*(global_data **)_pthread_global_slot(_PTHREAD_CLIB))->_environ_lock
#define gdata_sig_hands (*(global_data **)_pthread_global_slot(_PTHREAD_CLIB))->sig_hands
#define gdata_sig_lock (*(global_data **)_pthread_global_slot(_PTHREAD_CLIB))->sig_lock

extern monitor _glob_mon;		/* use to lock globals for short times */
extern semaphore _glob_sem;

void _lib_lock(semaphore *, susp_type);
void _lib_unlock(semaphore *, susp_type);

void *_getdata(u_int32 psect, size_t datasize, void (*initdata)(void *), void (*termdata)(void *));

void _monitor_lock(monitor *, susp_type);
void _monitor_unlock(monitor *, susp_type);

void _cs_thread_init(process_id proc_id);

/* The following is not prototyped in <pthread.h> */
error_code _pthread_init(process_id procid);

#endif /* _THREAD_H */
