Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:45:13

0001 /*
0002  * SPDX-FileCopyrightText: Copyright (c) 2009-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
0003  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0004  *
0005  * Licensed under the Apache License, Version 2.0 (the "License");
0006  * you may not use this file except in compliance with the License.
0007  * You may obtain a copy of the License at
0008  *
0009  *     http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  *
0017  * Licensed under the Apache License v2.0 with LLVM Exceptions.
0018  * See https://nvidia.github.io/NVTX/LICENSE.txt for license information.
0019  */
0020 
0021 #ifndef NVTX_IMPL_GUARD
0022 #error Never include this file directly -- it is automatically included by nvToolsExt.h (except when NVTX_NO_IMPL is defined).
0023 #endif
0024 
0025 #if defined(NVTX_AS_SYSTEM_HEADER)
0026 #if defined(__clang__)
0027 #pragma clang system_header
0028 #elif defined(__GNUC__) || defined(__NVCOMPILER)
0029 #pragma GCC system_header
0030 #elif defined(_MSC_VER)
0031 #pragma system_header
0032 #endif
0033 #endif
0034 
0035 /* ---- Platform-independent helper definitions and functions ---- */
0036 
0037 /* Prefer macros over inline functions to reduce symbol resolution at link time */
0038 
0039 #if defined(_WIN32)
0040 #define NVTX_PATHCHAR   wchar_t
0041 #define NVTX_STR(x)     L##x
0042 #define NVTX_GETENV     _wgetenv
0043 #define NVTX_BUFSIZE    16384
0044 #define NVTX_DLLHANDLE  HMODULE
0045 #define NVTX_DLLOPEN(x) LoadLibraryW(x)
0046 #define NVTX_DLLFUNC(h, x) NVTX_REINTERPRET_CAST(void(*)(void), GetProcAddress((h), (x)))
0047 #define NVTX_DLLCLOSE   FreeLibrary
0048 #define NVTX_DLLDEFAULT NVTX_NULLPTR
0049 #define NVTX_YIELD()    SwitchToThread()
0050 #define NVTX_MEMBAR()   MemoryBarrier()
0051 #define NVTX_ATOMIC_WRITE_32(address, value) \
0052     InterlockedExchange(NVTX_REINTERPRET_CAST(volatile LONG*, (address)), (value))
0053 #define NVTX_ATOMIC_CAS_32(old, address, exchange, comparand) \
0054     (old) = InterlockedCompareExchange(NVTX_REINTERPRET_CAST(volatile LONG*, (address)), (exchange), (comparand))
0055 #elif defined(__GNUC__)
0056 #define NVTX_PATHCHAR   char
0057 #define NVTX_STR(x)     x
0058 #define NVTX_GETENV     getenv
0059 #define NVTX_BUFSIZE    16384
0060 #define NVTX_DLLHANDLE  void*
0061 #define NVTX_DLLOPEN(x) dlopen(x, RTLD_LAZY)
0062 #define NVTX_DLLFUNC(h, x) dlsym((h), (x))
0063 #define NVTX_DLLCLOSE   dlclose
0064 #if !defined(__APPLE__)
0065 #define NVTX_DLLDEFAULT NVTX_NULLPTR
0066 #else
0067 #define NVTX_DLLDEFAULT RTLD_DEFAULT
0068 #endif
0069 #define NVTX_YIELD()    sched_yield()
0070 #define NVTX_MEMBAR()   __sync_synchronize()
0071 /* Ensure full memory barrier for atomics, to match Windows functions */
0072 #define NVTX_ATOMIC_WRITE_32(address, value) \
0073     __sync_synchronize(); *(address) = (value); __sync_synchronize()
0074 #define NVTX_ATOMIC_CAS_32(old, address, exchange, comparand) \
0075     (old) = __sync_val_compare_and_swap((address), (comparand), (exchange))
0076 #else
0077 #error The library does not support your configuration!
0078 #endif
0079 
0080 /* NVTX_LOAD_SEQUENCE_VERSION macro
0081 *
0082 *  NVTX3 can update the search sequence used for finding a suitable injection library.
0083 *  If multiple copies of the NVTX3 headers are included in the same translation unit,
0084 *  the one included first sets the loader sequence.  If there is any problem where a
0085 *  tool is expected to load, but is not loading, the app can test this macro to verify
0086 *  which version of the search is being used.  Check if NVTX_LOAD_SEQUENCE_VERSION is
0087 *  defined; if it is not, the version is 1.  Otherwise, the version is indicated by
0088 *  the value of NVTX_LOAD_SEQUENCE_VERSION.
0089 *
0090 *  Version history:
0091 *    1: NVTX3 initial implementation.  The search continues until a usable function
0092 *       pointer is found.  If none is found, init aborts and rolls back anything it
0093 *       did during the search (e.g. any loaded libraries are unloaded).  If a non-zero
0094 *       function pointer is found, it is called.  If that function returns non-zero
0095 *       ("true" in C), that indicates a tool successfully initialized.  If it returns
0096 *       zero ("false"), the tool init was unsuccessful, so init aborts and rolls back
0097 *       anything it did.  No further attempt is made to search for a different init
0098 *       function if the first one found returns false.  The search order is:
0099 *       - Check for env var NVTX_INJECTION64_PATH (or "32" in 32-bit process)
0100 *         - Treat env var value as path to dynamic library, try loading it
0101 *         - If it loads, try get the exported symbol "InitializeInjectionNvtx2"
0102 *         - If this returns a non-null pointer, the search finishes here
0103 *       - (Android only) Look for libNvtxInjection64.so (or "32" in 32-bit process)
0104 *         - Must be in the /data/data/<package name>/files" directory
0105 *         - Treat env var value as path to dynamic library, try loading it
0106 *         - If it loads, try get the exported symbol "InitializeInjectionNvtx2"
0107 *         - If this returns a non-null pointer, the search finishes here
0108 *       Note: There were two other options partially implemented, but disabled.
0109 *       - For supporting a pre-injected library on POSIX platforms, e.g. with
0110 *         LD_PRELOAD, try using dlsym with a null module handle to get the init
0111 *         function.  This was unconditionally disabled after finding cases where
0112 *         a tool loaded multiple injections that supported NVTX, and couldn't
0113 *         control which one was getting picked by the NVTX loader.
0114 *       - (Linux only, not including Cygwin) Check for static injection using a
0115 *         weak symbol.  This was implemented incorrectly, so it wasn't usable.
0116 *
0117 *    2: Fix the support for static injection libraries.  This is meant for cases
0118 *       where dlopen is not supported or allowed, and the executable format has
0119 *       support for weak symbols.  Tools may provide a static library with a
0120 *       C-linkage symbol named "InitializeInjectionNvtx2_fnptr", whose type is
0121 *       NvtxInitializeInjectionNvtxFunc_t, i.e. a function pointer to NVTX init
0122 *       function.  If such a symbol is provided by a static library, the NVTX
0123 *       loader's weak symbol will bind to it and call it for initialization.
0124 *       Otherwise, the weak symbol will be defined by NVTX and default to null,
0125 *       indicating no static injection library is present.  Static injection is
0126 *       last in the load sequence, because it gives all the run-time methods of
0127 *       injection to override a program's compiled-in tool without rebuilding the
0128 *       program.  The search order is:
0129 *       - Check for env var NVTX_INJECTION64_PATH (or "32" in 32-bit process)
0130 *         - Treat env var value as path to dynamic library, try loading it
0131 *         - If it loads, try get the exported symbol "InitializeInjectionNvtx2"
0132 *         - If this returns a non-null pointer, the search finishes here
0133 *       - (Android only) Look for libNvtxInjection64.so (or "32" in 32-bit process)
0134 *         - Must be in the /data/data/<package name>/files" directory
0135 *         - Treat env var value as path to dynamic library, try loading it
0136 *         - If it loads, try get the exported symbol "InitializeInjectionNvtx2"
0137 *         - If this returns a non-null pointer, the search finishes here
0138 *       - (Currently disabled, experimental support for non-Windows) Use dlsym
0139 *         with a null module handle to query the process-wide dynamic symbol
0140 *         table for a function named "InitializeInjectionNvtx2Preinject".  The
0141 *         symbol is different to prevent injections from being loaded this way
0142 *         unless they choose to do so.
0143 *         - If this returns a non-null pointer, the search finishes here
0144 *       - (GCC-like compilers with ELF binary targets only) Check for static
0145 *         injection using a weak symbol "InitializeInjectionNvtx2_fnptr".
0146 *       If the default support choices in this header are not working as expected,
0147 *       clients may now override load sequence support decisions by defining these
0148 *       macros before including the NVTX header files:
0149 *       - NVTX_SUPPORT_ENV_VARS
0150 *       - NVTX_SUPPORT_DYNAMIC_INJECTION_LIBRARY
0151 *       - NVTX_SUPPORT_ANDROID_INJECTION_LIBRARY_IN_PACKAGE
0152 *       - NVTX_SUPPORT_ALREADY_INJECTED_LIBRARY
0153 *       - NVTX_SUPPORT_STATIC_INJECTION_LIBRARY
0154 */
0155 #define NVTX_LOAD_SEQUENCE_VERSION 2
0156 
0157 #ifndef NVTX_SUPPORT_ALREADY_INJECTED_LIBRARY
0158 /* Define this to 1 for platforms that where pre-injected libraries can be discovered. */
0159 #if defined(_WIN32)
0160 /* Windows has no process-wide table of dynamic library symbols, so this can't be supported. */
0161 #define NVTX_SUPPORT_ALREADY_INJECTED_LIBRARY 0
0162 #else
0163 /* POSIX platforms allow calling dlsym on a null module to use the process-wide table.
0164 *  Note: Still disabled in load sequence version 2.  Needs to support following the
0165 *  RTLD_NEXT chain, and needs more testing before support can be enabled by default.*/
0166 #define NVTX_SUPPORT_ALREADY_INJECTED_LIBRARY 0
0167 #endif
0168 #endif
0169 
0170 #ifndef NVTX_SUPPORT_ENV_VARS
0171 /* Define this to 1 for platforms that support environment variables */
0172 /* TODO: Detect UWP, a.k.a. Windows Store app, and set this to 0. */
0173 /* Try:  #if defined(WINAPI_FAMILY_PARTITION) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */
0174 #define NVTX_SUPPORT_ENV_VARS 1
0175 #endif
0176 
0177 #ifndef NVTX_SUPPORT_DYNAMIC_INJECTION_LIBRARY
0178 /* Define this to 1 for platforms that support dynamic/shared libraries */
0179 #define NVTX_SUPPORT_DYNAMIC_INJECTION_LIBRARY 1
0180 #endif
0181 
0182 #ifndef NVTX_SUPPORT_ANDROID_INJECTION_LIBRARY_IN_PACKAGE
0183 #if defined(__ANDROID__)
0184 #define NVTX_SUPPORT_ANDROID_INJECTION_LIBRARY_IN_PACKAGE 1
0185 #else
0186 #define NVTX_SUPPORT_ANDROID_INJECTION_LIBRARY_IN_PACKAGE 0
0187 #endif
0188 #endif
0189 
0190 #ifndef NVTX_SUPPORT_STATIC_INJECTION_LIBRARY
0191 /* On platforms that support weak symbols (i.e. non-Windows), injection libraries may
0192 *  be statically linked into an application.  This is useful for platforms where dynamic
0193 *  injection is not available.  Weak symbols not marked extern are definitions, not just
0194 *  declarations.  They are guaranteed to be initialized to zero if no normal definitions
0195 *  are found by the linker to override them.  This means the NVTX load sequence can safely
0196 *  detect the presence of a static injection -- if InitializeInjectionNvtx2_fnptr is zero,
0197 *  there is no static injection. */
0198 #if defined(__GNUC__) && !defined(_WIN32) && !defined(__CYGWIN__)
0199 #define NVTX_SUPPORT_STATIC_INJECTION_LIBRARY 1
0200 #else
0201 #define NVTX_SUPPORT_STATIC_INJECTION_LIBRARY 0
0202 #endif
0203 #endif
0204 
0205 #if NVTX_SUPPORT_STATIC_INJECTION_LIBRARY && !defined(NVTX_STATIC_INJECTION_IMPL)
0206 /* To make an NVTX injection library support static injection, it must do these things:
0207 *  - Define InitializeInjectionNvtx2_fnptr as a normal symbol (not weak), pointing to
0208 *    the implementation of InitializeInjectionNvtx2 (which does not need to be a
0209 *    dynamic export if only supporting static injection).
0210 *  - Define NVTX_STATIC_INJECTION_IMPL so the weak definition below is skipped.
0211 *  - Compile the static injection files with -fPIC if they are to be linked with other
0212 *    files compiled this way.  If you forget this, GCC will simply tell you to add it.
0213 *  When building the application, there a few ways to link in a static injection:
0214 *  - Compile the injection's source files normally, and include the .o files as inputs
0215 *    to the linker.
0216 *  - If the injection is provided as an archive (.a file), it will not resolve any
0217 *    unresolved symbols, so the linker will skip it by default.  This can be fixed
0218 *    by wrapping the static injection's name on the linker command line with options
0219 *    to treat it differently.  For example:
0220 *      gcc example.o libfoo.a -Wl,--whole-archive libinj-static.a -Wl,--no-whole-archive libbar.a
0221 *    Note that libinj-static.a is bracketed by options to turn on "whole archive" and
0222 *    then back off again afterwards, so libfoo.a and libbar.a are linked normally.
0223 *  - In CMake, a static injection can be added with options like this:
0224 *      target_link_libraries(app PRIVATE -Wl,--whole-archive inj-static -Wl,--no-whole-archive)
0225 */
0226 __attribute__((weak)) NvtxInitializeInjectionNvtxFunc_t InitializeInjectionNvtx2_fnptr;
0227 #endif
0228 
0229 /* This function tries to find or load an NVTX injection library and get the
0230 *  address of its InitializeInjection2 function.  If such a function pointer
0231 *  is found, it is called, and passed the address of this NVTX instance's
0232 *  nvtxGetExportTable function, so the injection can attach to this instance.
0233 *  If the initialization fails for any reason, any dynamic library loaded will
0234 *  be freed, and all NVTX implementation functions will be set to no-ops.  If
0235 *  initialization succeeds, NVTX functions not attached to the tool will be set
0236 *  to no-ops.  This is implemented as one function instead of several small
0237 *  functions to minimize the number of weak symbols the linker must resolve.
0238 *  Order of search is:
0239 *  - Pre-injected library exporting InitializeInjectionNvtx2
0240 *  - Loadable library exporting InitializeInjectionNvtx2
0241 *      - Path specified by env var NVTX_INJECTION??_PATH (?? is 32 or 64)
0242 *      - On Android, libNvtxInjection??.so within the package (?? is 32 or 64)
0243 *  - Statically-linked injection library defining InitializeInjectionNvtx2_fnptr
0244 */
0245 NVTX_LINKONCE_FWDDECL_FUNCTION int NVTX_VERSIONED_IDENTIFIER(nvtxInitializeInjectionLibrary)(void);
0246 NVTX_LINKONCE_DEFINE_FUNCTION int NVTX_VERSIONED_IDENTIFIER(nvtxInitializeInjectionLibrary)(void)
0247 {
0248     static const char initFuncName[] = "InitializeInjectionNvtx2";
0249 #if NVTX_SUPPORT_ALREADY_INJECTED_LIBRARY
0250     static const char initFuncPreinjectName[] = "InitializeInjectionNvtx2Preinject";
0251 #endif
0252     NvtxInitializeInjectionNvtxFunc_t init_fnptr = NVTX_NULLPTR;
0253     NVTX_DLLHANDLE injectionLibraryHandle = NVTX_DLLDEFAULT;
0254     int entryPointStatus = 0;
0255 
0256 #if NVTX_SUPPORT_DYNAMIC_INJECTION_LIBRARY
0257     /* Try discovering dynamic injection library to load */
0258     {
0259 #if NVTX_SUPPORT_ENV_VARS
0260         /* If env var NVTX_INJECTION64_PATH is set, it should contain the path
0261         *  to a 64-bit dynamic NVTX injection library (and similar for 32-bit). */
0262         const NVTX_PATHCHAR* const nvtxEnvVarName = (sizeof(void*) == 4)
0263             ? NVTX_STR("NVTX_INJECTION32_PATH")
0264             : NVTX_STR("NVTX_INJECTION64_PATH");
0265 #endif /* NVTX_SUPPORT_ENV_VARS */
0266         NVTX_PATHCHAR injectionLibraryPathBuf[NVTX_BUFSIZE];
0267         const NVTX_PATHCHAR* injectionLibraryPath = NVTX_NULLPTR;
0268 
0269         /* Refer to this variable explicitly in case all references to it are #if'ed out */
0270         (void)injectionLibraryPathBuf;
0271 
0272 #if NVTX_SUPPORT_ENV_VARS
0273         /* Disable the warning for getenv & _wgetenv -- this usage is safe because
0274         *  these functions are not called again before using the returned value. */
0275 #if defined(_MSC_VER)
0276 #pragma warning( push )
0277 #pragma warning( disable : 4996 )
0278 #endif
0279         injectionLibraryPath = NVTX_GETENV(nvtxEnvVarName);
0280 #if defined(_MSC_VER)
0281 #pragma warning( pop )
0282 #endif
0283 #endif
0284 
0285 #if NVTX_SUPPORT_ANDROID_INJECTION_LIBRARY_IN_PACKAGE
0286         if (!injectionLibraryPath)
0287         {
0288             const char *bits = (sizeof(void*) == 4) ? "32" : "64";
0289             char cmdlineBuf[32];
0290             char pkgName[PATH_MAX];
0291             int count;
0292             int pid;
0293             FILE *fp;
0294             size_t bytesRead;
0295             size_t pos;
0296 
0297             pid = NVTX_STATIC_CAST(int, getpid());
0298             count = snprintf(cmdlineBuf, sizeof(cmdlineBuf), "/proc/%d/cmdline", pid);
0299             if (count <= 0 || count >= NVTX_STATIC_CAST(int, sizeof(cmdlineBuf)))
0300             {
0301                 NVTX_ERR("Path buffer too small for: /proc/%d/cmdline\n", pid);
0302                 return NVTX_ERR_INIT_ACCESS_LIBRARY;
0303             }
0304 
0305             fp = fopen(cmdlineBuf, "r");
0306             if (!fp)
0307             {
0308                 NVTX_ERR("File couldn't be opened: %s\n", cmdlineBuf);
0309                 return NVTX_ERR_INIT_ACCESS_LIBRARY;
0310             }
0311 
0312             bytesRead = fread(pkgName, 1, sizeof(pkgName) - 1, fp);
0313             fclose(fp);
0314             if (bytesRead == 0)
0315             {
0316                 NVTX_ERR("Package name couldn't be read from file: %s\n", cmdlineBuf);
0317                 return NVTX_ERR_INIT_ACCESS_LIBRARY;
0318             }
0319 
0320             pkgName[bytesRead] = 0;
0321 
0322             /* String can contain colon as a process separator. In this case the package name is before the colon. */
0323             pos = 0;
0324             while (pos < bytesRead && pkgName[pos] != ':' && pkgName[pos] != '\0')
0325             {
0326                 ++pos;
0327             }
0328             pkgName[pos] = 0;
0329 
0330             count = snprintf(injectionLibraryPathBuf, NVTX_BUFSIZE, "/data/data/%s/files/libNvtxInjection%s.so", pkgName, bits);
0331             if (count <= 0 || count >= NVTX_BUFSIZE)
0332             {
0333                 NVTX_ERR("Path buffer too small for: /data/data/%s/files/libNvtxInjection%s.so\n", pkgName, bits);
0334                 return NVTX_ERR_INIT_ACCESS_LIBRARY;
0335             }
0336 
0337             /* On Android, verify path is accessible due to aggressive file access restrictions. */
0338             /* For dlopen, if the filename contains a leading slash, then it is interpreted as a */
0339             /* relative or absolute pathname; otherwise it will follow the rules in ld.so. */
0340             if (injectionLibraryPathBuf[0] == '/')
0341             {
0342 #if (__ANDROID_API__ < 21)
0343                 int access_err = access(injectionLibraryPathBuf, F_OK | R_OK);
0344 #else
0345                 int access_err = faccessat(AT_FDCWD, injectionLibraryPathBuf, F_OK | R_OK, 0);
0346 #endif
0347                 if (access_err != 0)
0348                 {
0349                     NVTX_ERR("Injection library path wasn't accessible [code=%s] [path=%s]\n", strerror(errno), injectionLibraryPathBuf);
0350                     return NVTX_ERR_INIT_ACCESS_LIBRARY;
0351                 }
0352             }
0353             injectionLibraryPath = injectionLibraryPathBuf;
0354         }
0355 #endif /* NVTX_SUPPORT_ANDROID_INJECTION_LIBRARY_IN_PACKAGE */
0356 
0357         /* At this point, injectionLibraryPath is specified if a dynamic
0358         *  injection library was specified by a tool. */
0359         if (injectionLibraryPath)
0360         {
0361             /* Load the injection library */
0362             injectionLibraryHandle = NVTX_DLLOPEN(injectionLibraryPath);
0363             if (!injectionLibraryHandle)
0364             {
0365                 NVTX_ERR("Failed to load injection library\n");
0366                 return NVTX_ERR_INIT_LOAD_LIBRARY;
0367             }
0368             else
0369             {
0370                 /* Attempt to get the injection library's entry-point */
0371                 init_fnptr = NVTX_REINTERPRET_CAST(NvtxInitializeInjectionNvtxFunc_t, NVTX_DLLFUNC(injectionLibraryHandle, initFuncName));
0372                 if (!init_fnptr)
0373                 {
0374                     NVTX_DLLCLOSE(injectionLibraryHandle);
0375                     NVTX_ERR("Failed to get address of function InitializeInjectionNvtx2 from injection library\n");
0376                     return NVTX_ERR_INIT_MISSING_LIBRARY_ENTRY_POINT;
0377                 }
0378             }
0379         }
0380     }
0381 #endif /* NVTX_SUPPORT_DYNAMIC_INJECTION_LIBRARY */
0382 
0383 #if NVTX_SUPPORT_ALREADY_INJECTED_LIBRARY
0384     if (!init_fnptr)
0385     {
0386         /* Use POSIX global symbol chain to query for init function from any module */
0387         init_fnptr = NVTX_REINTERPRET_CAST(NvtxInitializeInjectionNvtxFunc_t, NVTX_DLLFUNC(NVTX_DLLDEFAULT, initFuncPreinjectName));
0388     }
0389 #endif
0390 
0391 #if NVTX_SUPPORT_STATIC_INJECTION_LIBRARY
0392     if (!init_fnptr)
0393     {
0394         /* Check weakly-defined function pointer.  A statically-linked injection can define this
0395         *  as a normal symbol and set it to the address of the NVTX init function -- this will
0396         *  provide a non-null value here.  If there is no other definition of this symbol, it
0397         *  will be null here. */
0398         if (InitializeInjectionNvtx2_fnptr)
0399         {
0400             init_fnptr = InitializeInjectionNvtx2_fnptr;
0401         }
0402     }
0403 #endif
0404 
0405     /* At this point, if init_fnptr is not set, then no tool has specified
0406     *  an NVTX injection library -- return non-success result so all NVTX
0407     *  API functions will be set to no-ops. */
0408     if (!init_fnptr)
0409     {
0410         return NVTX_ERR_NO_INJECTION_LIBRARY_AVAILABLE;
0411     }
0412 
0413     /* Invoke injection library's initialization function.  If it returns
0414     *  0 (failure) and a dynamic injection was loaded, unload it. */
0415     entryPointStatus = init_fnptr(NVTX_VERSIONED_IDENTIFIER(nvtxGetExportTable));
0416     if (entryPointStatus == 0)
0417     {
0418         NVTX_ERR("Failed to initialize injection library -- initialization function returned 0\n");
0419         if (injectionLibraryHandle)
0420         {
0421             NVTX_DLLCLOSE(injectionLibraryHandle);
0422         }
0423         return NVTX_ERR_INIT_FAILED_LIBRARY_ENTRY_POINT;
0424     }
0425 
0426     return NVTX_SUCCESS;
0427 }
0428 
0429 NVTX_LINKONCE_DEFINE_FUNCTION void NVTX_VERSIONED_IDENTIFIER(nvtxInitOnce)(void)
0430 {
0431     unsigned int old;
0432     if (NVTX_VERSIONED_IDENTIFIER(nvtxGlobals).initState == NVTX_INIT_STATE_COMPLETE)
0433     {
0434         return;
0435     }
0436 
0437     NVTX_ATOMIC_CAS_32(
0438         old,
0439         &NVTX_VERSIONED_IDENTIFIER(nvtxGlobals).initState,
0440         NVTX_INIT_STATE_STARTED,
0441         NVTX_INIT_STATE_FRESH);
0442     if (old == NVTX_INIT_STATE_FRESH)
0443     {
0444         int result;
0445         int forceAllToNoops;
0446 
0447         /* Load & initialize injection library -- it will assign the function pointers */
0448         result = NVTX_VERSIONED_IDENTIFIER(nvtxInitializeInjectionLibrary)();
0449 
0450         /* Set all pointers not assigned by the injection to null */
0451         forceAllToNoops = result != NVTX_SUCCESS; /* Set all to null if injection init failed */
0452         NVTX_VERSIONED_IDENTIFIER(nvtxSetInitFunctionsToNoops)(forceAllToNoops);
0453 
0454         /* Signal that initialization has finished, so now the assigned function pointers will be used */
0455         NVTX_ATOMIC_WRITE_32(
0456             &NVTX_VERSIONED_IDENTIFIER(nvtxGlobals).initState,
0457             NVTX_INIT_STATE_COMPLETE);
0458     }
0459     else /* Spin-wait until initialization has finished */
0460     {
0461         NVTX_MEMBAR();
0462         while (NVTX_VERSIONED_IDENTIFIER(nvtxGlobals).initState != NVTX_INIT_STATE_COMPLETE)
0463         {
0464             NVTX_YIELD();
0465             NVTX_MEMBAR();
0466         }
0467     }
0468 }