Shared device memory mapping for 6.2.1

Alright i’m at the bottom of the barrel about this problem.

I am trying to port some device driver code from 6.1 to 6.2.1 and I can’t successfully get shared memory mapping to work between processes . When I run checks in the resource command using a new pointer mapped with the shared memory file descriptor I get all of the data from the memory mapped region just fine. However when I make the same call in another process using the same file descriptor that I just used in the original process, all of the bytes read from the shared memory region are null. Here’s the relevant code

Resource manager:

[code] s_glb.apc8620_pbase=PCI_MEM_ADDR(buff32[0]);
printf(“Assigned s_glb.apc8620_pbase to %x\n”, buff32[0]);
s_glb.apc8620_port_length=sysconf(_SC_PAGE_SIZE);

// memory map the IO space to our own pointer
s_glb.apc8620_vbase=mmap_device_memory(NULL,
s_glb.apc8620_port_length,
PROT_READ|PROT_WRITE|
PROT_NOCACHE,
MAP_SHARED,
s_glb.apc8620_pbase);
if(s_glb.apc8620_vbase==MAP_FAILED)
{
perror(“apc8620 mmap_device failed:”);
exit(EXIT_FAILURE);
}

// Here the memory sharing funkiness begins
/* open the shared memory object, create it if it doesn’t exist */
strcpy(devName,"/dev/apc8620RM");
// copy name to global status struct passed to clients in devctl(GET_STATUS)
strcpy(s_glb.memName,devName);

printf(“Memory Name: %s\n”, devName);

// create shared memory object
fd = shm_open(devName,O_RDWR|O_CREAT,0);
if ( fd == -1 ) {
perror(“shm_open failed:”);
exit(EXIT_FAILURE);
}

/* overlay the shared memory object on the physical memory /
if ( shm_ctl(fd, SHMCTL_ANON|SHMCTL_PHYS|SHMCTL_GLOBAL,
s_glb.apc8620_pbase,
s_glb.apc8620_port_length) == -1 )
{
perror(“shm_ctl failed:”);
close(fd);
munmap((char
)s_glb.apc8620_vbase,s_glb.apc8620_port_length);
shm_unlink(devName);
exit(EXIT_FAILURE);
}

ptr = mmap ( 0, len, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_SHARED, fd, 0);
if ( ptr == MAP_FAILED)
{
fprintf( stderr, “mmap failed!”);
}
[/code]

Second process:

[code] printf(“Opening shared memory and getting status\n”);
// open apc8620 to get its status
if ((smem_info.device_fd = open("/dev/apc8620", O_RDONLY)) == -1) {
printf(“Error opening device\n”);
return(NULL);
}
if(devctl(smem_info.device_fd,APC8620_GET_STATUS,&data,
sizeof(data),NULL)<0)
{
printf(“apc8620_open: APC8620_GET_STATUS failed”);
return(NULL);
}
smem_info.port_length=data.stx.apc8620_port_length;
strcpy(smem_info.memName,data.stx.memName);
smem_info.mem_fd = shm_open(data.stx.memName, O_RDWR,0);

  if( smem_info.mem_fd == -1 ) {
    perror("shm_open failed:");
exit(EXIT_FAILURE);
  } 
  // the other half of the memory funkiness
  // map the shared memory from the server to the client
  /*
  smem_info.base= mmap(NULL,smem_info.port_length,
 			 PROT_READ|PROT_WRITE|PROT_NOCACHE,
	 		 MAP_SHARED,smem_info.mem_fd,0);
  */

  ptr = mmap ( NULL, data.stx.apc8620_port_length, 
	   PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_SHARED, smem_info.mem_fd, 0);
  
  if ( ptr == MAP_FAILED)
{
  fprintf( stderr, "map failed!");
}

[/code]

loading up both processes into GDB, dumping

x /1024xb ptr from the resource manager (first code section) returns 1024 bytes of accurate information.
However

x /1024xb ptr from the second process (with the breakpoints set at the end in both of those code sections) returns 1024 bytes of 0x00.

There has to be something i’m missing…

On a possibly related note: In the resource manager, unless I use both SHMCTL_ANON and SHMCTL_PHYS together shm_ctl returns Function not Implemented. (The original code for 6.1 did not use SHMCTL_ANON, also the sample code from the shm_ctl() documentation at www.qnx.com returns Function not Implemented (it does not use SHMCTL_ANON)).

Can anyone spot anything wrong in this or have any ideas on things to try? I’m basically just out of ideas for what it could possibly be.
I’ve verified every data member and function argument that I think is relevant to these calls and they all check out. Its almost as if QNX has a devil set aside for me =)

One thing i’ve heard mentioned around the lab is that some lower level functionality of QNX was removed from the Non commercial release (which i’m using) between 6.1 and 6.2.1… I hope that’s not it because i’m hoping to get the onboard network working with QNX 6.3…

The credibility of this concern is heightened by the fact that the sample code given in the qnx documentation (www.qnx.com) for shm_ctl, which covers simple shared memory also causes shm_ctl to return Function not Implemented. =/

Might I just not have some package that I need?

Appreciative of any help,
Iniari

/dev/apc is a weird name for a shareme. Usually share mem are found under /dev/shmem.

You are not using O_CREAT, in the first process that’s odd.

In first program, why are you using mmap at the end, pointer apc8620_vbase is ready to use.

I’m pretty sure the delta between 6.2.1 and 6.1 is not the cause of the problem. However 6.2.1 could have a bug or the behavior may have been changed

Sorry, don’t have more significant pointers for you !

The first process does use O_CREAT

  // create shared memory object
  fd = shm_open(devName,O_RDWR|O_CREAT,0);
  if ( fd == -1 ) {
    perror("shm_open failed:");
    exit(EXIT_FAILURE);
  } 

The ptr variable mapped at the end of the two code statements were just debugging checks (to test accessing the shared memory through the shared memory file descriptor, instead of through the first process’s virtual memory address).

A couple random thoughts… Try a name like ‘/test’ as the shared object - start with a slash and don’t contain any slashs other than the start… Check to see that you can see the object in /dev/shmem once you have created it.

There were changes between 6.x and 6.2 which broke working shared memory implementations (which apparently were taking advantage of a bug). I don’t recall the details of that.

Rick…

I wish I could get my hands on those details, as they sound like quite the suspect in this whole thing.

Also- I reconfigured the path names such that they were /[name] and both the driver file wound up in /dev and the shared file wound up in /dev/shmem all on their own.

I wish that this was my own code to begin with; that way I’d be more certain that I’m not overlooking something else. Granted I’m a CS undergrad, but this is the first time i’ve ever seen QNX. So I show up to CMU’s Microdynamic Systems Laboratory for my first real job over the summer, and I get some code that workes on QNX 6.1 on a different machine running slightly different hardware, a target box (assembly required, heh) and a manual on real time programming for Neutrino 2… kinda scary for my first job =)

Anyhow, I appreciate the feedback over all the posts I’ve made here- this community is amazing.

Let me know if any more ideas pop up
Iniari

I though about that as well but looked it up in the manual and the name used is valid, just unusual.

More random thoughts…

I assume the problem is not just in gdb, but actually exists when the code runs on it’s own - in case this is really a gdb problem?

Is the ptr you are referencing declared volitile? Again in case funky optimization by the compiler is getting in the way.

Rick…

I found this in the release notes for 6.2 – I hope it helps:

Shared memory

In the past, objects created in the directory /dev/shmem weren’t created
with permission/ownership attributes. These objects are now all still
created as name-special devices, but will properly use the creation mode and ownership information and will fail requests that don’t match
properly. This may inadvertently affect programs that were relying on
the broken behavior of no access control for objects/files in /dev/shmem or those created with shm_open().

Permissions and ownership of these objects may be manipulated with the chmod/chown utilities (or the chmod/chown() functions) after the objects have been created.

I believe I’ve isolated the problem- the SHMCTL_ANON flag.

Looking around in all of the documentation of functions related to shared memory mapping I caught a blurb about SHMCTL_ANON zeroing the regions it creates. With that in mind, I modified the working code on the 6.1 machine and included the SHMCTL_ANON flag. Lo and behold the program then broke in the same way- the shared memory was null.

This would leave me one easy step away from the solution if it weren’t for the fact that my newer 6.2.1 box fails the shm_ctl (with Function not implemented of all things) if I don’t include the SHMCTL_ANON flag.

Now i’m left with 2 questions- First, what calls does shm_ctl make internally? If possible I would like to try just using a different set of functions to get the same result, and seeing if it works.
I don’t see any way offhand, looking through the QNX docs, to associate a shared file descriptor with a physical address.

Also- I’m using fairly new hardware. (Intel P4 2.8GHz CPU and the Intel D865GLC moboard)
What possibility is there that shm_ctl failing with only the SHMCTL_PHYS flag set and not SHMCTL_ANON flag set is a product hardware incompatibility?

Greatful for any help as always,
Iniari

Now here’s something interesting–

I think PHOTON might be to blame for all of my troubles.

On a whim I put a head and keyboard on the old, working system. (It runs headless, and people SSH into it).
I noticed the old system boots straight to the command line. I executed the code from the command line and it worked as expected. Then I started the photon environment…

When I tried to run the code from the photon GUI’s terminal window the old system failed with shm_ctl: function not implemented!

My new system boots straight to the photon environment whether I like it or not. So my new question is this: How do I edit the startup procedure of QNX? I figure there must be some file comparable to Microsoft’s autoexec.

Thanks

Iniari

To boot to the command line (not photon) execute the following command as root:

touch /etc/system/config/nophoton