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