[mod.computers.masscomp] Shared memory examples sought

masscomp@soma.UUCP (06/17/86)

	We would like to link two concurrent processes in a real-time 
application using shared memory.  One process simultaneously sends 
data to and receives data from the data acquisition and control 
processor in short bursts (1 to 2 s) separated by pseudo-random 
intervals (3 s avg.).  The other process runs an interactive 
graphical simulation on an independent graphics processor (IGP).  
This simulation runs as a large display list in IGP memory that 
updates itself on the fly by reading display information from 
registers in the host memory.  The host updates these registers once 
every second.  We want the data-acquisition process to change two of 
the registers in host memory that the simulation process uses.  To 
us, shared memory seems to be the fastest and surest way of doing this.
	None of us has experience with shared memory programming.  So
we seek information and examples that would be helpful to us in 
linking these processes together.

Len Trejo (for Neuroscience Group).
NPRDC arpa: trejo@nprdc		Phone: (619) 225-7424/7627

stan@drillsys (Stan Hanks) (06/24/86)

I recently finished a similar application for a positron emision 
scanner. I'm not convinced that this is the best way to solve the
problem, but it certainly is one way.

Being a casual reader of this news group (Stan Barber is a good friend
and I occasionally do joint work with him on their Masscomp) and not
normally running System V (I'm actually a Sun OEM), I can't well
include code and say "Here, this works". And as the previously mentioned
work is copyrighted and owned by the company who leased me to do it, 
I can't include it either. But, here is a scetch of how it goes. 
Holler if you need more detail; I'll get onto a System V machine and
pound out the details.

=============================================
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

/* warning! good for 32 bit unsigned only !!!! */
#define BIS(flag, bit)	flag |= (1<<bit)
#define BIC(flag, bit)	flag &= ^(1<<bit)
#define BIT(flag, bit)  flag & (1<<bit)
#define INCMOD32(flag)	flag = (++flag % 32)

main()
{
	int flagd, bufd;		/* shared mem descriptors */
	char         *buf;		/* pointer to the buffer  */
	char         *buff[32];		/* sub-pointers to buffer */
	unsigned int *flag;		/* busy flags for buffer  */
	int i;

	/* allocate shared memory for 32-bit flag and 32 1K buffers */
	if ((flagd = shmget((key_t)0, 4, IPC_CREAT)) == -1) {
		printf("oops.\n");
		exit(1);
	}
	if ((bufd = shmget((key_t)1, 32*1024, IPC_CREAT)) == -1) {
		printf("oops.\n");
		exit(1);
	}

	/* attach the shared memory */
	if ((flag = (unsigned int *)shmat(flagd, 0, SHM_RND))) == -1) {
		printf("oops.\n");
		exit(1);
	}
	if ((buf = shmat(bufd, 0, SHM_RND))) == -1) {
		printf("oops.\n");
		exit(1);
	}

	/* clear the shared flags -- this is important!!! */
	*flag = 0;
	/* build array of 1K buffers */
	for (i=0; i<32; i++) buff[i] = buf + i*1024;

	/* pause to procreat */
	switch ((pid = fork()))) {
		case -1:
			printf("oops.\n");
			exit(1);
			break;
		case  0:
			do_child_stuff(flagd, bufd);
			break;
		default:
			break;
	}

	/* parent now stuffs things into shared memory */
	while (! done) {	 /* hey, what did you want for nothing??? */
		char sbuf[1024]; /* data that needs to be shared */
		int  which = 0;  /* which bucket are we using now?? */

		if (BIT(*flag, which)) {
			printf("Yow! We wrapped around. Abandon program\n");
			exit(1);
		}
		get_stuff_to_be_shared(sbuf);
		bcopy(sbuf, buff[which], 1024); /* bcopy(from, to, nbytes) */
		BIS(*flag, which);		/* set busy bit */
		INCMOD32(which);		/* move to next bucket */
	}
}

/* here we are in another process, waiting on this data to arrive */
do_child_stuff(xflagd, xbufd)
int xflagd, xbufd;
{
	char *xbuf;
	char *xbuff[32];
	unsigned int *xflag;
	int i;
	
	/* attach the shared memory */
	if ((xflag = (unsigned int *)shmat(xflagd, 0, SHM_RND))) == -1) {
		printf("oops.\n");
		exit(1);
	}
	if ((xbuf = shmat(xbufd, 0, SHM_RND))) == -1) {
		printf("oops.\n");
		exit(1);
	}
	/* build array of 1K buffers */
	for (i=0; i<32; i++) xbuff[i] = xbuf + i*1024;

	/* here we go.... */
	while (! done) {
		char rbuf[1024];	/* recieved data */
		int which = 0;		/* which buffer ? */

		/* we process in the same order as we fill, so */
		/* as to provide the same data ordering        */
		/* this also provides synchronization and      */
		/* eliminates the need for more serious mutex  */
		/* protocols. this of course changes if the    */
		/* data rates cause overruns                   */

		while(! BIT(*xflag, which)
			;			/* busy wait */
		bcopy(xbuff[which], rbuf, 1024);/* retrieve data */
		BIC(*xflag, which);		/* clear busy bit */
		INCMOD32(which);		/* look at next bucket */
		do_stuff_with_data(rbuf);
	}
}

=================================

Hope this helps.


Stan Hanks					...!drillsys!stan
Sr. Research Scientist				stan@rice.ARPA
Teleco Oilfield Services, Drilling Systems Technology
Houston TX					(713) 699-5594