[OpenMP] changing OMP rtl to use shared memory instead of env variable

Patch by Erdner, Todd <todd.erdner@intel.com>

Differential Revision: https://reviews.llvm.org/D89898
This commit is contained in:
AndreyChurbanov 2020-10-26 19:02:21 +03:00
parent a562dc82a8
commit d6a0957467
3 changed files with 111 additions and 8 deletions

View File

@ -125,6 +125,9 @@ function(libomp_get_libflags libflags)
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")

View File

@ -14,6 +14,7 @@ include(CheckCXXCompilerFlag)
include(CheckIncludeFile)
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(LibompCheckLinkerFlag)
include(LibompCheckFortranFlag)
@ -95,6 +96,14 @@ if(${LIBOMP_FORTRAN_MODULES})
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)

View File

@ -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 <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#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 @@ void __kmp_internal_end_library(int gtid_req) {
}
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 @@ void __kmp_internal_end_library(int gtid_req) {
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 @@ void __kmp_register_library_startup(void) {
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);
#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 @@ void __kmp_register_library_startup(void) {
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_register_library_startup(void) {
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);