/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 *
 *	$Id: kreq.h,v 6.5 1999/06/16 05:54:52 jsquyres Exp $
 *
 *	Function:	- kernel request constants and templates
 */

#ifndef _KREQ
#define _KREQ

#include <lam_config.h>
#include <all_queue.h>
#include <portable.h>

#define KTYPEHI		0xffff0000
#define KTYPELO		0x0000ffff
#define KEVENTHI	0x7fff0000

#define ksync_type(a, b) ((a == 0) || (b == 0) || (a & b))

#define ksync_type_sql(a, b) ((((a & KTYPEHI) == KTYPEHI) || \
		((b & KTYPEHI) == KTYPEHI) || \
		((a & KTYPEHI) == (b & KTYPEHI))) && \
		(((a & KTYPELO) == KTYPELO) || \
		((b & KTYPELO) == KTYPELO) || \
		((a & KTYPELO) == (b & KTYPELO))))

#define ksync_event(a, b) (a == b)

#define ksync_event_sql(a, b) (((a & ~KEVENTHI) == (b & ~KEVENTHI)) && \
		(((a & KEVENTHI) == KEVENTHI) || \
		((b & KEVENTHI) == KEVENTHI) || \
		((a & KEVENTHI) == (b & KEVENTHI))))
/*
 * KSYNCSQL is triggered by the blocked process.  KSYNCSQL will only
 * be used on the second half of a KQSR and only by external processes.
 */
#define ksync_cmp(p, q) ((p->kp_msg.k_flags & KSYNCSQL) ? \
		(ksync_event_sql(p->kp_msg.k_event, (q).k_event) && \
		ksync_type_sql(p->kp_msg.k_type, (q).k_type)) : \
		(ksync_event(p->kp_msg.k_event, (q).k_event) && \
		ksync_type(p->kp_msg.k_type, (q).k_type)))

/*
 * kernel message descriptor
 */
struct kmsg {
	int4		k_event;	/* message event (==) */
	int4		k_type;		/* message type (& or SQL) */
	int4		k_length;	/* message length */
	int4		k_flags;	/* option flags, jives with nh_flags */
#define	KSYNCSQL	0x01		/* use SQL rules for sync */
#define	KTRY		0x02		/* error if block */
#define	KNMSG		0x04		/* k_msg is struct nmsg */
#define	KPROBE		0x08		/* KQRECV is probe only */
#define	KTRACE		0x20		/* time kernel operations */
	char		*k_msg;		/* message body */
};

/*
 * kernel request codes
 */
#define KQSEND		0		/* send a message to a process */
#define KQRECV		1		/* receive a message from a process */
#define KQSTATE		2		/* get the state of a process */
#define KQDOOM		3		/* signal a process */
#define KQSR		4		/* send then recv */

#define KQATTACH	5		/* attach process */
#define KQSURRENDER	6		/* create a process */
#define KQMAX		7		/* # kernel client requests */

/*
 * non-client kernel requests
 */
#define KQDETACH	7		/* end kernel session */
#define KQDUMP		8		/* print process descriptors */

/*
 * process states
 */
#define KSREADY		0		/* ready to run */
#define KSSEND		1		/* send blocked */
#define KSRECV		2		/* receive blocked */
#define KSFREE		3		/* not in use */

/*
 * process flags
 */
#define KSURRENDER	2		/* process should surrender */
#define KIPROC		0x10		/* internal process */
#define KMSG2		0x20		/* send blocked process is KQSR */

/*
 * limits
 */
#define KPMAX		72		/* max # kernel processes */
#define KLENQ		8		/* initial kreq queue length */
#define KNFYI		9		/* debugging info size */
#define KPKTLEN		(8192 + sizeof(struct nmsg))
					/* message transfer packet length */

/*
 * kernel request
 */
struct kreq {
	int4		kq_req;
	int4		kq_index;
	int4		kq_pid;
	int4		kq_priority;
	int4		kq_signal;
	int4		kq_fyi[KNFYI];
	struct kmsg	kq_msg;
	struct kmsg	kq_msg2;	/* 2nd half of KQSR */
};

/*
 * kernel reply
 */
struct kreply {
	int4		kr_reply;
	int4		kr_signal;
	int4		kr_length;
	int4		kr_event;
	int4		kr_type;
	int4		kr_state;
	int4		kr_priority;
	int4		kr_index;
	int4		kr_sigs;	/* for KQSTATE */
	int4		kr_fyi[KNFYI];
	double		kr_blktime;	/* time spent blocking */
};

/*
 * kernel process status
 */
struct kstatus {
	int4		ks_state;
	int4		ks_priority;
	int4		ks_signal;
	int4		ks_event;
	int4		ks_type;
	int4		ks_length;
	int4		ks_fyi[KNFYI];
};

/*
 * kernel process descriptor
 */
struct kproc {
	struct kproc	*kp_next;	/* linked list */
	int4		kp_pid;		/* process identifier */
	int4		kp_index;	/* desc. index */
	int4		kp_priority;	/* process priority */
	int4		kp_port;	/* communication port */
	int4		kp_state;	/* process state */
	int4		kp_signal;	/* pending signals */
	int4		kp_flags;	/* misc. information */
	int4		kp_fyi[KNFYI];	/* misc. debugging info */
	struct kmsg	kp_msg;		/* blocked message */
	struct kmsg	kp_msg2;	/* 2nd half of KQSR */
	QUEUE		*kp_kqueue;	/* internal request queue */
	void		(*((*kp_run)()))();
					/* internal client code */
	double		kp_blktime;	/* start of blocking */
};

#ifdef __cplusplus
extern "C" {
#endif

extern int		atkexit(void (*exitfunc)(), char *arg);
extern int		kattach(int pri);
extern int		kbgetpid(void);
extern int		kcreate(const char *path, char **argv);
extern int		kcreatev(const char *path, char **argv,
    				char **envv, char *wrkdir, int *fds);
extern int		kdetach(int pid);
extern int		kenter(const char *name, int pri);
extern int		kinit(int pri);
extern int		krecv(struct kmsg *pkmsg);
extern int		krecvfront(struct kmsg *pkmsg);
extern int		krecvback(struct kmsg *pkmsg);
extern int		ksend(struct kmsg *pkmsg);
extern int		ksr(struct kmsg *pkmsg, struct kmsg *pkmsg2);
extern int		ksrfront(struct kmsg *pkmsg, struct kmsg *pkmsg2);
extern int		ksrback(struct kmsg *pkmsg2);
extern int		kstate(int pid, struct kstatus *pstate);
extern void		kexit(int status);
extern void		_kexit(int status);

#ifdef __cplusplus
}
#endif

#endif
