diff --git a/api/boinc_api.C b/api/boinc_api.C index cb240c57c8..b69c5946a5 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -167,12 +167,21 @@ static int setup_shared_mem() { delete app_client_shm; app_client_shm = NULL; } +#else +#ifdef USE_FILE_MAPPED_SHMEM + if (create_shmem( + MMAPPED_FILE_NAME, sizeof(SHARED_MEM), (void**)&app_client_shm->shm + )) { + delete app_client_shm; + app_client_shm = NULL; + } #else if (attach_shmem(aid.shmem_seg_name, (void**)&app_client_shm->shm)) { delete app_client_shm; app_client_shm = NULL; } -#endif +#endif // ! USE_FILE_MAPPED_SHMEM +#endif // ! _WIN32 if (app_client_shm == NULL) return -1; return 0; } diff --git a/api/graphics2.h b/api/graphics2.h index 327d851db8..c904fb22a4 100644 --- a/api/graphics2.h +++ b/api/graphics2.h @@ -17,7 +17,12 @@ extern void boinc_app_key_release(int, int); // extern void boinc_graphics_loop(int, char**); extern void* boinc_graphics_make_shmem(char*, int); + +#ifdef USE_FILE_MAPPED_SHMEM +// Use boinc_graphics_make_shmem() instead of boinc_graphics_get_shmem() +#else extern void* boinc_graphics_get_shmem(char*); +#endif // Implementation stuff // diff --git a/api/graphics2_util.C b/api/graphics2_util.C index 1e311abed9..32bb248d72 100644 --- a/api/graphics2_util.C +++ b/api/graphics2_util.C @@ -35,15 +35,19 @@ void* boinc_graphics_make_shmem(char* prog_name, int size) { return p; #else void* p; +#ifdef USE_FILE_MAPPED_SHMEM + int retval = create_shmem("gfx_mmap_file", size, &p); +#else key_t key = get_shmem_name(prog_name); int retval = create_shmem(key, size, 0, &p); +#endif if (retval) return 0; return p; #endif } -void* boinc_graphics_get_shmem(char* prog_name) { #ifdef _WIN32 +void* boinc_graphics_get_shmem(char* prog_name) { HANDLE shmem_handle; char shmem_name[256]; void* p; @@ -51,11 +55,17 @@ void* boinc_graphics_get_shmem(char* prog_name) { shmem_handle = attach_shmem(shmem_name, &p); if (shmem_handle == NULL) return 0; return p; +} #else +#ifdef USE_FILE_MAPPED_SHMEM +// Use boinc_graphics_make_shmem() instead of boinc_graphics_get_shmem() +#else +void* boinc_graphics_get_shmem(char* prog_name) { void* p; key_t key = get_shmem_name(prog_name); int retval = attach_shmem(key, &p); if (retval) return 0; return p; -#endif } +#endif +#endif diff --git a/checkin_notes b/checkin_notes index 221176a163..0033ea165a 100755 --- a/checkin_notes +++ b/checkin_notes @@ -8135,3 +8135,22 @@ Rytis 26 Aug 2007 html/ inc/util.inc user/team_email_list.php + +Charlie 25 Aug 2007 + Begin implementation of using memory-mapped files for shared memory. + As a temporary measure during development, the new shared memory logic + is selected by defining USE_FILE_MAPPED_SHMEM. Once the conversion is + complete, we will use these as guideposts to remove the old logic + (using shmget,shmat, shmdt, shmctl, key_t, etc.) and then remove the + references to USE_FILE_MAPPED_SHMEM. + Note: these changes are to the HEAD / trunk only, for version 6. + + api/ + boinc_api.C + graphics2.h + graphics2_util.C + client/ + app.C + app_start.C + lib/ + shmem.C,h diff --git a/client/app.C b/client/app.C index 49a133f047..691c9bd23b 100644 --- a/client/app.C +++ b/client/app.C @@ -184,7 +184,11 @@ void ACTIVE_TASK::cleanup_task() { int retval; if (app_client_shm.shm) { +#ifdef USE_FILE_MAPPED_SHMEM + retval = detach_shmem(app_client_shm.shm, sizeof(SHARED_MEM)); +#else retval = detach_shmem(app_client_shm.shm); + #endif if (retval) { msg_printf(NULL, MSG_INTERNAL_ERROR, "Couldn't detach shared memory: %s", boincerror(retval) diff --git a/client/app_start.C b/client/app_start.C index 296970b216..a2066e904a 100644 --- a/client/app_start.C +++ b/client/app_start.C @@ -575,10 +575,17 @@ int ACTIVE_TASK::start(bool first_time) { // Set up core/app shared memory seg if needed // if (!app_client_shm.shm) { +#ifdef USE_FILE_MAPPED_SHMEM + sprintf(buf, "%s%s", slot_dir, MMAPPED_FILE_NAME); + retval = create_shmem( + buf, sizeof(SHARED_MEM), (void**)&app_client_shm.shm + ); +#else retval = create_shmem( shmem_seg_name, sizeof(SHARED_MEM), gstate.boinc_project_gid, (void**)&app_client_shm.shm ); +#endif if (retval) { needs_shmem = true; destroy_shmem(shmem_seg_name); // Don't leave an orphan shmem segment diff --git a/lib/shmem.C b/lib/shmem.C index 3648b908e8..55445350dd 100755 --- a/lib/shmem.C +++ b/lib/shmem.C @@ -48,6 +48,12 @@ extern "C" int debug_printf(const char *fmt, ...); #endif #endif +#ifdef USE_FILE_MAPPED_SHMEM +#include +#include +#include +#endif + #include "error_numbers.h" #include "shmem.h" @@ -159,6 +165,50 @@ int detach_shmem(void* p) { #else +#ifdef USE_FILE_MAPPED_SHMEM + +int create_shmem(char *path, size_t size, void** pp) { + int fd; + + // try 0666, then SHM_R|SHM_W + // seems like some platforms require one or the other + // (this may be superstition) + // + // NOTE: in principle it should be 0660, not 0666 + // (i.e. Apache should belong to the same group as the + // project admin user, and should therefore be able to access the seg. + // However, this doesn't seem to work on some Linux systems. + // I don't have time to figure this out (31 July 07) + // it's a big headache for anyone it affects, + // and it's not a significant security issue. + // + fd = open(path, O_RDWR | O_CREAT, 0666); + if (fd < 0) + return ERR_SHMGET; + + *pp = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0); + + // Now close the file. The kernel doesnŐt use our file descriptor. + close(fd); + + if (*pp == MAP_FAILED) + return ERR_SHMGET; + + return 0; +} + +int destroy_shmem(key_t key){ + return 0; +} + +int detach_shmem(void* p, size_t size) { + int retval; + retval = shmdt((char *)p); + return retval; +} + +#else // USE_FILE_MAPPED_SHMEM + int create_shmem(key_t key, int size, gid_t gid, void** pp) { int id; @@ -272,12 +322,15 @@ int print_shmem_info(key_t key) { return 0; } +#endif // USE_FILE_MAPPED_SHMEM + // For debugging shared memory logic // For testing on Apple, Linux, UNIX systems with limited number // of shared memory segments per process and / or system-wide // Mac OS X has a default limit of 8 segments per process, 32 system-wide // If void stress_shmem(short reduce_by) { +#ifndef USE_FILE_MAPPED_SHMEM int retval; void * shmaddr[16]; key_t key[] = { @@ -297,8 +350,9 @@ void stress_shmem(short reduce_by) { retval = shmctl(id, IPC_RMID, 0); } } +#endif // !defined(USE_FILE_MAPPED_SHMEM) } -#endif +#endif // !defined(_WIN32) && !defined(__EMX__) const char *BOINC_RCSID_f835f078de = "$Id$"; diff --git a/lib/shmem.h b/lib/shmem.h index 7c1cd7d004..6a21ece501 100755 --- a/lib/shmem.h +++ b/lib/shmem.h @@ -44,16 +44,24 @@ int detach_shmem(HANDLE hSharedMem, void* p); #else +#ifdef USE_FILE_MAPPED_SHMEM + +#define MMAPPED_FILE_NAME "boinc_mmap_file" + +// create a shared-memory segment of the given size. +// +extern int create_shmem(char *path, size_t size, void** pp); + +// detach from a shared-mem segment +// +extern int detach_shmem(void* p, size_t size); + +#else + // create a shared-memory segment of the given size. // extern int create_shmem(key_t, int size, gid_t gid, void**); -// Destroy a shared-memory segment. -// If there are attachments to it, -// print a message in a loop until the attachments are gone -// -extern int destroy_shmem(key_t); - // attach to a shared-memory segment // extern int attach_shmem(key_t, void**); @@ -64,11 +72,19 @@ extern int detach_shmem(void*); extern int shmem_info(key_t key); +#endif + +// Destroy a shared-memory segment. +// If there are attachments to it, +// print a message in a loop until the attachments are gone +// +extern int destroy_shmem(key_t); + #ifndef __EMX__ // For testing on Apple, Linux, UNIX systems with limited number // of shared memory segments per process and / or system-wide void stress_shmem(short reduce_by); #endif -#endif -#endif +#endif // !defined(_WIN32) +#endif // BOINC_SHMEM_H