/*	Copyright  (c)	Günter Woigk  1990-2000
  					mailto:kio@little-bat.de

 	This program is distributed in the hope that it will be useful,
 	but WITHOUT ANY WARRANTY; without even the implied warranty of
 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

 	Permission to use, copy, modify, distribute, and sell this software and
 	its documentation for any purpose is hereby granted without fee, provided
 	that the above copyright notice appear in all copies and that both that
 	copyright notice and this permission notice appear in supporting
 	documentation, and that the name of the copyright holder not be used
 	in advertising or publicity pertaining to distribution of the software
 	without specific, written prior permission.  The copyright holder makes no
 	representations about the suitability of this software for any purpose.
 	It is provided "as is" without express or implied warranty.

 	THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 	INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 	EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 	CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 	DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 	TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 	PERFORMANCE OF THIS SOFTWARE.
*/


#ifdef  _disp_h_		// this file should only be included by disp.h




const	size_t		minStackFree	=	MINSTACKFREE;



/* ----	thread work space -----------------------------------------
*/
class Twsp
{
friend			class 	Sema;
friend			class 	Irpt;
friend	static	void	swap_registers	( Tid, Tid );
friend	static	bool	Switch			( Tid );
friend			Tid		Split			( ThreadProc, void*, ulong, ulong, cstr );
friend			void	StartDispatcher	( );
friend	static	void	CallEntry 		( void );
friend	static	char*	QString			( int );
friend			int		NumThreads		( long mask );
friend			bool	IsValidTid		( Tid tid );
friend			Tid		GetTid			( cstr name );
friend inline	void	CheckMagic 		( Tid t );
friend static	void	XXCHECK			( Tid t );
friend inline	void	XXCHECK			( );

private:
		long		state;				// running, suspended, irptshed, semashed, timeshed
		ulong		prio;				// thread priority: lower is better
#if SEMA_BOOST
		ulong		prio_org;			// nominal priority (most times same as prio)
#endif

		Tid			next;				// linking in t_running, t_suspended or t_timeshed list
		Tid			prev;
		
		Tid			next_w;				// linking in sema.wait or Irpt.wait
		Tid			prev_w;
		union
		{	Sema*	sema;				// Sema for which thread is waiting
			Irpt*	irpt;				// Irpt for which thread is sheduled
		};
		long		time;				// alarm time for which thread is sheduled

#if SEMA_BOOST
		Sema*		blocked_sems;		// linked list of Semas blocked by this thread
#endif

		ptr			stack_top;			// start of stack
		ptr			stack_lower_limit;	// stack lower limit

		jmp_buf		registers;			// saved registers for setjmp() and longjmp()

		char*		qspool;				// quick string pool for cstrings.cp
		int			qsidx;				// allocation index in quick string pool
		char*		name;				// thread's name
		long		ptime;				// process time for this thread
		void*		split_data;			// data pointer on thread start
		ThreadProc 	split_proc;			// thread start procedure address
		long		magic;				// security word
		enum	  {	cMagic = 0xE7D67506 };


/* ----	methods --------------------------------------------
*/
private:
inline	void		load_registers		( );
inline	int			save_registers		( );
static	void		swap_registers		( Tid, Tid );
static	void		kill_zombie			( );
inline	void		purge				( );

		void		unlink_running 		( );
		void 		unlink_suspended	( );
		void 		unlink_timeshed 	( );
		void 		unlink_semashed 	( );
		void 		unlink_irptshed 	( );
		void		link_running 		( );
		void 		link_suspended 		( );
		void 		link_timeshed 		( long alarmtime );
		void 		link_semashed 		( Sema* );
		void 		link_irptshed 		( Irpt* );
		void		change_prio 		( ulong newprio );

		ptr 		stack_ptr 			( );
		size_t		stack_size			( )			{ return stack_top - stack_lower_limit; }
		void		check_stack			( );

		Tid			Next				( )			{ return next; }
		Tid			Prev				( )			{ return prev; }

		bool		MagicOk				( )			{ return magic==cMagic; }
		bool		MagicError			( )			{ return magic!=cMagic; }
static	void		CHECK				( );

public:
		size_t 		StackFree 			( )			{ return stack_ptr() - stack_lower_limit; }

		long		State				( )			{ return state; }
#if SEMA_BOOST
		ulong		Prio				( )			{ return prio_org; }
#else
		ulong		Prio				( )			{ return prio; }
#endif
		long		Timeout				( )			{ return time; }
		cstr 		Name				( )			{ return name; }
		long&		Ptime				( )			{ return ptime;}
		
		void		Termi				( );
		void		Suspend				( );
		void		Resume				( );
		void		Wait				( long );	// wait duration
		void		Shedule				( long );	// wait until clock
		void		ChangePrio			( ulong);	// change thread's priority
};




#endif
