Looking at LinuxPLC on QNX RTP.

S

Thread Starter

Scott Whitlock

Hello, I've actually done what I said I would, and tried compiling the LinuxPLC source on the QNX Real Time Platform (RTP). Not much luck. Here's what I found: QNX RTP is totally POSIX compliant, but some of the code used in smm, gmm, and cmm are not. Specifically, including the headers &lt;sys/shm.h> and &lt;asm/page.h> are not standard POSIX files. Regarding the shm.h file (shared memory), the preferred POSIX compliant way to do shared memory is to use shm_open() and shm_unlink() to create and remove the shared memory object, and then use the functions from <sys/mman.h> to map that memory into your process. This will comply with the POSIX Real Time Interface (1003.1b). As for the page.h file, I think that the only reason you need this header is for the PAGE_SIZE constant. I guess we need to look at *why* you need this value, and where else we can get that from, or we could just have special cases for different platforms. Since QNX doesn't actually page to disk (for performance reasons) it could probably just be commented out in the QNX version. So, let me know about the PAGE_SIZE constant. I will be checking out how hard it will be for me to replace the function calls for shared memory with POSIX compliant ones. If Linux is also POSIX compliant in this area (and I'm sure it is), then we'll have a good cross platform code base going here in no time! The great thing about making it POSIX compliant, too, is that porting the PuffinPLC concept to LynxOS and other platforms will be that much easier in the future. Thanks, and keep up the good work, Scott _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
S

Scott Whitlock

--- Scott Whitlock <[email protected]> wrote: > Regarding the shm.h file (shared memory), the > preferred POSIX compliant way to do shared memory is > to use shm_open() and shm_unlink() to create and > remove the shared memory object, and then use the > functions from <sys/mman.h> to map that memory into > your process. This will comply with the POSIX Real > Time Interface (1003.1b). All I really had to change was /lib/misc/shmem_util.c because it was very encapsulated. I pasted the new file to the end of this message for you to check out. I've marked all the changed areas with "//QNX" to set them off. Please don't yell at me for using C++ comments in C code... :) I found a bunch of other details - probably minor differences between Linux and QNX RTP. However, one other major incompatibility is the use of semaphores. Basically, it's the same as the shared memory - there are other function calls to use for POSIX compliance. For instance, semget() and semop() are not recognized in QNX, but the POSIX functions sem_open(), sem_close(), etc., are there. > As for the page.h file, I think that the only reason > you need this header is for the PAGE_SIZE constant. > I > guess we need to look at *why* you need this value, > and where else we can get that from, or we could > just > have special cases for different platforms. Since > QNX > doesn't actually page to disk (for performance > reasons) it could probably just be commented out in > the QNX version. Regarding the PAGE_SIZE constant, I suggest using the sysconf(PAGESIZE) function call instead (from the &lt;unistd.h> file). That's it for now... more to follow. Here's the new shmem_util.c file - notice that I've done everything I can to keep the interface the same to the rest of the code (i.e. using keys for the shared memory, etc.). Can someone try compiling this on Linux? ------------8<-------------------- /* * (c) 2000 Jiri Baum * Mario de Sousa * * Offered to the public under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * This code is made available on the understanding that it will not be * used in safety-critical situations without a full and competent review. */ /* * Shared Memory Utility Routines * * This file implements the routines in shmem_util.h * * These routines merely make life simpler when working with * shared memory */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> //QNX #include <sys/shm.h> #include <sys/mman.h> #include <fcntl.h> //QNX #include <sys/sem.h> #include <errno.h> #include <limits.h> #include <time.h> /* random seed generator */ //QNX #include <asm/page.h> /* is this the correct include for PAGE_SIZE ? */ #define PAGE_SIZE 4096 //QNX -- actually, we should use sysconf(PAGESIZE) for this parameter #include "shmem_util.h" static int shmem_debug = 0; static int shmpg_save = 1; static int MAX_RAND_KEY_TRIES = 10; int detach_shmem(void *mem_ptr) //QNX { return shmdt (mem_ptr); } { return munmap( mem_ptr, shmpg_save * PAGE_SIZE ); } //QNX int create_shmem_rand(void **mem_ptr, int *shmkey, int shmpg) { int local_shm_key, i; srand(time(0)); for (i = 0; i < MAX_RAND_KEY_TRIES; i++) { while ((local_shm_key = rand()) == IPC_PRIVATE); if (create_shmem(mem_ptr, local_shm_key, shmpg) >= 0) { if (shmkey != NULL) *shmkey = local_shm_key; return 0; } } /* for */ return -1; } int create_shmem(void **mem_ptr, int shmkey, int shmpg) { int shmid; void *local_mem_ptr; char shm_name[16]; //QNX if (shmem_debug) printf("create_shmem(): creating shmem with key %d.\n", shmkey); //QNX shmid = shmget(shmkey, shmpg * PAGE_SIZE, IPC_CREAT|IPC_EXCL|0666); sprintf( shm_name, "/LinuxPLC%d", shmkey ); shmid = shm_open(shm_name, O_RDWR|O_CREAT, 0666); //QNX if (shmid==-1) { /* perror("Error creating shared memory"); */ return -1; } //QNX local_mem_ptr = shmat(shmid, 0/* no preferred address */ //QNX , 0 /* use defaults */); local_mem_ptr = mmap( 0, shmpg * PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0 ); close(shmid); shmpg_save = shmpg; /* save number of pages for future use */ //QNX if (local_mem_ptr == MAP_FAILED ) { //QNX NULL) { /* perror("Error creating shared memory"); */ delete_shmem(shmkey); return -1; } memset(local_mem_ptr, 0, shmpg * PAGE_SIZE); if (mem_ptr != NULL) *mem_ptr = local_mem_ptr; return 0; } int attach_shmem(void **mem_ptr, int shmkey) { int shmid; char shm_name[16]; //QNX if (shmem_debug) printf("attach_shmem(): attaching shmem with key %d.\n", shmkey); //QNX shmid = shmget(shmkey, 0, 0); sprintf( shm_name, "LinuxPLC%d", shmkey ); shmid = shm_open( shm_name, O_RDWR, 0666 ); //QNX if (shmid==-1) { /* perror("Error attaching shared memory"); */ return -1; } //QNX *mem_ptr = shmat(shmid, 0/* no preferred address */, 0 /* use defaults */); *mem_ptr = mmap( 0, shmpg_save * PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shmid, 0 ); close(shmid); //QNX if (*mem_ptr == NULL) { /* perror("Error attaching shared memory"); */ return -1; } return 0; } int delete_shmem(int shmkey) { //QNX int shmid; char shm_name[16]; //QNX if (shmem_debug) printf("delete_shmem(): deleting shmem with key %d.\n", shmkey); /* get hold of shared memmory */ sprintf( shm_name, "LinuxPLC%d", shmkey ); //QNX shmid = shmget(shmkey, 0, 0); //QNX if (shmid==-1) { //QNX /* perror("Error attaching shared memory"); */ //QNX return -1; //QNX } /* delete shared memory */ //QNX if (shmctl(shmid, IPC_RMID, 0)== -1) { if( shm_unlink( shm_name ) == -1 ) { //QNX /* perror("Error removing shared memory"); */ return -1; } return 0; } _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
M

Mario de Sousa

Scott Whitlock wrote: > > All I really had to change was /lib/misc/shmem_util.c > because it was very encapsulated. I pasted the new > file to the end of this message for you to check out. > I've marked all the changed areas with "//QNX" to set > them off. Please don't yell at me for using C++ > comments in C code... :) I have started integrating this into our code. I'll probably update the cvs this afetrnoon. Please notice that your code will probably not detach the shared memory correctly due to the use of the static shmpg_save variable. We actually use two shared memory areas for each process. This might change in the future, but currently this library cannot store this state. I'll probably change the code that uses the library so it passes the number of pages to detach. It shouldn't be too difficult. > I found a bunch of other details - probably minor > differences between Linux and QNX RTP. > > However, one other major incompatibility is the use of > semaphores. Basically, it's the same as the shared > memory - there are other function calls to use for > POSIX compliance. For instance, semget() and semop() > are not recognized in QNX, but the POSIX functions > sem_open(), sem_close(), etc., are there. > You have probably noticed that access to semaphores is limited to the sem_util.c file? Cheers, Mario. -- ---------------------------------------------------------------------------- Mario J. R. de Sousa [email protected] ---------------------------------------------------------------------------- The box said it requires Windows 95 or better, so I installed Linux _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
S

Scott Whitlock

--- Mario de Sousa <[email protected]> wrote: > > However, one other major incompatibility is the > use of > > semaphores. Basically, it's the same as the > shared > > memory - there are other function calls to use for > > POSIX compliance. For instance, semget() and > semop() > > are not recognized in QNX, but the POSIX functions > > sem_open(), sem_close(), etc., are there. > > > > You have probably noticed that access to semaphores > is limited to the sem_util.c file? Yes, but not entirely limited to it. There were uses of the semop() and semget() functions in other files. It will take a little longer to modify, but I'll be sure to do it. Another thing... in the shmem_util.c file, where I use the sprintf() function in several places, make sure that it's like this: sprintf( shm_name, "/LinuxPLC%d", shmkey ); This is because the file name you give it MUST start with a "/". It also must have only that one slash. I'm not sure if I got this right. And now that I'm thinking about it, most of the C files under 'lib' try to include the <sys/shm.h> header, but they don't need to, because only the shmem_util.h actually deals with the library functions. It's best if you remove those lines, because it's small changes to a lot of files - not worth me sending you the changes. Regards, Scott _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
M

Mario de Sousa

Scott Whitlock wrote: > > > You have probably noticed that access to semaphores > > is limited to the sem_util.c file? > > Yes, but not entirely limited to it. There were uses > of the semop() and semget() functions in other files. > It will take a little longer to modify, but I'll be > sure to do it. Yes. I had forgotten about those. They are probably all in the gmm library. Jiri started the library before I created the sem_util.c file. They shouldn't be too difficult to fix. > > And now that I'm thinking about it, most of the C > files under 'lib' try to include the <sys/shm.h> > header, but they don't need to, because only the > shmem_util.h actually deals with the library > functions. It's best if you remove those lines, > because it's small changes to a lot of files - not > worth me sending you the changes. > Yes, the cleanup of all the uneccessary #includes is in the TODO file ;-( Cheers, Mario. -- ---------------------------------------------------------------------------- Mario J. R. de Sousa [email protected] ---------------------------------------------------------------------------- The box said it requires Windows 95 or better, so I installed Linux _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
Top