/*
 *           PVM 3.0:  Parallel Virtual Machine System 3.0
 *               University of Tennessee, Knoxville TN.
 *           Oak Ridge National Laboratory, Oak Ridge TN.
 *                   Emory University, Atlanta GA.
 *      Authors:  A. L. Beguelin, J. J. Dongarra, G. A. Geist,
 *          R. J. Manchek, B. K. Moore, and V. S. Sunderam
 *                   (C) 1992 All Rights Reserved
 *
 *                              NOTICE
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted
 * provided that the above copyright notice appear in all copies and
 * that both the copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * Neither the Institutions (Emory University, Oak Ridge National
 * Laboratory, and University of Tennessee) nor the Authors make any
 * representations about the suitability of this software for any
 * purpose.  This software is provided ``as is'' without express or
 * implied warranty.
 *
 * PVM 3.0 was funded in part by the U.S. Department of Energy, the
 * National Science Foundation and the State of Tennessee.
 */

/*
 *  pvmshmem.h
 *
$Log: pvmshmem.h,v $
 * Revision 1.3  1994/11/08  15:38:05  manchek
 * shared memory damage control
 *
 */


/* 
 *		    Page Layout
 *		 _________________
 *		|      lock       | \
 *		|_________________|  \  PVMPAGEHDR
 *		|    ref count    |  /
 *		|=================| /
 *		|                 |
 *		|      frag       |
 *		|       .         |
 *		|       .         |
 *		|       .         |
 */

#ifdef IMA_SYMM
#define	PVMPAGEHDR			16
#define PVM_INITLOCK(cp)	s_init_lock((slock_t)(cp))
#define PVM_LOCK(cp)		s_lock((slock_t)(cp))
#define PVM_UNLOCK(cp)		s_unlock((slock_t)(cp))
#endif

/* page header and incoming message box header */

#ifdef IMA_KSR1

struct shmpghdr {				
	int		pg_ref;				/* count */
#define pg_lock	pg_ref
};
struct msgboxhdr {				
	int		mb_read;			/* message last read */
	int		mb_last;			/* message last received */
#define mb_lock mb_read
};
	
#define	PVMPAGEHDR			sizeof(struct shmpghdr)
#define PAGELOCK(cp)		_gspwt(cp)
#define PAGEUNLOCK(cp)		_rsp(cp)
#define _SC_PAGESIZE		_SC_PAGE_SIZE

#endif /*IMA_KSR1*/

#ifdef IMA_ALPHAMP

#include <sys/mman.h>

struct shmpghdr {
	msemaphore	pg_lock;			/* mutex lock */
	int		pg_priv;			/* TRUE if page is private */
	int		pg_ref;				/* reference count */
};
struct msgboxhdr {
	msemaphore	mb_lock;			/* mutex lock */
	int		mb_read;			/* message last read */
	int		mb_last;			/* message last received */
	int		mb_sleep;			/* Is task blocked on a semaphore? */
};
	
#define	PVMPAGEHDR			sizeof(struct shmpghdr)
				
#define PAGEINITLOCK(lp)	msem_init((lp), MSEM_UNLOCKED)
#define PAGELOCK(lp)		msem_lock((lp), 0)
#define PAGEUNLOCK(lp)		msem_unlock((lp), 0)

#endif /*IMA_ALPHAMP*/

#ifdef IMA_SUNMP

#include <synch.h>

struct shmpghdr {
	mutex_t	pg_lock;			/* mutex lock */
	int		pg_priv;			/* TRUE if page is private */
	int		pg_ref;				/* reference count */
};
struct msgboxhdr {
	mutex_t	mb_lock;			/* mutex lock */
	int		mb_read;			/* message last read */
	int		mb_last;			/* message last received */
	int 	mb_sleep;			/* Is task blocked on a semaphore? */
	cond_t	mb_cond;			/* condition to block on */
};
	
#define	PVMPAGEHDR			sizeof(struct shmpghdr)
				
#define PAGEINITLOCK(lp)	mutex_init((lp), USYNC_PROCESS, 0)
#define PAGELOCK(lp)		mutex_lock(lp)
#define PAGEUNLOCK(lp)		mutex_unlock(lp)
/*
#define PAGEINITLOCK(p)		\
				mutex_init(&((struct shmpghdr *)(p))->pg_lock,USYNC_PROCESS,0)
#define PAGELOCK(p)			mutex_lock(&((struct shmpghdr *)(p))->pg_lock)
#define PAGEUNLOCK(p)		mutex_unlock(&((struct shmpghdr *)(p))->pg_lock)
#define PAGEREFCOUNT(cp)	(((shmpghdr*)(cp-PVMPAGEHDR))->pg_ref) 
*/

#endif /*IMA_SUNMP*/

#if defined(IMA_SGIMP) || defined(IMA_SGIMP64)

#include <mutex.h>

struct shmpghdr {
	unsigned long	pg_lock;
	int				pg_priv;		/* TRUE if page is private */
	unsigned long	pg_ref;			/* reference count */
};

struct msgboxhdr {
	unsigned long	mb_lock;		/* mutex lock */
	int				mb_read;		/* message last read */
	int				mb_last;		/* message last received */
	int 			mb_sleep;		/* Is task blocked on a semaphore? */
};

#define PAGEINITLOCK(lp)	(*(lp) = 0)
#define PAGELOCK(lp)		while(test_then_add(lp, 1)) test_then_add(lp, -1L)
#define PAGEUNLOCK(lp)		test_then_add(lp, -1L)
#define	TEST_ADD(addr,inc)	test_then_add(addr, (long)inc)

#define	PVMPAGEHDR			sizeof(struct shmpghdr)

/*
#define PAGEINITLOCK(lp)	init_lock(lp)
#define PAGELOCK(lp)		while(acquire_lock(lp))
#define PAGEUNLOCK(lp)		release_lock(lp)
*/

#endif /*IMA_SGIMP || IMA_SGIMP64*/

#ifdef IMA_POWER4

#ifndef _POWER4
#define _POWER4
#endif

#include <power4_ipc.h>

struct shmpghdr {
	int		pg_lock;			/* page lock */
	int		pg_priv;			/* TRUE if page is private */
	int		pg_ref;				/* reference count */
};

struct msgboxhdr {
	int		mb_lock;			/* mutex lock */
	int		mb_read;			/* message last read */
	int		mb_last;			/* message last received */
	int 	mb_sleep;			/* Is task blocked on a semaphore? */
};

struct gtask {					/* global task table entry */
	int gt_tid;					/* PVM task id */
	int gt_stat;				/* Is it ready to recv msg? */
};

#define	PVMPAGEHDR			sizeof(struct shmpghdr)
#define _SC_PAGESIZE		_SC_PAGE_SIZE
#define PAGEINITLOCK(lp)	(*(lp) = 0)
/* XXX oh, kill me with a shovel.  nice place for a while. -b */
#define PAGELOCK(lp)		while(gcs(lp,0,1))
#define PAGEUNLOCK(lp)		gcs(lp,1,0)

#endif /*POWER4*/

/* header of pid -> tid table */

struct pidtidhdr {
	int i_proto;				/* t-d protocol */
	int i_ndf;					/* native data format */
	int i_next;					/* pointer to pid->tid table */
	int i_bufsiz;				/* shared-memory buffer size */
	int i_dpid;					/* pvmd's Unix proc ID */
};

/* pid -> tid table entry */

struct pidtid {
	int	pt_pid;					/* Unix proc id */
	int pt_tid;					/* PVM task id */
	int pt_ptid;				/* PVM parent task id */
	int pt_stat;				/* Is it ready to recv msg? */
};
#define ST_NOTREADY		0		/* not ready */
#define ST_SHMEM		1		/* has shared-memory buffer */
#define ST_SOCKET		2		/* has socket connection */
#define ST_EXIT			-1		/* gone */

/* packet header */

struct shmpkhdr {
	int ph_src;					/* sender's tid */
	int ph_dst;					/* receiver's tid */
	int ph_dat;					/* message body's location in sender's buf */
	int ph_flag;				/* flags */
};

/* tasks whose msg buf has been mapped into our address space */

struct peer {
	struct peer *p_link;		/* dll */
	struct peer *p_rlink;
	int p_tid;					/* task ID */
	int p_shmid;				/* shared-memory ID of msg buffer */
	int p_semid;				/* semaphore ID */
	char *p_buf;				/* peer's msg buffer */
	char *p_dbuf;				/* my dynamic buffer for this guy */
	int p_dlen;					/* size of dynamic buffer */
};


/* misc */

#define PDMNODE		128			/* pvmd debug mask */
#define MAXFRAGSIZE	0x1000		/* max fragment size (4K) */
#define SHMBUFSIZE	0x100000	/* 1 MB of shared msg buffer for each task */
#define INBOXPAGE	5			/* size of incoming box (number of pages) */
#define FRAGPAGE	1			/* number of pages in each fragment */
#define PERMS		0600		/* permissions for shared-memory msg buffers */
#define	BUSYWAIT	1000000		/* max wait cycles before backing off */
#define PVMSHMFILE  "/tmp/pvmshm.%d"	/* file to map to shared memory */

struct peer *peer_conn __ProtoGlarp__((int tid));
void peer_init __ProtoGlarp__((void));
void peer_wake __ProtoGlarp__((struct peer *pp));
void peer_cleanup __ProtoGlarp__((void));
