pastebin - collaborative debugging tool
rovema.kpaste.net RSS


Linux VDSO rds_clock_gettime() patch
Posted by Anonymous on Tue 29th Nov 2022 12:56
raw | new post

  1. Index: Base/CMakeLists.txt
  2. ===================================================================
  3. --- Base/CMakeLists.txt (revision 9721)
  4. +++ Base/CMakeLists.txt (working copy)
  5. @@ -35,13 +35,15 @@
  6.      if(RDE_BUILD)
  7.          set(PROJECT_SOURCE_FILES ${PROJECT_SOURCE_FILES}
  8.              RecursiveSemaphor.cpp
  9. -            PosixSystem.cpp )
  10. +            PosixSystem.cpp
  11. +           LinuxVDSOClockGetTime.cpp )
  12.      else(RDE_BUILD)
  13.    set(PROJECT_SOURCE_FILES ${PROJECT_SOURCE_FILES}
  14.        TraceBack.cpp
  15.        RovFileSystem.cpp
  16.        RecursiveSemaphor.cpp
  17. -      PosixSystem.cpp )
  18. +      PosixSystem.cpp
  19. +      LinuxVDSOClockGetTime.cpp )
  20.    endif(RDE_BUILD)
  21.  endif(WIN32)
  22.  
  23. Index: Base/LinuxVDSOClockGetTime.cpp
  24. ===================================================================
  25. --- Base/LinuxVDSOClockGetTime.cpp      (nonexistent)
  26. +++ Base/LinuxVDSOClockGetTime.cpp      (working copy)
  27. @@ -0,0 +1,194 @@
  28. +
  29. +/*
  30. + * LinuxVDSOClockGetTime.cpp - use Linux VDSO
  31. + * shortcut for |clock_gettime()|, even if userland (g)libc
  32. + * does not have support for VDSO
  33. + *
  34. + * Written by Roland Mainz <roland.mainz@nrubsig.org>
  35. + *
  36. + */
  37. +
  38. +/*
  39. + * We compile this as plain ISO C code, so we can use
  40. + * |rds_clock_gettime()| as drop-in replacement for
  41. + * POSIX/glibc |clock_gettime()|
  42. + */
  43. +extern "C" {
  44. +
  45. +#define _XOPEN_SOURCE 700
  46. +
  47. +#include <stdio.h>
  48. +#include <stddef.h>
  49. +#include <stdint.h>
  50. +#include <stdlib.h>
  51. +#include <string.h>
  52. +#include <elf.h>
  53. +#include <time.h>
  54. +#include <pthread.h>
  55. +#include <sys/auxv.h>
  56. +
  57. +/* Catch cursed idiots playing around with XPG config */
  58. +#if (_XOPEN_SOURCE < 700)
  59. +#error _XOPEN_SOURCE wrong version
  60. +#endif
  61. +
  62. +
  63. +/* debug */
  64. +#if 1
  65. +#define D(x) x
  66. +#else
  67. +#define D(x)
  68. +#endif
  69. +
  70. +/*
  71. + * workaround for old
  72. + * /opt/develop/i686-elbe-linux-gnu/bin/i686-elbe-linux-gnu-c++
  73. + * compiler
  74. + */
  75. +#ifndef __PTRDIFF_WIDTH__
  76. +#define __PTRDIFF_WIDTH__ (__WORDSIZE)
  77. +#endif
  78. +
  79. +/* 32bit vs. 64bit */
  80. +#if (__PTRDIFF_WIDTH__ == 32)
  81. +typedef Elf32_Ehdr     ElfXX_Ehdr;
  82. +typedef Elf32_Shdr     ElfXX_Shdr;
  83. +typedef Elf32_Sym      ElfXX_Sym;
  84. +#elif (__PTRDIFF_WIDTH__ == 64)
  85. +typedef Elf64_Ehdr     ElfXX_Ehdr;
  86. +typedef Elf64_Shdr     ElfXX_Shdr;
  87. +typedef Elf64_Sym      ElfXX_Sym;
  88. +#else
  89. +#error Unsupported __PTRDIFF_WIDTH__
  90. +#endif
  91. +
  92. +
  93. +/*
  94. + * get_linux_vdso_sym() - Look up symbol in AUX AT_SYSINFO_EHDR
  95. + */
  96. +static
  97. +void *get_linux_vdso_sym(const char *funcname)
  98. +{
  99. +       const char      *dynstr;
  100. +       void            *ret = NULL;
  101. +       unsigned char   *vdso_addr;
  102. +       ssize_t         i;
  103. +       size_t          si;
  104. +       const char      *name;
  105. +       ElfXX_Ehdr      *elf_header;
  106. +       ElfXX_Shdr      *section_header;
  107. +       ElfXX_Shdr      *s;
  108. +       ElfXX_Shdr      *s2;
  109. +       ElfXX_Sym       *sym;
  110. +
  111. +       /*
  112. +        * valgrind can disable |AT_SYSINFO_EHDR| - see
  113. +        * https://www.mail-archive.com/kde-bugs-dist@kde.org/msg550927.html
  114. +        */
  115. +       vdso_addr = (unsigned char *)getauxval(AT_SYSINFO_EHDR);
  116. +       if (!vdso_addr) {
  117. +               D((void)fprintf(stderr, "get_linux_vdso_sym: getauxval(AT_SYSINFO_EHDR) failed.\n"));
  118. +               return NULL;
  119. +       }
  120. +    
  121. +       elf_header = (ElfXX_Ehdr *)vdso_addr;
  122. +       section_header = (ElfXX_Shdr *)(vdso_addr + elf_header->e_shoff);
  123. +
  124. +       for (dynstr = NULL, i=0L; i < elf_header->e_shnum; i++) {
  125. +               s    = &section_header[i];
  126. +               s2   = &section_header[elf_header->e_shstrndx];
  127. +               name = (const char*)(vdso_addr + s2->sh_offset + s->sh_name);
  128. +
  129. +               if (strcmp(name, ".dynstr") == 0) {
  130. +                       dynstr = (const char *)(vdso_addr + s->sh_offset);
  131. +                       break;
  132. +               }
  133. +       }
  134. +      
  135. +       if (!dynstr)
  136. +               return NULL;
  137. +
  138. +       for (i=0L; i < elf_header->e_shnum; i++) {
  139. +               s    = &section_header[i];
  140. +               s2   = &section_header[elf_header->e_shstrndx];
  141. +               name = (const char*)(vdso_addr + s2->sh_offset + s->sh_name);
  142. +
  143. +               /* Not .dynsym ? Then look at next section... */
  144. +               if (strcmp(name, ".dynsym"))
  145. +                       continue;
  146. +
  147. +               for (si=0L; si < (s->sh_size/s->sh_entsize); si++) {
  148. +                       sym = &(((ElfXX_Sym*)(vdso_addr + s->sh_offset))[si]);
  149. +                       name = dynstr + sym->st_name;
  150. +
  151. +                       D((void)fprintf(stderr, "get_linux_vdso_sym: symbol=|%s| vs. |%s|\n",
  152. +                               funcname, name));
  153. +                       if (!strcmp(name, funcname)) {
  154. +                               ret = (void *)(vdso_addr + sym->st_value);
  155. +                               break;
  156. +                       }
  157. +               }
  158. +
  159. +               if (ret)
  160. +                       break;
  161. +       }
  162. +
  163. +       return ret;
  164. +}
  165. +
  166. +
  167. +/*
  168. + * Initalisation code
  169. + */
  170. +typedef int (clock_gettime_func_t)(clockid_t clk_id, struct timespec *tp);
  171. +
  172. +static pthread_once_t rds_clock_gettime_func_is_initialized = PTHREAD_ONCE_INIT;
  173. +static clock_gettime_func_t *rds_clock_gettime_func = NULL;
  174. +
  175. +
  176. +static
  177. +void rds_clock_gettime_func_init(void)
  178. +{
  179. +       rds_clock_gettime_func = (clock_gettime_func_t *)get_linux_vdso_sym("clock_gettime");
  180. +       if (!rds_clock_gettime_func)
  181. +               rds_clock_gettime_func = (clock_gettime_func_t *)get_linux_vdso_sym("__vdso_clock_gettime");
  182. +
  183. +       D((void)fprintf(stderr, "rds_clock_gettime_func_init: "
  184. +               "rds_clock_gettime_func = 0x%lx (%s)\n",
  185. +               (long)rds_clock_gettime_func,
  186. +               (rds_clock_gettime_func?
  187. +                       "Using fast codepath":
  188. +                       "Using slow codepath")));
  189. +       if (!rds_clock_gettime_func) {
  190. +               (void)fprintf(stderr, "rds_clock_gettime_func_init: "
  191. +                       "WARNING: aux symbol for clock_gettime not found"
  192. +                       ", using slow libc codepath.\n");
  193. +       }
  194. +}
  195. +
  196. +
  197. +/*
  198. + * |rds_clock_gettime()| - our "public" interface
  199. + *
  200. + * Notes:
  201. + * - The first call might be slower because the call to
  202. + * |rds_clock_gettime_func_init()|
  203. + */
  204. +int rds_clock_gettime(clockid_t clk_id, struct timespec *tp)
  205. +{
  206. +       (void)pthread_once(&rds_clock_gettime_func_is_initialized,
  207. +               rds_clock_gettime_func_init);
  208. +
  209. +       if (rds_clock_gettime_func) {
  210. +               /* our own "fast" codepath */
  211. +               return (*rds_clock_gettime_func)(clk_id, tp);
  212. +       }
  213. +       else
  214. +       {
  215. +#undef clock_gettime
  216. +               /* libc codepath, whatever they use - might be VDSO, might be syscall */
  217. +               return clock_gettime(clk_id, tp);
  218. +       }
  219. +}
  220. +
  221. +} /* extern "C" */
  222. Index: Base/PosixSystem.hpp
  223. ===================================================================
  224. --- Base/PosixSystem.hpp        (revision 9721)
  225. +++ Base/PosixSystem.hpp        (working copy)
  226. @@ -42,6 +42,12 @@
  227.  
  228.  extern void dumpBackTrace( ostream & _outStr );
  229.  
  230. +//-C PROTOTYPES --------------------------------------------------------------
  231. +extern "C" {
  232. +int rds_clock_gettime(clockid_t clk_id, struct timespec *tp);
  233. +}
  234. +#define clock_gettime(clk_id, tp) rds_clock_gettime((clk_id), (tp))
  235. +
  236.  //-DEFINES/MACROS--------------------------------------------------------------
  237.  #ifdef DEBUG
  238.  extern void testAssert(T_Name compare);
  239. Index: Bcm/BasicCalcMod.hpp
  240. ===================================================================
  241. --- Bcm/BasicCalcMod.hpp        (revision 9721)
  242. +++ Bcm/BasicCalcMod.hpp        (working copy)
  243. @@ -6,6 +6,11 @@
  244.  #include "Rds3DFileParameter.hpp"
  245.  #include "Rds3DExtFileParameter.hpp"
  246.  
  247. +extern "C" int rds_clock_gettime(clockid_t clk_id, struct timespec *tp);
  248. +// #define clock_gettime(clk_id, tp) rds_clock_gettime((clk_id), (tp))
  249. +#undef clock_gettime
  250. +#define clock_gettime rds_clock_gettime
  251. +
  252.  // Some typedefs to maintain compatibility
  253.  typedef BCM_error cm_error;
  254.  typedef BCM_fatal_error cm_fatal_error;
  255. Index: Bcm/BcmBase.hpp
  256. ===================================================================
  257. --- Bcm/BcmBase.hpp     (revision 9721)
  258. +++ Bcm/BcmBase.hpp     (working copy)
  259. @@ -613,7 +613,7 @@
  260.      void verifyLockEditBitMask();
  261.      void widenAllDynamicLimits();
  262.      void writeCalculationErrorToRDS();
  263. -
  264. +
  265.      // static variables
  266.      static C_System::MUTEX* s_phMutex;
  267.      static T_Int32 s_iMutexCount;
  268. Index: Communication/libcifx/src/OS_Linux.c
  269. ===================================================================
  270. --- Communication/libcifx/src/OS_Linux.c        (revision 9721)
  271. +++ Communication/libcifx/src/OS_Linux.c        (working copy)
  272. @@ -50,6 +50,8 @@
  273.  *   Linux O/S abstraction for toolkit                                        */
  274.  /*****************************************************************************/
  275.  
  276. +#define _GNU_SOURCE 1
  277. +
  278.  #include <stdlib.h>
  279.  #include <string.h>
  280.  #include <stdio.h>
  281. @@ -63,6 +65,8 @@
  282.  #include <fcntl.h>
  283.  #include <semaphore.h>
  284.  
  285. +int rds_clock_gettime(clockid_t clk_id, struct timespec *tp);
  286. +
  287.  #ifndef CIFX_TOOLKIT_DISABLEPCI
  288.    #include <pciaccess.h>
  289.  #endif
  290. @@ -568,12 +572,30 @@
  291.    printf("%s() called\n", __FUNCTION__);
  292.  #endif
  293.  
  294. -  clock_gettime( CLOCK_REALTIME, &lock_ts );
  295. +#if __GLIBC_PREREQ(2, 30)
  296. +  /*
  297. +   * 1. Use |pthread_mutex_clocklock()| if available because
  298. +   * |pthread_mutex_timedlock()| is not guranteed to count
  299. +   * in |CLOCK_REALTIME|
  300. +   * 2. RDS has |rds_clock_gettime()|, same as POSIX |clock_gettime()|
  301. +   * but faster on platforms with VDSO if glibc has no VDSO support
  302. +   * 3. See https://www.austingroupbugs.net/view.php?id=1216
  303. +   */
  304. +  (void)rds_clock_gettime( CLOCK_REALTIME, &lock_ts );
  305.  
  306.    lock_ts.tv_sec  = ulTimeout / 1000;
  307.    ulTimeout      -= lock_ts.tv_sec * 1000;
  308.    lock_ts.tv_nsec = ulTimeout * 1000 * 1000;
  309. +
  310. +  lRet = pthread_mutex_clocklock(mut, CLOCK_REALTIME, &lock_ts);
  311. +#else
  312. +  (void)rds_clock_gettime( CLOCK_REALTIME, &lock_ts );
  313. +
  314. +  lock_ts.tv_sec  = ulTimeout / 1000;
  315. +  ulTimeout      -= lock_ts.tv_sec * 1000;
  316. +  lock_ts.tv_nsec = ulTimeout * 1000 * 1000;
  317.    lRet = pthread_mutex_timedlock(mut, &lock_ts);
  318. +#endif
  319.    if( lRet != 0 )
  320.    {
  321.      fprintf(stderr, "WaitMutex: %s\n", strerror(lRet) );

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at