[comp.unix.wizards] shared memory under SysV

EE784@sscvax.mcmaster.ca (05/11/88)

In answering another query in this newsgroup, I got to thinking about
how I'd interpreted the original documentation for a return value from
one of the shared memory functions.  Presumably there are:
        1) others who have also thought about this question;
        2) others who know the answer.
Under uPort sysV/AT (a system V, rev. 2 port to IBM AT and clones [swapping,
not paging:-) ]) shared memory is supported for, among other things, using
the memory-mapped video RAM.  The man pages for the various shm(2) calls
give the following synopses:

        int shmid ( key, size, shmflg )
        key_t key;
        int size, shmflg;

        char *shmat ( shmid, shmaddr, shmflg )
        int shmid;
        char *shmaddr;
        int shmflg;
        [stuff about detaching deleted]

and say the following about the return value of shmat:

        Upon successful completion, the return value is as follows:
                Shmat returns the data segment start address of the
                attached shared memory segment.
                [stuff about detaching deleted]
        Otherwise, a value of -1 is returned and errno is set to
        indicate the error.

Since shared memory is available only under the large model, pointers are
32 bits.  There is no apparent reason that a pointer cannot assume the
equivalent of -1 for valid addresses (although trying to use it will
probably generate a memory exception, since I certainly don't have that
much physical memory).  My initial temptation was to assume the
documentation was wrong and that a NULL pointer should be returned if
shmat fails; however, the doc'n went out of its way to indicate that it
should be -1 (presumably -1L) on failure.  So the code that uses it
looks like:

        int gfx_id, shmget ();
        unsigned g_plane_siz = 32768U;
        char *gfx_ptr, *shmat ();
        key_t gfx_key;

        if (( gfx_id = shmget ( gfx_key, g_plane_siz, 0 )) == -1 ) {
                perror ();
                exit ( 1 );
        }
        gfx_ptr = shmat ( gfx_id, (char *)NULL, 0 );
        if ( (long)gfx_ptr == -1L ) {
                perror ();
                exit ( 1 );
        }

The original key is assigned at boot time to make the graphics memory
public, and shmflg (== 0) is effectively ignored.  So, the code works,
and there is no good reason why the attach should fail if the key is
available, but I've always been bothered about the test on gfx_ptr.
The other obvious anomaly here is that the documentation indicates
that g_plane_siz must be int, but uPort's own examples assume it is
unsigned, and this in fact works.

So, the questions are:
        1) what is the proper return value of shmat on failure;
        2) if it is -1, is it int or long (should be long, I believe).
Any other insights cheerfully accepted.

--mike borza    <EE784.SSCvax.McMaster.CA>

Ed@mead.scrc.symbolics.com (Ed Schwalenberg) (05/14/88)

    Date: Wed, 11 May 88 01:50 EST
    From: EE784@sscvax.mcmaster.ca

    Under uPort sysV/AT (a system V, rev. 2 port to IBM AT and clones [swapping,
    not paging:-) ]) shared memory is supported for, among other things, using
    the memory-mapped video RAM.  The man pages for the various shm(2) calls
    give the following synopses:
    ...
    and say the following about the return value of shmat:

	    Upon successful completion, the return value is as follows:
		    Shmat returns the data segment start address of the
		    attached shared memory segment.
		    [stuff about detaching deleted]
	    Otherwise, a value of -1 is returned and errno is set to
	    indicate the error.

    Since shared memory is available only under the large model, pointers are
    32 bits.  There is no apparent reason that a pointer cannot assume the
    equivalent of -1 for valid addresses (although trying to use it will
    probably generate a memory exception, since I certainly don't have that
    much physical memory).  My initial temptation was to assume the
    documentation was wrong and that a NULL pointer should be returned if
    shmat fails; however, the doc'n went out of its way to indicate that it
    should be -1 (presumably -1L) on failure.

    So, the questions are:
	    1) what is the proper return value of shmat on failure;
At least in the AT&T/Intel/Interactive System V for the 386, you can only
attach shared memory segments on 4Meg boundaries.  NULL is on a 4Meg
boundary, but -1 is not.  Normally, of course, your text segment lives at
0, but perhaps you can make an executable with the text segment elsewhere,
and use segment 0 for shared memory.

	    2) if it is -1, is it int or long (should be long, I believe).
    Any other insights cheerfully accepted.

    --mike borza    <EE784.SSCvax.McMaster.CA>

mike@cimcor.UUCP (Michael Grenier) (05/15/88)

From article <14379@brl-adm.ARPA>, by Ed@mead.scrc.symbolics.com (Ed Schwalenberg):
>     Under uPort sysV/AT (a system V, rev. 2 port to IBM AT and clones [swapping,
>     not paging:-) ]) shared memory is supported for, among other things, using
>     the memory-mapped video RAM. 
...
>     much physical memory).  My initial temptation was to assume the
>     documentation was wrong and that a NULL pointer should be returned if
>     shmat fails; however, the doc'n went out of its way to indicate that it
>     should be -1 (presumably -1L) on failure.
> 
>     So, the questions are:
> 	    1) what is the proper return value of shmat on failure;



This is what my graphics package does under Microport Unix V/AT
for the shared memory attach. Using a cast you don't worry if its
long or not.
   
-Mike Grenier    {ihnp4, rutgers, amdahl}!bungia!cimcor!mike

void g_herc_open()
{
	if ((shm_id = shmget ((key_t)Herc_loc, SCREEN_SIZE*2L-1 , 0)) == -1) 
	{
		perror(" gplot:herc_open() - ");
		fprintf(stderr, "Unable to locate shared memory segment \n");
		fprintf(stderr, "Did you execute /etc/shmcreate as found in /etc/rc.d/shm.rc \n");
		fprintf(stderr, "i.e. /etc/shmcreate 0xb0000 b0000 32768\n");
		exit(1);
	};
		
    
    	if ((video_buf = shmat (shm_id, (char *) 0, 0)) == (char *) -1)
    	{
		perror(" gplot:herc_open() - ");
		fprintf(stderr, "Unable to attach shared memory segment \n");
		fprintf(stderr, "Did you execute /etc/shmcreate as found in /etc/rc.d/shm.rc \n");
		exit(1);
	};
	init_io();
}

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (05/17/88)

  I think this is a major conflict with ANSI C. The procedure must
return either an int or a pointer, but it can't portably do both, since
some systems don't represent the two types remotely the same way. This
works on the nice machine on which SysV was developed, but you better
hope that what's really returned for an error is "(char *) -1".
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/17/88)

In article <10861@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes:
>  I think this is a major conflict with ANSI C. The procedure must
>return either an int or a pointer, but it can't portably do both, since
>some systems don't represent the two types remotely the same way. This
>works on the nice machine on which SysV was developed, but you better
>hope that what's really returned for an error is "(char *) -1".

This botch has nothing to do with ANSI C.  A lot of old UNIX code
(mostly inherited from PDP-11-only days) did not properly distinguish
between integers and pointers.  Due to the way the system call error
handling routine worked, functions such as sbrk() returned some form of
-1, perhaps ((char *)-1), on error.  Obviously the proper C design for
such error returns (reported in-band in a nominally pointer value)
would be a null pointer, not some sort of cast -1.

Why this wasn't fixed when the IPC stuff was added for USG 4.x I don't
know.  Probably the same reason the PWB/Graphics unportable uses of
getc() were "fixed" by adding #if u3b2 instead of doing it right.