diff --git a/openmp/runtime/cmake/LibompHandleFlags.cmake b/openmp/runtime/cmake/LibompHandleFlags.cmake --- a/openmp/runtime/cmake/LibompHandleFlags.cmake +++ b/openmp/runtime/cmake/LibompHandleFlags.cmake @@ -125,6 +125,9 @@ if(${IA32}) libomp_append(libflags_local -lirc_pic LIBOMP_HAVE_IRC_PIC_LIBRARY) endif() + if(LIBOMP_HAVE_SHM_OPEN_WITH_LRT) + libomp_append(libflags_local -lrt) + endif() if(${CMAKE_SYSTEM_NAME} MATCHES "DragonFly|FreeBSD") libomp_append(libflags_local "-Wl,--no-as-needed" LIBOMP_HAVE_AS_NEEDED_FLAG) libomp_append(libflags_local "-lm") diff --git a/openmp/runtime/cmake/config-ix.cmake b/openmp/runtime/cmake/config-ix.cmake --- a/openmp/runtime/cmake/config-ix.cmake +++ b/openmp/runtime/cmake/config-ix.cmake @@ -14,6 +14,7 @@ include(CheckIncludeFile) include(CheckLibraryExists) include(CheckIncludeFiles) +include(CheckSymbolExists) include(LibompCheckLinkerFlag) include(LibompCheckFortranFlag) @@ -95,6 +96,14 @@ libomp_check_fortran_flag(-m32 LIBOMP_HAVE_M32_FORTRAN_FLAG) endif() +# Check for Unix shared memory +check_symbol_exists(shm_open "sys/mman.h" LIBOMP_HAVE_SHM_OPEN_NO_LRT) +if (NOT LIBOMP_HAVE_SHM_OPEN_NO_LRT) + set(CMAKE_REQUIRED_LIBRARIES -lrt) + check_symbol_exists(shm_open "sys/mman.h" LIBOMP_HAVE_SHM_OPEN_WITH_LRT) + set(CMAKE_REQUIRED_LIBRARIES) +endif() + # Check linker flags if(WIN32) libomp_check_linker_flag(/SAFESEH LIBOMP_HAVE_SAFESEH_FLAG) diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -41,6 +41,15 @@ #include "tsan_annotations.h" +#if KMP_OS_WINDOWS +// windows does not need include files as it doesn't use shared memory +#else +#include +#include +#include +#define SHM_SIZE 1024 +#endif + #if defined(KMP_GOMP_COMPAT) char const __kmp_version_alt_comp[] = KMP_VERSION_PREFIX "alternative compiler support: yes"; @@ -6139,7 +6148,6 @@ } KMP_MB(); /* Flush all pending memory write invalidates. */ - /* find out who we are and what we should do */ { int gtid = (gtid_req >= 0) ? gtid_req : __kmp_gtid_get_specific(); @@ -6181,6 +6189,10 @@ if (__kmp_debug_buf) __kmp_dump_debug_buffer(); #endif + // added unregister library call here when we switch to shm linux + // if we don't, it will leave lots of files in /dev/shm + // cleanup shared memory file before exiting. + __kmp_unregister_library(); return; } } @@ -6393,16 +6405,61 @@ char *value = NULL; // Actual value of the environment variable. +#if KMP_OS_UNIX && KMP_DYNAMIC_LIB // shared memory is with dynamic library + char *shm_name = __kmp_str_format("/%s", name); + int shm_preexist = 0; + char *data1; + int fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666); + if ((fd1 == -1) && (errno == EEXIST)) { + // file didn't open because it already exists. + // try opening existing file + fd1 = shm_open(shm_name, O_RDWR, 0666); + if (fd1 == -1) { // file didn't open + // error out here + __kmp_fatal(KMP_MSG(FunctionError, "Can't open SHM"), KMP_ERR(0), + __kmp_msg_null); + } else { + // able to open existing file + shm_preexist = 1; + } + } else if (fd1 == -1) { // SHM didn't open; it was due to error other than + // already exists. + // error out here. + __kmp_fatal(KMP_MSG(FunctionError, "Can't open SHM2"), KMP_ERR(errno), + __kmp_msg_null); + } + if (shm_preexist == 0) { + // we created SHM now set size + if (ftruncate(fd1, SHM_SIZE) == -1) { + // error occured setting size; + __kmp_fatal(KMP_MSG(FunctionError, "Can't set size of SHM"), + KMP_ERR(errno), __kmp_msg_null); + } + } + data1 = + (char *)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); + if (data1 == MAP_FAILED) { + // failed to map shared memory + __kmp_fatal(KMP_MSG(FunctionError, "Can't map SHM"), KMP_ERR(errno), + __kmp_msg_null); + } + if (shm_preexist == 0) { // set data to SHM, set value + KMP_STRCPY_S(data1, SHM_SIZE, __kmp_registration_str); + } + // Read value from either what we just wrote or existing file. + value = __kmp_str_format("%s", data1); // read value from SHM + munmap(data1, SHM_SIZE); + close(fd1); +#else // Windows and unix with static library // Set environment variable, but do not overwrite if it is exist. __kmp_env_set(name, __kmp_registration_str, 0); - // Check the variable is written. + // read value to see if it got set value = __kmp_env_get(name); - if (value != NULL && strcmp(value, __kmp_registration_str) == 0) { +#endif + if (value != NULL && strcmp(value, __kmp_registration_str) == 0) { done = 1; // Ok, environment variable set successfully, exit the loop. - } else { - // Oops. Write failed. Another copy of OpenMP RTL is in memory. // Check whether it alive or dead. int neighbor = 0; // 0 -- unknown status, 1 -- alive, 2 -- dead. @@ -6452,14 +6509,23 @@ done = 1; // Exit the loop. } break; case 2: { // Neighbor is dead. + +#if KMP_OS_UNIX && KMP_DYNAMIC_LIB // shared memory is with dynamic library + // close shared memory. + shm_unlink(shm_name); // this removes file in /dev/shm +#else // Clear the variable and try to register library again. __kmp_env_unset(name); +#endif } break; default: { KMP_DEBUG_ASSERT(0); } break; } } KMP_INTERNAL_FREE((void *)value); - } +#if KMP_OS_UNIX && KMP_DYNAMIC_LIB // shared memory is with dynamic library + KMP_INTERNAL_FREE((void *)shm_name); +#endif + } // while KMP_INTERNAL_FREE((void *)name); } // func __kmp_register_library_startup @@ -6467,15 +6533,40 @@ void __kmp_unregister_library(void) { char *name = __kmp_reg_status_name(); - char *value = __kmp_env_get(name); + char *value = NULL; + +#if KMP_OS_UNIX && KMP_DYNAMIC_LIB // shared memory is with dynamic library + char *shm_name = __kmp_str_format("/%s", name); + int fd1 = shm_open(shm_name, O_RDONLY, 0666); + if (fd1 == -1) { + // file did not open. return. + return; + } + char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0); + if (data1 != MAP_FAILED) { + value = __kmp_str_format("%s", data1); // read value from SHM + munmap(data1, SHM_SIZE); + } + close(fd1); +#else + value = __kmp_env_get(name); +#endif KMP_DEBUG_ASSERT(__kmp_registration_flag != 0); KMP_DEBUG_ASSERT(__kmp_registration_str != NULL); if (value != NULL && strcmp(value, __kmp_registration_str) == 0) { - // Ok, this is our variable. Delete it. +// Ok, this is our variable. Delete it. +#if KMP_OS_UNIX && KMP_DYNAMIC_LIB // shared memory is with dynamic library + shm_unlink(shm_name); // this removes file in /dev/shm +#else __kmp_env_unset(name); +#endif } +#if KMP_OS_UNIX && KMP_DYNAMIC_LIB // shared memory is with dynamic library + KMP_INTERNAL_FREE(shm_name); +#endif + KMP_INTERNAL_FREE(__kmp_registration_str); KMP_INTERNAL_FREE(value); KMP_INTERNAL_FREE(name);