[comp.unix.xenix] shared memory

chad@lakesys.UUCP (D. Chadwick Gibbons) (02/06/89)

        I am having some problems with shared memory operations on SCO
XENIX/286 2.2.3 - System V shared memory, not the Xenix equivalent.

        On a 286 you have to declare the shared memory segment to be a
pointer to a far segment of memory.  Unless you use large model programs,
you have to write your own versions of standard library functions which will
access the segment.  The example given in the manual is that of strcpy(),
which will copy a given string into the segment.  It is identical to the
standard library's version, except the first argument is declared as a far
character pointer.

        On the application I am presently working on I use the shared
segment as a table for multiple users to access.  I define the segment's
size as a "sizeof(struct shmem);" which is the structure containing the
process table.  The main accessing of the shared segment is done through two
functions, putmem(), and getmem() which preform as memcpy() would except
modified to handle the far pointer.  Here is the code for putmem():

/* putmem: places data into shared memory segment */
void putmem(mem)
struct shmem *mem;
{
    register char far *d;
    register char *s;
    register int n;
    int size;

    size = sizeof(mem);
    if (size <= 0)
        return;

    s = (char *)mem;
    d = Memory; 
    if (s <= d && s + (size - 1) >= d) { /* overlap, must copy right-to-left */
        s += size - 1;
        d += size - 1;
        for (n = size; n > 0; n--)
            *d-- = *s--;
    } else
        for (n = size; n > 0; n--)
            *d++ = *s++;
    return;
}

The global "Memory" is simply the shared memory segment.  It is defined as
"char far *Memory;" and is initilized by another function which attaches the
given process to the shared segment.  The "register" identifier on the
variable "d" is probably illused.  I don't believe a far pointer can be
placed in a register - at least the compiler listing (-Fs option) does not
list it as being in a register.  However, removing the register declaration
does not change my error.

        In the beginning of the application, the shared segment is attached
to, and the creating process attempts to place a empty structure in the
segment.  The structure contains information such as empty strings and -1
for integers and this is my way of telling other processes that a given
location is unused.

        When I attempt to call putmem(); I receive a memory fault from this
function.  The debugger reports it occurs with this line: "*d++ = *s++;"
which is where the copying of the data is being preformed.

        What am I doing wrong with the copy of the data?  I would think this
should work, but, of course, it doesn't.  I tried using memcpy() but it did
not work due to the far pointer.  Any information would be appreciated, as
always.  My logic for the code of this function was obtained from using a
public domain version of memcpy().
-- 
D. Chadwick Gibbons, chad@lakesys.lakesys.com, ...!uunet!marque!lakesys!chad