ftw@datacube.UUCP (11/19/87)
Anyone out there have experience with shared memory in Sys V.3? I'm porting a driver from a Sun 3 environment, and one of the requirements is that a large chunk of physical address space be mapped into a users' virtual address space. This range of address may not swapped or cached. In Sun land, the driver did this by calling valloc(), and passing the pointer returned by valloc() to a function that calls mmap() enough times to get all the addresses mapped. In Motorola's Sys V port, they have added extensions to the shmget() function that allows physical addresses to be mapped. The default parameters for my system allow up to 128K bytes to be bought per-call. I need more space than this, so I call shmget() more than once, and I call shmat() to get back the corresponding virtual addresses. The addresses that come out of shmat() result in a non-contiguous virtual address space. I really need it to be contiguous. The second argument to shmat() can be NULL, or a valid user virtual address. I've tried buying memory with malloc() and passing that pointer to shmat, but I always get EINVAL from shmat(). Any Motorola Sys V gurus out there? Farrell T. Woods Datacube Inc. Systems / Software Group 4 Dearborn Rd. Peabody, Ma 01960 VOICE: 617-535-6644; FAX: (617) 535-5643; TWX: (710) 347-0125 INTERNET: ftw@datacube.COM UUCP: {rutgers, ihnp4, mirror}!datacube!ftw
allbery@ncoast.UUCP (11/26/87)
As quoted from <106600017@datacube> by ftw@datacube.UUCP: +--------------- | In Motorola's Sys V port, they have added extensions to the shmget() function | that allows physical addresses to be mapped. The default parameters for | my system allow up to 128K bytes to be bought per-call. I need more space | than this, so I call shmget() more than once, and I call shmat() to get | back the corresponding virtual addresses. The addresses that come out of | shmat() result in a non-contiguous virtual address space. I really need | it to be contiguous. The second argument to shmat() can be NULL, or a | valid user virtual address. I've tried buying memory with malloc() and | passing that pointer to shmat, but I always get EINVAL from shmat(). +--------------- You're trying to attach two pieces of memory to the same address. The way to do this is to call shmat() with NULL the first time, then for the others pass the virtual address immediately following the end of the previous segment (i.e. for the second, pass the address returned by shmat() plus the size of the segment, and so on). -- Brandon S. Allbery necntc!ncoast!allbery@harvard.harvard.edu {hoptoad,harvard!necntc,{sun,cbosgd}!mandrill!hal,uunet!hnsurg3}!ncoast!allbery Moderator of comp.sources.misc
archer@elysium.SGI.COM (Archer Sully) (11/28/87)
In article <5809@ncoast.UUCP>, allbery@ncoast.UUCP (Brandon Allbery) writes: > You're trying to attach two pieces of memory to the same address. The way to > do this is to call shmat() with NULL the first time, then for the others > pass the virtual address immediately following the end of the previous segment > (i.e. for the second, pass the address returned by shmat() plus the size of > the segment, and so on). > -- > Brandon S. Allbery Although Brandon doesn't mention it explicitly, there is a gotcha here. Shared segments need to be segment aligned, so if you try this trick on small segments, terrible things will happen. If the segment size on you machine is smaller that SHMMAX, then you're really in trouble. archer
ftw@datacube.UUCP (11/30/87)
Just wanted to take a moment and thank the folks who responded to my questions about shared memory on Sys V. To summarize: When I call shmget(), I should grab as much memory as I can, and that size arg. should be a multiple of a "shared memory block size". When I call shmat() for the first time, use a NULL arg. for the attach address; shmat() gives out virtual addresses that are always (shared memory) block aligned, even if the corresponding shmat() asked for a smaller chunk of memory. Successive calls to shmat() should have an arg of whatever the first shmat() returned for the virtual address, plus the number of bytes requested so far. This ensures a nice, flat virtual address space. The Sun scheme of valloc()/mmap() isn't applicable because shmat() needs an address that's not already in use (allocated my malloc()). Almost everyone who responded pointed this out. A virtual address given to shmat() MUST always be (shared memory) block aligned. If you specify through the third arg that you don't want shmat() to align the address for you, and you don't give it one that is already properly aligned, the call will fail. Jonathan Creighton (pyrnj!oracle!jcreight) has an interesting suggestion: he suggests that I choose a virtual address that is closer to the midpoint between the current stack and heap, so that I won't run out of space for malloc() or lotsa nested funtion calls. Thank you all for the help! Farrell T. Woods Datacube Inc. Systems / Software Group 4 Dearborn Rd. Peabody, Ma 01960 VOICE: 617-535-6644; FAX: (617) 535-5643; TWX: (710) 347-0125 INTERNET: ftw@datacube.COM UUCP: {rutgers, ihnp4, mirror}!datacube!ftw
crp@cci632.UUCP (12/03/87)
In article <106600019@datacube>, ftw@datacube.UUCP writes: > > When I call shmat() for the first time, use a NULL arg. for the attach > address; shmat() gives out virtual addresses that are always (shared memory) > block aligned, even if the corresponding shmat() asked for a smaller chunk > of memory. > > Successive calls to shmat() should have an arg of whatever the first shmat() > returned for the virtual address, plus the number of bytes requested so far. ^^^^ Be warned that some implementations allocate segments like this (i.e. progressively higher addresses), while others allocate segments from higher to lower addresses. In which case, the virtual address of the second and subsequent segments the address of the previous segment *minus* the *size* of that segment. Note that in this scenario, the address of the contiguous memory is actually the address of the *last* segment allocated; while with progressive addresses it's the address of the *first* segment. In any case, you should always attach any partial segment required last (i.e. size_of_all_shared_memory % segment_size), so that all segments are properly aligned. For example, to attach 600,000 bytes of shared memory on a machine with 128K segments and progressive addresses: start = attach 128K segment at first available address nextaddr = start + 128K nextaddr = attach 128K segment at nextaddr nextaddr += 128K nextaddr = attach 128K segment at nextaddr nextaddr += 128K nextaddr = attach 128K segment at nextaddr nextaddr += 128K nextaddr = attach 88000 byte segment at nextaddr return(start) > This ensures a nice, flat virtual address space. > > Jonathan Creighton (pyrnj!oracle!jcreight) has an interesting suggestion: > he suggests that I choose a virtual address that is closer to the midpoint > between the current stack and heap, so that I won't run out of space for > malloc() or lotsa nested funtion calls. Also be warned that dynamic stack growth or heap growth can trash (or detach) shared memory in certain implementations. You'll have to test your own configurations to learn this. An easy way out of problems like this is to pre-allocate stack and heap by calling an initialization function with *lots* of local variables (to grow the stack) and then malloc(lots_of_mem). Chuck Privitera (... !rochester!cci632!crp) Computer Consoles Inc. Rochester, New York variable
lwv@n8emr.UUCP (Larry W. Virden) (12/05/87)
One warning! Shared memory , even accessed via SVID compatible routines, are not all equal! So for a truely compatible product, one needs to write quite a sophisticated set of routines to call OVERTOP of shared memory, then let them have different #ifdefs or modules for the different o/s. Here are just TWO of the differences: 1. Under one well known and widely used CPU architecture, one is limited to either 32k or 64k shared memory segments per call. I forget which it is right now... sorry! 2. Under another well known system, the vendor requires shared memory to be within one's program-breakpoint. That is, you have to do a malloc() of the appropriate size and then map the appropriately aligned address into the shared memory environment. Note that this is a NICE feature in one sense, since you end up with a less restrictive environment interacting wih stdio, other routines, etc. - as long as EVERYONE uses malloc and not brk directly. Since the internal implementation is not described within the SVID description, vendors are free to implement it in many different ways. For instance, I have always wondered why shared memory wasnt implemented OUTSIDE of the maximum breakpoint value; that would be another way to guarantee that the program's use of malloc/etc would never interfere. -- Larry W. Virden 75046,606 (CIS) 674 Falls Place, Reynoldsburg, OH 43068 (614) 864-8817 cbosgd!n8emr!lwv (UUCP) cbosgd!n8emr!lwv@ucbvax.Berkeley.EDU (BITNET) We haven't inherited the world from our parents, but borrowed it from our children.