[comp.unix.ultrix] Mips f77 and shared memory

juh@qt.IPA.FhG.de (Juergen Henke) (02/02/91)

--
Is it possible to work with shared memory in Fortran on a DECstation (Ultrix
V4.x) ?
I am porting an application from VMS to Ultrix which did the interprocess
communication
via named COMMONs, which were installed.
I have no problems to use shared memory in C on this machine. I would like to
use COMMON
blocks which are actually in shared memory. Any ideas ?

Thanks in advance,

		Juergen

P.S.: I did not see any FORTRAN statements for several years...sigh
_________________________________________________________________________
Juergen Henke, e-mail juh@qt.IPA.FhG.de, PSI-mail PSI%4571109306::JUH_IPA
Fraunhofer-Institut f. Produktionstechnik u. Automatisierung
Eierstrasse 46, D-7000 Stuttgart 1

frank@croton.enet.dec.com (Frank Wortner) (02/05/91)

> Is it possible to work with shared memory in Fortran on a DECstation (Ultrix
> V4.x) ?
> I am porting an application from VMS to Ultrix which did the interprocess
> communication
> via named COMMONs [...]

Shared common areas do seem to be the Holy Grail of FORTRAN programming
(at least this week).  Here's a way that works.

Basically, you need two bits of support.  The first is a C subroutine that sets
up your shared memory segment, and the second is an assembly language
file that turns the common names into absolute symbols whose value is the
beginning of the shared memory area.  The whole thing works reasonably well
and requires minimal changes to the FORTRAN code.

I've enclosed a short demonstration program for your amusement.  Extract
the shar archive and then compile the resulting files like so:

	f77 shared.f common.s shminit.c

Now run the executable.  Change a value or two and then start a second
session with the same image.  You can either put the first in the backgound
("control-Z" it), or, if you're on a workstation, just start another terminal
session.  Then reinvoke a.out, and you'll see the changes you made in the
first session.

This program is a quick hack, so no comments about the ugly style, lack of
comments, etc.  At least it works!  Extending this program, making the
interface more general or cleaner , and adding additional shared common areas
are left as exercises for the reader.

Enjoy,

					Frank

Just call me "Dr. Fortran."  :-)

-------------------------Snip Here------------------------------


#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./shared.f`
then
echo "writing ./shared.f"
cat > ./shared.f << '\End\Of\Shar\'
	common /shared/ i(10)
	integer n
	write(6,100)
100	format('Shared memory tester')
	call shminit
 20	write(6,101)
101	format('Enter 1 through 10 to change a memory location')
	write(6,102)
102	format('Enter any other number to view the memory')
	read(5,103) n
103	format(i5)
	if(n.ge.1 .and. n.le.10) then
		call change(i, n)
	else
		call display(i)
	endif
	goto 20
	end
c
c Change a value in the shared common array
c
	subroutine change(i,n)
	integer i(10)
	write(6,101)
101	format('Please enter a new value:')
	read(5,100) ivalue
100	format(i5)
	i(n) = ivalue
	return
	end
c
c Display the shared common array
c
	subroutine display(i)
	integer i(10)
	write (*,100) (i(n), n=1,10)
100	format(10i6)
	return
	end
\End\Of\Shar\
else
  echo "will not over write ./shared.f"
fi
if `test ! -s ./common.s`
then
echo "writing ./common.s"
cat > ./common.s << '\End\Of\Shar\'
.globl	shared_

/*
** Shared memory is attached at 0x800000.  Force the
** FORTRAN common block to be an absolute address.
*/

shared_	= 0x800000
\End\Of\Shar\
else
  echo "will not over write ./common.s"
fi
if `test ! -s ./shminit.c`
then
echo "writing ./shminit.c"
cat > ./shminit.c << '\End\Of\Shar\'
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#define KEY	100	/* An arbitrary number */
#define SIZE	40	/* 10 32-bit integers */

/* This subroutine is called from a FORTRAN main program ---
** notice the trailing underscore!  It creates a shared memory
** segment and then returns.
*/

void shminit_()
{
	int shmid;
	char *addr;

	shmid = shmget(KEY, SIZE, IPC_CREAT|0666);
	if (shmid < 0) {
		perror("shminit: shmget failed: ");
		exit(1);
	}
	if ((int)(addr = shmat(shmid, 0, 0)) < 0) {
		perror("shminit: shmat failed: ");
		exit(2);
	}
	fprintf(stderr, "Shared memory attached at 0x%x\n", addr);
}
\End\Of\Shar\
else
  echo "will not over write ./shminit.c"
fi
echo "Finished archive 1 of 1"
exit