Project
Loading...
Searching...
No Matches
StaticTLSReserve.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef O2_SIMSETUP_STATICTLSRESERVE_H
13#define O2_SIMSETUP_STATICTLSRESERVE_H
14
15#include <cerrno>
16#include <charconv>
17#include <climits>
18#include <cstdio>
19#include <cstdlib>
20#include <cstring>
21#include <string>
22#include <string_view>
23#include <unistd.h>
24
25namespace o2
26{
27
29constexpr unsigned long Geant4StaticTLSReserve = 32768;
30
34inline std::string withStaticTLSReserve(const char* tunables, unsigned long reserve = Geant4StaticTLSReserve)
35{
36 constexpr std::string_view name = "glibc.rtld.optional_static_tls";
37 std::string kept;
38 bool haveReserve = false;
39 bool malformed = false;
40 unsigned long current = 0;
41 std::string_view rest = tunables ? tunables : "";
42 while (!rest.empty()) {
43 const auto colon = rest.find(':');
44 const std::string_view entry = rest.substr(0, colon);
45 rest = colon == std::string_view::npos ? std::string_view{} : rest.substr(colon + 1);
46 const auto equal = entry.find('=');
47 if (equal == std::string_view::npos || equal == 0) {
48 malformed = true; // also the truncated reserve as it arrives in GRID jobs
49 continue;
50 }
51 if (entry.substr(0, equal) == name) {
52 std::string_view value = entry.substr(equal + 1);
53 int base = 10;
54 if (value.size() > 2 && value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
55 base = 16;
56 value.remove_prefix(2);
57 } else if (value.size() > 1 && value[0] == '0') {
58 base = 8;
59 value.remove_prefix(1);
60 }
61 unsigned long bytes = 0;
62 const auto [end, ec] = std::from_chars(value.data(), value.data() + value.size(), bytes, base);
63 if (!value.empty() && ec == std::errc() && end == value.data() + value.size()) {
64 haveReserve = true;
65 current = bytes;
66 } else {
67 haveReserve = false; // a broken last value leaves no reserve
68 }
69 continue; // our own entry replaces all of them
70 }
71 kept += (kept.empty() ? "" : ":") + std::string(entry);
72 }
73 if (!malformed && haveReserve && current >= reserve) {
74 return {};
75 }
76 return std::string(name) + "=" + std::to_string(reserve) + (kept.empty() ? "" : ":" + kept);
77}
78
80inline bool setStaticTLSReserve(unsigned long reserve = Geant4StaticTLSReserve)
81{
82 const auto tunables = withStaticTLSReserve(getenv("GLIBC_TUNABLES"), reserve);
83 if (tunables.empty()) {
84 return false;
85 }
86 setenv("GLIBC_TUNABLES", tunables.c_str(), 1);
87 return true;
88}
89
92inline void ensureStaticTLSReserve([[maybe_unused]] char* argv[],
93 [[maybe_unused]] unsigned long reserve = Geant4StaticTLSReserve)
94{
95#ifdef __linux__
96 constexpr const char* guard = "O2_STATIC_TLS_REEXEC";
97 if (getenv(guard)) {
98 unsetenv(guard); // restarted already; do not loop if glibc ignores the tunable
99 return;
100 }
101 if (withStaticTLSReserve(getenv("GLIBC_TUNABLES"), reserve).empty()) {
102 return;
103 }
104 // the real path keeps the process name; /proc/self/exe would rename it to "exe"
105 char self[PATH_MAX];
106 const auto length = readlink("/proc/self/exe", self, sizeof(self) - 1);
107 if (length <= 0) {
108 return;
109 }
110 self[length] = '\0';
111 const char* base = strrchr(self, '/');
112 if (strncmp(base ? base + 1 : self, "ld-", 3) == 0) {
113 return; // started through the dynamic loader, which a restart would not reproduce
114 }
115 setStaticTLSReserve(reserve);
116 setenv(guard, "1", 1);
117 fprintf(stderr, "Restarting %s with GLIBC_TUNABLES=%s for the static TLS of Geant4\n", self, getenv("GLIBC_TUNABLES"));
118 execv(self, argv);
119 const int error = errno;
120 unsetenv(guard);
121 fprintf(stderr, "Restart of %s failed: %s\n", self, strerror(error));
122#endif
123}
124
125} // namespace o2
126
127#endif
std::function< bool(const void *, const void *)> equal
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines kept
char error[CURL_ERROR_SIZE]
size_t bytes
GLuint GLuint end
Definition glcorearb.h:469
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string withStaticTLSReserve(const char *tunables, unsigned long reserve=Geant4StaticTLSReserve)
bool setStaticTLSReserve(unsigned long reserve=Geant4StaticTLSReserve)
Sets the static TLS reserve in the environment, for the programs started from here....
constexpr unsigned long Geant4StaticTLSReserve
Static TLS reserve in bytes for a Geant4 built with the initial-exec TLS model and loaded by dlopen.
void ensureStaticTLSReserve(char *argv[], unsigned long reserve=Geant4StaticTLSReserve)
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
void empty(int)