/* @(#) process.h 1.1 94/10/31 Copyr 1987 Sun Micro */
/* Copyright (C) 1987. Sun Microsystems, Inc. */
/*
 * This source code is a product of Sun Microsystems, Inc. and is provided
 * for unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.  Users
 * may copy or modify this source code without charge, but are not authorized
 * to license or distribute it to anyone else except as part of a product or
 * program developed by the user.
 *
 * THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
 * AND IS LICENSED TO SUNSOFT, INC., A SUBSIDIARY OF SUN MICROSYSTEMS, INC.
 * SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
 * OF SUCH SOURCE CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT
 * EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  SUN MICROSYSTEMS, INC. DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN
 * NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
 * 
 * This source code is provided with no support and without any obligation on
 * the part of Sun Microsystems, Inc. to assist in its use, correction, 
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
 * SOURCE CODE OR ANY PART THEREOF.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California 94043
 */
#ifndef _lwp_process_h
#define _lwp_process_h

/*
 * Which queue or state a thread belongs to (if not on any queue)
 * A thread never belongs to more than one queue.
 */
typedef enum lwp_state_t {
	RS_UNBLOCKED	=0,	/* Runnable (__RunQ) */
	RS_SEND		=1,	/* Blocked on a send (__SendQ) */
	RS_RECEIVE	=2,	/* Blocked on a receive (__ReceiveQ) */
	RS_SLEEP	=3,	/* Sleeping for finite time (__SleepQ) */
	RS_MONITOR	=4,	/* Blocked on a monitor (__MonitorQ) */
	RS_CONDVAR	=5,	/* Blocked on a condition var (__CondvarQ) */
	RS_SUSPEND	=6,	/* Suspended (__SuspendQ) */
	RS_ZOMBIE	=7,	/* Dead but memory kept around until msg reply */
	RS_JOIN		=8,	/* Blocked on a join */
	RS_UNINIT	=9,	/* Not on any queue, uninitialized */
} lwp_state_t;

/*
 * Context block for lightweight process.
 */
typedef struct lwp_t {
	struct lwp_t *lwp_next;		/* list of processes blocked together */
	object_type_t lwp_type;		/* type (agt/lwp) (MUST BE 2'nd) */
	machstate_t lwp_machstate;	/* machine-dependent state */
	qheader_t lwp_ctx;		/* special context save/restore actions */
	bool_t lwp_full;		/* TRUE if rti resume, else coroutine */
	bool_t lwp_suspended;		/* TRUE if to be suspended */
	enum lwp_state_t lwp_run;	/* which queue holds the process */
	enum lwp_err_t lwp_lwperrno;	/* errors in primitives */
	qheader_t lwp_messages;		/* list of unreceived messages */
	caddr_t lwp_blockedon; 		/* entity waited upon */
	struct monitor_t *lwp_curmon;	/* currently-held monitor */
	int lwp_monlevel;		/* nesting level of reentrant monitor */
	struct msg_t lwp_tag;		/* message sent by this thread */
	qheader_t lwp_exchandles;	/* stack of exception handlers */
	qheader_t lwp_joinq;		/* threads awaiting this thread's death */
	int lwp_prio;			/* scheduling priority, higher favored */
	int lwp_flags;			/* LWPSUSPEND|LWPSERVER|LWPNOLASTRITES */
	int lwp_stack;			/* stack arg, passed to LASTRITES agt */
	int lwp_lock;			/* for validity checks */
	int lwp_cancel;			/* for kernel: TRUE if unwanted */
} lwp_t;
#define	LWPNULL ((lwp_t *) 0)
#define	NOBODY	CHARNULL	/* lwp_blockedon: not waiting on any object */

/*
 * Manipulate client error setting/clearing
 */
#define	SET_ERROR(proc, err)	{					\
	if ((proc != LWPNULL)) {					\
		(proc)->lwp_lwperrno = err;				\
	}								\
}
#define	IS_ERROR()							\
	(__Curproc->lwp_lwperrno != LE_NOERROR) 			\

#define	CLR_ERROR()	{						\
	if ((__Curproc != LWPNULL)) {					\
		__Curproc->lwp_lwperrno = LE_NOERROR;			\
	}								\
}

#define	NUGPRIO		0	/* idle priority (no other lwp this low) */

/*
 * Conditionally give up the processor if "prio" warrants it.
 * Always UNLOCKED when it returns, either via WAIT or UNLOCK.
 */
#define	YIELD_CPU(prio) {				\
	if (prio > __Curproc->lwp_prio) {		\
		__HighPrio = prio;			\
		WAIT();					\
	} else {					\
		UNLOCK();				\
	}						\
}

/*
 * Remove the specified process from the run
 * queue and set it's new state:
 * which queue it will be blocked on and which object can unblock it
 * (if applicable).
 */
#define	BLOCK(pro, state, waiton)	{				\
	REMX_ITEM(&__RunQ[pro->lwp_prio], pro);				\
	pro->lwp_run = state;						\
	pro->lwp_blockedon = (caddr_t)waiton;				\
	__Nrunnable--;							\
}

/*
 * Put a process back on the run queue. lwp_run prevents
 * a wakeup from unblocking an unblocked process.
 * Do this AFTER deueueing from whatever queue the process was on before.
 * If the (blocked) process is suspended, we now alter its status
 * to the suspended state (and __HighPrio remains the same since no new
 * runnable process was added).
 */
#define	UNBLOCK(dest) {								\
	if ((dest)->lwp_run != RS_UNBLOCKED) {					\
		if ((dest)->lwp_suspended) {					\
			ASSERT((dest) != __Curproc);				\
			INS_QUEUE(&__SuspendQ, dest);				\
			(dest)->lwp_run = RS_SUSPEND;				\
		} else {							\
			INS_QUEUE(&__RunQ[dest->lwp_prio], dest);		\
			__HighPrio = MAX(__HighPrio, (dest)->lwp_prio);		\
			(dest)->lwp_run = RS_UNBLOCKED;				\
		}								\
		(dest)->lwp_blockedon = NOBODY;					\
	}									\
	__Nrunnable++;								\
}

extern qheader_t __SuspendQ;	/* Queue of suspended processes */
extern qheader_t __SleepQ;	/* place to put processes sleeping on an alarm */
extern qheader_t __ZombieQ;	/* Queue of zombies (killed during send) */
extern int __LwpRunCnt;		/* Number of lwp's in the system */
extern thread_t __Slaves[];	/* list of server threads */
extern int __SlaveThreads;	/* index of free server thread */
extern int __NActiveSlaves;	/* count of living slave threads */
extern int __Nrunnable;		/* number of runnable threads */
extern void __freeproc(/* lwp */);	/* free lwp resources */
extern void __rem_corpse(/* queue, corpse, error */);	/* remove a dead lwp */
extern void __init_lwp();	/* initialize lwp library */
extern void __maincreate();	/* turn main into a l wp */

#endif /*!_lwp_process_h*/
