// The contents of this file are subject to the Mozilla Public License // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is the Berkeley Open Infrastructure for Network Computing. // // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 // University of California at Berkeley. All Rights Reserved. // // Contributor(s): // // interfaces for accessing shared memory segments #include #ifdef _WIN32 #include #endif #if HAVE_SYS_IPC_H #include #endif #if HAVE_SYS_SHM_H #include #endif #include #include "shmem.h" #ifdef _WIN32 HANDLE create_shmem(LPCTSTR seg_name, int size, void** pp) { SECURITY_ATTRIBUTES security; HANDLE hSharedMem; LPVOID pMemPtr; security.nLength = sizeof(security); security.lpSecurityDescriptor = NULL; security.bInheritHandle = TRUE; hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, &security, PAGE_READWRITE, 0, size, seg_name); if (!hSharedMem) return NULL; pMemPtr = MapViewOfFile( hSharedMem, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); *pp = pMemPtr; return hSharedMem; } HANDLE attach_shmem(LPCTSTR seg_name, void** pp) { HANDLE hSharedMem; LPVOID pMemPtr; hSharedMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, seg_name); if (!hSharedMem) return NULL; pMemPtr = MapViewOfFile( hSharedMem, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); *pp = pMemPtr; return hSharedMem; } int detach_shmem(HANDLE hSharedMem, void* p) { UnmapViewOfFile(p); CloseHandle(hSharedMem); return 0; } #else int create_shmem(key_t key, int size, void** pp) { int id; char buf[256]; assert(pp!=NULL); id = shmget(key, size, IPC_CREAT|0777); if (id < 0) { sprintf(buf, "create_shmem: shmget: key: %x size: %d", (unsigned int)key, size); perror(buf); return -1; } return attach_shmem(key, pp); } int destroy_shmem(key_t key){ struct shmid_ds buf; int id, retval; id = shmget(key, 0, 0); if (id < 0) return 0; // assume it doesn't exist retval = shmctl(id, IPC_STAT, &buf); if (retval) return -1; if (buf.shm_nattch > 0) { fprintf(stderr, "destroy_shmem: can't destroy segment; %d attachments\n", (int)buf.shm_nattch ); return -1; } retval = shmctl(id, IPC_RMID, 0); if (retval) { fprintf(stderr, "destroy_shmem: remove failed %d\n", retval); return -1; } return 0; } int attach_shmem(key_t key, void** pp){ void* p; char buf[256]; int id; assert(pp!=NULL); id = shmget(key, 0, 0); if (id < 0) { sprintf(buf, "attach_shmem: shmget: key: %x mem_addr: %d", (unsigned int)key, (int)pp); perror(buf); return -1; } p = shmat(id, 0, 0); if ((int)p == -1) { sprintf(buf, "attach_shmem: shmat: key: %x mem_addr: %d", (unsigned int)key, (int)pp); perror(buf); return -1; } *pp = p; return 0; } int detach_shmem(void* p) { int retval; assert(p!=NULL); retval = shmdt((char *)p); if (retval) perror("detach_shmem: shmdt"); return retval; } int shmem_info(key_t key) { int id; struct shmid_ds buf; char buf2[256]; id = shmget(key, 0, 0); if (id < 0) { sprintf(buf2, "shmem_info: shmget: key: %x", (unsigned int)key); perror(buf2); return -1; } shmctl(id, IPC_STAT, &buf); fprintf( stderr, "shmem key: %x\t\tid: %d, size: %d, nattach: %d\n", (unsigned int)key, id, buf.shm_segsz, (int)buf.shm_nattch ); return 0; } #endif bool APP_CLIENT_SHM::pending_msg(int seg_num) { if (seg_num < 0 || seg_num >= NUM_SEGS || shm == NULL) return false; return (shm[seg_num*SHM_SEG_SIZE]?true:false); } bool APP_CLIENT_SHM::get_msg(char *msg, int seg_num) { if (seg_num < 0 || seg_num >= NUM_SEGS || shm == NULL) return false; // Check if there's an available message if (!shm[seg_num*SHM_SEG_SIZE]) return false; // Copy the message from shared memory strncpy(msg, &shm[(seg_num*SHM_SEG_SIZE)+1], SHM_SEG_SIZE-1); // Reset the message status flag shm[seg_num*SHM_SEG_SIZE] = 0; return true; } bool APP_CLIENT_SHM::send_msg(char *msg,int seg_num) { if (seg_num < 0 || seg_num >= NUM_SEGS || shm == NULL) return false; // Check if there's already a message if (shm[seg_num*SHM_SEG_SIZE]) return false; // Copy the message into shared memory strncpy(&shm[(seg_num*SHM_SEG_SIZE)+1], msg, SHM_SEG_SIZE-1); // Set the message status flag shm[seg_num*SHM_SEG_SIZE] = 1; return true; } void APP_CLIENT_SHM::reset_msgs(void) { if (shm == NULL) return; memset(shm, 0, sizeof(char)*NUM_SEGS*SHM_SEG_SIZE); }