Re: [linux-audio-dev] shared memory problems

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] shared memory problems
From: Paul Davis (pbd_AT_Op.Net)
Date: Sun Nov 11 2001 - 18:39:04 EET


>No, sorry. Indeed it does - it is even specified to do so. From SUS on
>mmap:

   [ very helpful stuff elided ]

>> work in the particular way that it does. this is a technique i've used
>> in the past on Interactive Unix, on Mach, on Ultrix and on Solaris.
>
>You happen to be lucky then :) The standards dont say anything that would
>make me believe that this should work.

the standards don't, no. but since shmat (id, addr, 0) will work most
of the time, all thats required is careful selection of `addr'. you
never get to be much of a systems programmer on any given OS without
knowing something about to select `addr' for such things (though
perhaps never enough) :)

>> yes, you can't *depend* on it. in theory, it might not work. but if 2
>> conditions are satisfied, it will:
>>
>> 1) for the particular set of mappings in question,
>> they are all initiated in the "client" processes
>> before other calls to mmap(2) and shmat(2) with 0
>> as the requested address.
>
>Not from the spec (from the linux shmat manpage yes, but...).

well, actually, this is great news. because it means that neither
shmat nor mmmap will attempt to use the "unmapped region" of a process
unless specifically asked to. this actually means that we only need to
satisfy this:

>> 2) shmat works in the fashion described by the man page,
>> using an unmapped area that other mechanisms will not
>> operate on (like ld.so)

and its done. the following hack satisfies this quite easily (given
what we know about the kernel's mapping of tasks):

static char *top_end_of_unmapped_memory = (char *) (1048576 * 1536); /* 1.5GB */
static char *low_end_of_unmapped_memory = (char *) (1048576 * 1024); /* 1GB */

static char *
fixed_shmat (int shmid, char *shmaddr, int shmflg, size_t size)
{
        char *addr;
        char *attempt;

        if (shmaddr != 0) {
                return shmat (shmid, shmaddr, shmflg);
        }

        attempt = (char *) (top_end_of_unmapped_memory - size);

        while (attempt > low_end_of_unmapped_memory) {
                if ((addr = (char *) shmat (shmid, attempt, shmflg|SHM_RND)) != (char *) -1) {
                        top_end_of_unmapped_memory = addr;
                        return addr;
                }
                attempt -= size;
        }
        return (char *) -1;
}

>of another way at the moment). Also segment:offset addressing is not
>that difficult, if you design the data in shm to avoid having pointers
>in the first place (i.e. use arrays + indexes rather than linked lists,
>etc.) - also a macro for "dereferencing" hides the complexity.

good food for thought. right now, i'm trying to get stuff checked into
CVS for JACK and putting a rudimentary framework for the website. once
that's done, you can check out the code and fix it for me, right? :)))

i wish there was a way force certain things to happen when a process
dies on SIGKILL, though. we can't call shmctl(id,IPC_RMID) on shm
segments until we know that no more clients will attempt to connect -
i.e. the server is exiting (because a "marked-destroyed" segment
cannot be accessed by a new task). thus, i defer this via
on_exit(). alas, these are not called if it dies with SIGKILL, and we
end up with "persistent" shm segments. sigh. at least i can handle all
other signals properly.

btw, i have JACK running with maarten's rudimentary FLTK client,
rythmnlab and the prototypical simple JACK client now. lots of things
to work on, but its starting to feel very nice.

--p


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Sun Nov 11 2001 - 18:38:20 EET