- Index: Base/CMakeLists.txt
- ===================================================================
- --- Base/CMakeLists.txt (revision 9721)
- +++ Base/CMakeLists.txt (working copy)
- @@ -35,13 +35,15 @@
- if(RDE_BUILD)
- set(PROJECT_SOURCE_FILES ${PROJECT_SOURCE_FILES}
- RecursiveSemaphor.cpp
- - PosixSystem.cpp )
- + PosixSystem.cpp
- + LinuxVDSOClockGetTime.cpp )
- else(RDE_BUILD)
- set(PROJECT_SOURCE_FILES ${PROJECT_SOURCE_FILES}
- TraceBack.cpp
- RovFileSystem.cpp
- RecursiveSemaphor.cpp
- - PosixSystem.cpp )
- + PosixSystem.cpp
- + LinuxVDSOClockGetTime.cpp )
- endif(RDE_BUILD)
- endif(WIN32)
- Index: Base/LinuxVDSOClockGetTime.cpp
- ===================================================================
- --- Base/LinuxVDSOClockGetTime.cpp (nonexistent)
- +++ Base/LinuxVDSOClockGetTime.cpp (working copy)
- @@ -0,0 +1,194 @@
- +
- +/*
- + * LinuxVDSOClockGetTime.cpp - use Linux VDSO
- + * shortcut for |clock_gettime()|, even if userland (g)libc
- + * does not have support for VDSO
- + *
- + * Written by Roland Mainz <roland.mainz@nrubsig.org>
- + *
- + */
- +
- +/*
- + * We compile this as plain ISO C code, so we can use
- + * |rds_clock_gettime()| as drop-in replacement for
- + * POSIX/glibc |clock_gettime()|
- + */
- +extern "C" {
- +
- +#define _XOPEN_SOURCE 700
- +
- +#include <stdio.h>
- +#include <stddef.h>
- +#include <stdint.h>
- +#include <stdlib.h>
- +#include <string.h>
- +#include <elf.h>
- +#include <time.h>
- +#include <pthread.h>
- +#include <sys/auxv.h>
- +
- +/* Catch cursed idiots playing around with XPG config */
- +#if (_XOPEN_SOURCE < 700)
- +#error _XOPEN_SOURCE wrong version
- +#endif
- +
- +
- +/* debug */
- +#if 1
- +#define D(x) x
- +#else
- +#define D(x)
- +#endif
- +
- +/*
- + * workaround for old
- + * /opt/develop/i686-elbe-linux-gnu/bin/i686-elbe-linux-gnu-c++
- + * compiler
- + */
- +#ifndef __PTRDIFF_WIDTH__
- +#define __PTRDIFF_WIDTH__ (__WORDSIZE)
- +#endif
- +
- +/* 32bit vs. 64bit */
- +#if (__PTRDIFF_WIDTH__ == 32)
- +typedef Elf32_Ehdr ElfXX_Ehdr;
- +typedef Elf32_Shdr ElfXX_Shdr;
- +typedef Elf32_Sym ElfXX_Sym;
- +#elif (__PTRDIFF_WIDTH__ == 64)
- +typedef Elf64_Ehdr ElfXX_Ehdr;
- +typedef Elf64_Shdr ElfXX_Shdr;
- +typedef Elf64_Sym ElfXX_Sym;
- +#else
- +#error Unsupported __PTRDIFF_WIDTH__
- +#endif
- +
- +
- +/*
- + * get_linux_vdso_sym() - Look up symbol in AUX AT_SYSINFO_EHDR
- + */
- +static
- +void *get_linux_vdso_sym(const char *funcname)
- +{
- + const char *dynstr;
- + void *ret = NULL;
- + unsigned char *vdso_addr;
- + ssize_t i;
- + size_t si;
- + const char *name;
- + ElfXX_Ehdr *elf_header;
- + ElfXX_Shdr *section_header;
- + ElfXX_Shdr *s;
- + ElfXX_Shdr *s2;
- + ElfXX_Sym *sym;
- +
- + /*
- + * valgrind can disable |AT_SYSINFO_EHDR| - see
- + * https://www.mail-archive.com/kde-bugs-dist@kde.org/msg550927.html
- + */
- + vdso_addr = (unsigned char *)getauxval(AT_SYSINFO_EHDR);
- + if (!vdso_addr) {
- + D((void)fprintf(stderr, "get_linux_vdso_sym: getauxval(AT_SYSINFO_EHDR) failed.\n"));
- + return NULL;
- + }
- +
- + elf_header = (ElfXX_Ehdr *)vdso_addr;
- + section_header = (ElfXX_Shdr *)(vdso_addr + elf_header->e_shoff);
- +
- + for (dynstr = NULL, i=0L; i < elf_header->e_shnum; i++) {
- + s = §ion_header[i];
- + s2 = §ion_header[elf_header->e_shstrndx];
- + name = (const char*)(vdso_addr + s2->sh_offset + s->sh_name);
- +
- + if (strcmp(name, ".dynstr") == 0) {
- + dynstr = (const char *)(vdso_addr + s->sh_offset);
- + break;
- + }
- + }
- +
- + if (!dynstr)
- + return NULL;
- +
- + for (i=0L; i < elf_header->e_shnum; i++) {
- + s = §ion_header[i];
- + s2 = §ion_header[elf_header->e_shstrndx];
- + name = (const char*)(vdso_addr + s2->sh_offset + s->sh_name);
- +
- + /* Not .dynsym ? Then look at next section... */
- + if (strcmp(name, ".dynsym"))
- + continue;
- +
- + for (si=0L; si < (s->sh_size/s->sh_entsize); si++) {
- + sym = &(((ElfXX_Sym*)(vdso_addr + s->sh_offset))[si]);
- + name = dynstr + sym->st_name;
- +
- + D((void)fprintf(stderr, "get_linux_vdso_sym: symbol=|%s| vs. |%s|\n",
- + funcname, name));
- + if (!strcmp(name, funcname)) {
- + ret = (void *)(vdso_addr + sym->st_value);
- + break;
- + }
- + }
- +
- + if (ret)
- + break;
- + }
- +
- + return ret;
- +}
- +
- +
- +/*
- + * Initalisation code
- + */
- +typedef int (clock_gettime_func_t)(clockid_t clk_id, struct timespec *tp);
- +
- +static pthread_once_t rds_clock_gettime_func_is_initialized = PTHREAD_ONCE_INIT;
- +static clock_gettime_func_t *rds_clock_gettime_func = NULL;
- +
- +
- +static
- +void rds_clock_gettime_func_init(void)
- +{
- + rds_clock_gettime_func = (clock_gettime_func_t *)get_linux_vdso_sym("clock_gettime");
- + if (!rds_clock_gettime_func)
- + rds_clock_gettime_func = (clock_gettime_func_t *)get_linux_vdso_sym("__vdso_clock_gettime");
- +
- + D((void)fprintf(stderr, "rds_clock_gettime_func_init: "
- + "rds_clock_gettime_func = 0x%lx (%s)\n",
- + (long)rds_clock_gettime_func,
- + (rds_clock_gettime_func?
- + "Using fast codepath":
- + "Using slow codepath")));
- + if (!rds_clock_gettime_func) {
- + (void)fprintf(stderr, "rds_clock_gettime_func_init: "
- + "WARNING: aux symbol for clock_gettime not found"
- + ", using slow libc codepath.\n");
- + }
- +}
- +
- +
- +/*
- + * |rds_clock_gettime()| - our "public" interface
- + *
- + * Notes:
- + * - The first call might be slower because the call to
- + * |rds_clock_gettime_func_init()|
- + */
- +int rds_clock_gettime(clockid_t clk_id, struct timespec *tp)
- +{
- + (void)pthread_once(&rds_clock_gettime_func_is_initialized,
- + rds_clock_gettime_func_init);
- +
- + if (rds_clock_gettime_func) {
- + /* our own "fast" codepath */
- + return (*rds_clock_gettime_func)(clk_id, tp);
- + }
- + else
- + {
- +#undef clock_gettime
- + /* libc codepath, whatever they use - might be VDSO, might be syscall */
- + return clock_gettime(clk_id, tp);
- + }
- +}
- +
- +} /* extern "C" */
- Index: Base/PosixSystem.hpp
- ===================================================================
- --- Base/PosixSystem.hpp (revision 9721)
- +++ Base/PosixSystem.hpp (working copy)
- @@ -42,6 +42,12 @@
- extern void dumpBackTrace( ostream & _outStr );
- +//-C PROTOTYPES --------------------------------------------------------------
- +extern "C" {
- +int rds_clock_gettime(clockid_t clk_id, struct timespec *tp);
- +}
- +#define clock_gettime(clk_id, tp) rds_clock_gettime((clk_id), (tp))
- +
- //-DEFINES/MACROS--------------------------------------------------------------
- #ifdef DEBUG
- extern void testAssert(T_Name compare);
- Index: Bcm/BasicCalcMod.hpp
- ===================================================================
- --- Bcm/BasicCalcMod.hpp (revision 9721)
- +++ Bcm/BasicCalcMod.hpp (working copy)
- @@ -6,6 +6,11 @@
- #include "Rds3DFileParameter.hpp"
- #include "Rds3DExtFileParameter.hpp"
- +extern "C" int rds_clock_gettime(clockid_t clk_id, struct timespec *tp);
- +// #define clock_gettime(clk_id, tp) rds_clock_gettime((clk_id), (tp))
- +#undef clock_gettime
- +#define clock_gettime rds_clock_gettime
- +
- // Some typedefs to maintain compatibility
- typedef BCM_error cm_error;
- typedef BCM_fatal_error cm_fatal_error;
- Index: Bcm/BcmBase.hpp
- ===================================================================
- --- Bcm/BcmBase.hpp (revision 9721)
- +++ Bcm/BcmBase.hpp (working copy)
- @@ -613,7 +613,7 @@
- void verifyLockEditBitMask();
- void widenAllDynamicLimits();
- void writeCalculationErrorToRDS();
- -
- +
- // static variables
- static C_System::MUTEX* s_phMutex;
- static T_Int32 s_iMutexCount;
- Index: Communication/libcifx/src/OS_Linux.c
- ===================================================================
- --- Communication/libcifx/src/OS_Linux.c (revision 9721)
- +++ Communication/libcifx/src/OS_Linux.c (working copy)
- @@ -50,6 +50,8 @@
- * Linux O/S abstraction for toolkit */
- /*****************************************************************************/
- +#define _GNU_SOURCE 1
- +
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- @@ -63,6 +65,8 @@
- #include <fcntl.h>
- #include <semaphore.h>
- +int rds_clock_gettime(clockid_t clk_id, struct timespec *tp);
- +
- #ifndef CIFX_TOOLKIT_DISABLEPCI
- #include <pciaccess.h>
- #endif
- @@ -568,12 +572,30 @@
- printf("%s() called\n", __FUNCTION__);
- #endif
- - clock_gettime( CLOCK_REALTIME, &lock_ts );
- +#if __GLIBC_PREREQ(2, 30)
- + /*
- + * 1. Use |pthread_mutex_clocklock()| if available because
- + * |pthread_mutex_timedlock()| is not guranteed to count
- + * in |CLOCK_REALTIME|
- + * 2. RDS has |rds_clock_gettime()|, same as POSIX |clock_gettime()|
- + * but faster on platforms with VDSO if glibc has no VDSO support
- + * 3. See https://www.austingroupbugs.net/view.php?id=1216
- + */
- + (void)rds_clock_gettime( CLOCK_REALTIME, &lock_ts );
- lock_ts.tv_sec = ulTimeout / 1000;
- ulTimeout -= lock_ts.tv_sec * 1000;
- lock_ts.tv_nsec = ulTimeout * 1000 * 1000;
- +
- + lRet = pthread_mutex_clocklock(mut, CLOCK_REALTIME, &lock_ts);
- +#else
- + (void)rds_clock_gettime( CLOCK_REALTIME, &lock_ts );
- +
- + lock_ts.tv_sec = ulTimeout / 1000;
- + ulTimeout -= lock_ts.tv_sec * 1000;
- + lock_ts.tv_nsec = ulTimeout * 1000 * 1000;
- lRet = pthread_mutex_timedlock(mut, &lock_ts);
- +#endif
- if( lRet != 0 )
- {
- fprintf(stderr, "WaitMutex: %s\n", strerror(lRet) );
Linux VDSO rds_clock_gettime() patch
Posted by Anonymous on Tue 29th Nov 2022 12:56
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.