
/*
 * pr_shm_ipc.h
 *
 * System V Shared Memory protocol configuration
 * 
 *
static rcsid = "$Header: /home/globdev/CVS/globus-packages/nexus/source/nexus/pr_shm_ipc.h,v 1.3 1997/09/05 18:36:41 scofield Exp $"
*/

#include <sys/shm.h>

/*
 * SHMEM_PROTO_IS_THREAD_SAFE
 *
 * It is advantageous if an SHM module be thread safe, since this
 * allows you to simply create a handler thread which blocks on a
 * receive, and automatically wakes up and handles the message when
 * one arrives.
 *
 * In order for an SHMEM module to be considered "thread safe", the
 * following must be true:
 *   1) One thread can be doing a blocking receive, while other threads
 *	are simultaneously doing sends.
 *   2) A thread can send a message to its own node, which will
 *	be received by the blocking receive in the handler thread.
 *   3) Thread locks are process shared as indicated by the compile
 *      time define _POSIX_THREAD_PROCESS_SHARED.
 *
 * If these conditions are true, then #define SHMEM_PROTO_IS_THREAD_SAFE
 */
#ifdef _POSIX_THREAD_PROCESS_SHARED
/*#define SHMEM_PROTO_IS_THREAD_SAFE*/
#endif


/*
 * shm_destination_t
 *
 * This encapsulates the information about a node to which we
 * may send messages.
 */
typedef long shm_destination_t;


/*
 * shm_handle_t
 *
 * This contains the shared memory segment identifier.
 *
 */
typedef int shm_handle_t;


/*
 * SHMEM_COMPARE_DESTINATIONS(shm_destination_t D1, shm_destination_t D2,
 *		  	    nexus_bool_t Result)
 *
 * Set Result==NEXUS_TRUE if shm_destination_t's D1 and D2 are the same.
 */
#define SHMEM_COMPARE_DESTINATIONS(D1, D2, Result) \
    Result = (((D1) == (D2)) ? NEXUS_TRUE : NEXUS_FALSE)


/*
 * SHMEM_COPY_DESTINATION(shm_destination_t To, shm_destination_t From)
 *
 * Copy shm_destination_t 'From' to 'To'.
 */
#define SHMEM_COPY_DESTINATION(To, From) \
    (To) = (From)


/*
 * SHMEM_HASH_DESTINATION(shm_destination_t Dest, int Hash)
 *
 * Hash the destination information into a value
 * between 0 and PROTO_TABLE_SIZE.
 */
#define SHMEM_HASH_DESTINATION(Dest, Hash) \
    (Hash) = ((Dest) % PROTO_TABLE_SIZE)


/*
 * SHMEM_GET_MY_MI_PROTO_SIZE(int Size)
 *
 * Fillin Size with the number of bytes I need to store my_node
 * into the mi_proto byte array.
 */
#define SHMEM_GET_MY_MI_PROTO_SIZE(Size) (Size) = sizeof(shm_destination_t)


/*
 * SHMEM_GET_MY_MI_PROTO(nexus_byte_t *Array, shm_destination_t My_Node)
 *
 * Fillin my_node into the mi_proto byte array
 */
#define SHMEM_GET_MY_MI_PROTO(Array, My_Node) \
{ \
    memcpy((Array), &My_Node, sizeof(shm_destination_t)); \
}


/* 
 * SHMEM_CONSTRUCT_FROM_MI_PROTO(shm_destination_t Dest,
 *			      nexus_mi_proto_t *Mi_proto,
 *			      nexus_byte_t *   Array)
 *
 * Copy the needed elements from Array to Dest.
 */
#define SHMEM_CONSTRUCT_FROM_MI_PROTO(Dest, Mi_proto, Array) \
{ \
    memcpy(&(Dest), (Array), sizeof(shm_destination_t)); \
}


/*
 * SHMEM_CREATE(shm_handle_t      Handle, 
 *             shm_destination_t Destination,
 *             int               Size
 *             int               Perms)  
 * 
 * System V IPC shared memory create.
 */
#define SHMEM_CREATE(Handle, Destination, Size, Perms) \
{ \
     (Handle) = shmget((Destination), (Size), (Perms)); \
}


/*
 * SHMEM_ATTACH(shm_segment_t * Segment, shm_handle_t Handle)
 *
 * System V IPC shared memory attach.
 */
#define SHMEM_ATTACH(Segment, Handle) \
{ \
    (Segment) = (shm_segment_t *) shmat((Handle), NULL, 0); \
}

/*
 * SHMEM_DESTROY(shm_handle_t Handle)
 *
 * System V IPC shared memory segment removal.
 */
#define SHMEM_DESTROY(Handle) \
{ \
     shmctl((Handle), IPC_RMID, NULL); \
}
