Skip to content

Deduplicate minipal header helpers - #132113

Merged
mdh1418 merged 6 commits into
dotnet:mainfrom
mdh1418:deduplicate-minipal-header-helpers
Aug 13, 2026
Merged

Deduplicate minipal header helpers#132113
mdh1418 merged 6 commits into
dotnet:mainfrom
mdh1418:deduplicate-minipal-header-helpers

Conversation

@mdh1418

@mdh1418 mdh1418 commented Aug 11, 2026

Copy link
Copy Markdown
Member

Addresses #131991 (comment)

Deduplicate the helper functions currently defined with internal linkage in  src/native/minipal  headers.

The affected helpers remain defined as  inline  in their headers so callers can inline them, but paired  .c  files now provide one external fallback definition for cases where the compiler emits a call instead. In C, each paired source file does this by including the inline definition and then redeclaring the function with  extern.

C inline linkage

A plain C  inline  definition does not necessarily emit an externally linkable function. At higher optimization levels, the compiler may substitute the header implementation directly at the call site, but at lower optimization levels, or whenever it chooses not to inline, the generated code may call an external symbol.

Each paired source file therefore follows this pattern:

#include "header.h"
 
extern return_type function(arguments);

The header supplies the function body, and the extern redeclaration causes that translation unit to provide the external definition required by non-inlined callers. This preserves access to the inline implementation while avoiding a private static  copy in every translation unit.

Out-of-line helpers

Based on review feedback, the following helpers are not sufficiently performance-sensitive to justify retaining their implementations in headers:

  •  minipal_getexepath 
  •  minipal_get_current_thread_id_no_cache 
  •  minipal_set_thread_name 

Their implementations now live in  getexepath.c  and  thread.c , and their headers contain declarations only.

 minipal_get_current_thread_id  remains inline because its common path is a TLS lookup and branch. It calls the out-of-line uncached implementation only when the TLS cache is empty.

Moving  minipal_set_thread_name  and the uncached thread-ID implementation into  thread.c  also keeps  _GNU_SOURCE  source-local. Arbitrary consumers of  thread.h  no longer compile code requiring GNU-only declarations.

Executable-path configuration

The executable-path implementation uses  getauxval(AT_EXECFN)  as a Linux fallback when  /proc/self/exe  cannot be resolved. Availability was previously determined by component-specific generated configuration headers, which were not available to minipal’s source file.

Minipal now performs its own  getauxval  capability check and exposes the result through  minipalconfig.h . Because  minipal_getexepath  has one out-of-line implementation, all callers now use the same capability-tested behavior regardless of optimization level or consumer configuration.

CPUID linker symbol names

The CPUID fallback helpers retain their source-level names,  __cpuid  and __cpuidex , to match the corresponding compiler intrinsics. Those names were harmless while the functions were  static , because each definition had translation-unit-local linkage.

Providing external fallback definitions under those names would export reserved double-underscore symbols and could collide with compiler headers or compatibility shims. Assembler-name labels are therefore used to assign minipal-owned linker names:

inline void __cpuid(...) __asm("minipal_cpuid");
inline void __cpuidex(...) __asm("minipal_cpuidex");

This preserves the existing source-level API while emitting the external symbols as  minipal_cpuid  and  minipal_cpuidex . These labels are separate from the inline assembly inside the function bodies that executes the CPUID instruction.

Validation

  • Built  clr+libs+host  for Linux x64 Debug.
  • Verified GCC and Clang C consumers link at  -O0  using the external definitions.
  • Verified optimized consumers can use the inline definitions.
  • Verified C++ consumers use compatible C-linkage symbols.
  • Verified the minipal archive provides the expected external helper symbols.
  • Verified the shipped archives expose  minipal_cpuid  and  minipal_cpuidex  rather than strong  __cpuid  and  __cpuidex  symbols.
  • Verified no  _SOURCE  or  _INLINE  implementation-control macros remain.

@mdh1418
mdh1418 requested review from jkotas and a lite review from Copilot August 11, 2026 04:14
@github-actions github-actions Bot added the area-PAL-coreclr only for closed issues label Aug 11, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR deduplicates several minipal helper implementations by moving them out of headers into single .c translation units, reducing per-TU duplication (including TLS) and improving call-stack visibility for these helpers.

Changes:

  • Move thread, getexepath, and entrypoints helper implementations from headers to new .c files with exported prototypes.
  • Add minipal sources (*.c) to the minipal build and adjust System.IO.Compression.Native to link against minipal.
  • Introduce “SOURCE” macros for selective in-header vs out-of-line definitions (notably ospagesize.h and cpuid.h).

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/native/minipal/thread.h Replaces header inlines with prototypes + shared TLS declaration.
src/native/minipal/thread.c New implementation file for thread ID helpers and thread naming.
src/native/minipal/ospagesize.h Adds MINIPAL_OSPAGESIZE_* inline control macro for constant page-size platforms.
src/native/minipal/ospagesize.c Refactors to include header first and conditionally compile POSIX implementation.
src/native/minipal/getexepath.h Replaces header inline with prototype for external implementation.
src/native/minipal/getexepath.c New implementation file for executable path resolution across platforms.
src/native/minipal/entrypoints.h Replaces header inline resolver with exported prototype.
src/native/minipal/entrypoints.c New implementation file for minipal_resolve_dllimport.
src/native/minipal/cpuid.h Adds MINIPAL_CPUID_* inline control macro.
src/native/minipal/cpuid.c New compilation unit to host cpuid fallback implementations.
src/native/minipal/CMakeLists.txt Adds new .c sources to minipal build outputs.
src/native/libs/System.IO.Compression.Native/CMakeLists.txt Links System.IO.Compression.Native against minipal to satisfy new out-of-line symbols.

Comment thread src/native/minipal/ospagesize.h Outdated
Comment thread src/native/minipal/cpuid.h Outdated
Comment thread src/native/minipal/cpuid.h Outdated
Comment thread src/native/minipal/getexepath.h Outdated
Comment thread src/native/minipal/getexepath.h Outdated
mdh1418 and others added 4 commits August 12, 2026 19:40
Link the shared library against minipal so externally defined helpers are resolved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep helper implementations inline in headers while providing one external definition for callers when the compiler does not inline them. Move the shared thread ID TLS cache to thread.c.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep minipal_getexepath inline for callers while providing one external fallback definition when the compiler does not inline it.

Use a target-platform condition for the Linux auxv fallback because HAVE_GETAUXVAL is configured separately by each consumer. This ensures the inline and external definitions compile the same logic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep small platform helpers inline for callers while providing one external fallback definition.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 13, 2026 01:53
@mdh1418
mdh1418 force-pushed the deduplicate-minipal-header-helpers branch from 4bc3b14 to 670f632 Compare August 13, 2026 01:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Suppressed comments (4)

src/native/minipal/thread.h:92

  • minipal_get_current_thread_id is used from multiple C source files (e.g., System.Native). With external-linkage inline in a header, builds can end up with multiple global definitions (or require a single out-of-line definition) depending on compiler/flags. Restoring static inline here avoids potential link-time failures for non-inlined builds.
inline size_t minipal_get_current_thread_id(void)

src/native/minipal/thread.h:114

  • Same linkage concern as minipal_get_current_thread_id: minipal_set_thread_name is called from other C translation units. If it stays header-defined, it should keep internal linkage (static inline) to avoid relying on C inline/linkage corner cases.
inline int minipal_set_thread_name(pthread_t thread, const char* name)

src/native/minipal/getexepath.h:188

  • This block now calls getauxval based only on AT_EXECFN, but getauxval availability is already feature-tested via HAVE_GETAUXVAL in multiple native builds. Dropping the guard can cause compile/link failures on platforms/toolchains where AT_EXECFN is defined but getauxval is unavailable. Guard the fallback on HAVE_GETAUXVAL as well.
#if defined(AT_EXECFN)
    // fallback to AT_EXECFN, which does not work properly in rare cases
    // when .NET process is set as interpreter (shebang).
    const char* exePath = (const char *)(getauxval(AT_EXECFN));
    if (exePath)

src/native/minipal/thread.c:17

  • These extern declarations don’t provide a definition for the header-defined inline functions and are redundant with the declarations/definitions already visible via #include "thread.h". They also become actively misleading if the header switches back to static inline (linkage mismatch). Consider removing them.
extern size_t minipal_get_current_thread_id_no_cache(void);
extern size_t minipal_get_current_thread_id(void);
extern int minipal_set_thread_name(pthread_t thread, const char* name);

Comment thread src/native/minipal/thread.h Outdated
Comment thread src/native/minipal/thread.c
Comment thread src/native/minipal/getexepath.h Outdated
Move executable path resolution, uncached thread ID lookup, and thread naming into their source files. Keep only the cached thread ID fast path inline, and configure getauxval availability directly for minipal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 13, 2026 16:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comment thread src/native/minipal/cpuid.c
@jkotas

jkotas commented Aug 13, 2026

Copy link
Copy Markdown
Member

Build breaks

Use the MSVC-supported _strdup spelling in the Windows executable-path implementation to avoid C4996 when getexepath.c is compiled as part of minipal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 13, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

@mdh1418

mdh1418 commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

/ba-g "Build failures are #117486, #131925, and #132030"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-PAL-coreclr only for closed issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants