Skip to content

SunOS process and thread support #105403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions eng/Subsets.props
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
<_NativeAotSupportedArch Condition="'$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm' or '$(TargetArchitecture)' == 'loongarch64' or '$(TargetArchitecture)' == 'riscv64' or ('$(TargetOS)' == 'windows' and '$(TargetArchitecture)' == 'x86')">true</_NativeAotSupportedArch>
<NativeAotSupported Condition="'$(_NativeAotSupportedOS)' == 'true' and '$(_NativeAotSupportedArch)' == 'true'">true</NativeAotSupported>

<!-- TODO: workaround for https://github.com/dotnet/runtime/issues/116929 -->
<_Crossgen2Supported Condition="'$(TargetOS)' != 'illumos' and '$(TargetOS)' != 'solaris'">true</_Crossgen2Supported>

<!-- Determine if we support running the .NET SDK on the target platform -->
<_SdkToolsSupportedOS Condition="'$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true'">true</_SdkToolsSupportedOS>
<_SdkToolsSupportedArch Condition="'$(TargetArchitecture)' != 'armel'">true</_SdkToolsSupportedArch>
Expand Down Expand Up @@ -440,7 +443,7 @@
<ProjectToBuild Include="$(CoreClrProjectRoot).nuget\Microsoft.CrossOsDiag.Private.CoreCLR\Microsoft.CrossOsDiag.Private.CoreCLR.proj" Category="clr" />
</ItemGroup>

<ItemGroup Condition="$(_subset.Contains('+clr.tools+'))">
<ItemGroup Condition="$(_subset.Contains('+clr.tools+')) and '$(_Crossgen2Supported)' == 'true'">
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\runincontext\runincontext.csproj;
$(CoreClrProjectRoot)tools\tieringtest\tieringtest.csproj;
$(CoreClrProjectRoot)tools\r2rdump\R2RDump.csproj;
Expand Down Expand Up @@ -676,7 +679,7 @@
<SharedFrameworkProjectToBuild Include="$(InstallerProjectRoot)pkg\sfx\Microsoft.NETCore.App\Microsoft.NETCore.App.Ref.sfxproj" />
</ItemGroup>
<ItemGroup>
<SharedFrameworkProjectToBuild Condition="'$(RuntimeFlavor)' != 'Mono' and ('$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true')" Include="$(InstallerProjectRoot)pkg\sfx\Microsoft.NETCore.App\Microsoft.NETCore.App.Crossgen2.sfxproj" />
<SharedFrameworkProjectToBuild Condition="'$(RuntimeFlavor)' != 'Mono' and ('$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true') and '$(_Crossgen2Supported)' == 'true'" Include="$(InstallerProjectRoot)pkg\sfx\Microsoft.NETCore.App\Microsoft.NETCore.App.Crossgen2.sfxproj" />
<SharedFrameworkProjectToBuild Condition="'$(RuntimeFlavor)' == '$(PrimaryRuntimeFlavor)' and '$(TargetsMobile)' != 'true'" Include="$(InstallerProjectRoot)pkg\sfx\installers\dotnet-host.proj" />
<SharedFrameworkProjectToBuild Condition="'$(RuntimeFlavor)' == '$(PrimaryRuntimeFlavor)' and '$(TargetsMobile)' != 'true'" Include="$(InstallerProjectRoot)pkg\sfx\installers\dotnet-hostfxr.proj" />
<SharedFrameworkProjectToBuild Condition="'$(RuntimeFlavor)' == '$(PrimaryRuntimeFlavor)' and '$(TargetsMobile)' != 'true'" Include="$(InstallerProjectRoot)pkg\sfx\installers\dotnet-runtime-deps\*.proj" />
Expand All @@ -691,7 +694,7 @@
When we're building in the VMR, we need to provide a crossgen2 that runs on the host machine for downstream repos to use to R2R their code.
In non-VMR builds, downstream repos can use the crossgen2 built for the target host SDK from another build leg, but in the VMR we need to provide one to use.
-->
<ProjectToBuild Condition="'$(RuntimeFlavor)' != 'Mono' and '$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true' and '$(BuildHostTools)' == 'true'" Include="$(InstallerProjectRoot)pkg\sfx\Microsoft.NETCore.App\Microsoft.NETCore.App.Crossgen2.Host.sfxproj" Category="packs" />
<ProjectToBuild Condition="'$(RuntimeFlavor)' != 'Mono' and '$(TargetsMobile)' != 'true' and '$(TargetsLinuxBionic)' != 'true' and '$(BuildHostTools)' == 'true' and '$(_Crossgen2Supported)' == 'true'" Include="$(InstallerProjectRoot)pkg\sfx\Microsoft.NETCore.App\Microsoft.NETCore.App.Crossgen2.Host.sfxproj" Category="packs" />
</ItemGroup>
<ItemGroup>
<SharedFrameworkProjectToBuild Condition="'$(_BuildHostPack)' == 'true'" Include="$(InstallerProjectRoot)pkg\archives\dotnet-nethost.proj" />
Expand Down
2 changes: 1 addition & 1 deletion eng/targetingpacks.targets
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
LatestRuntimeFrameworkVersion="$(ProductVersion)"
RuntimeFrameworkName="$(LocalFrameworkOverrideName)"
RuntimePackNamePatterns="$(LocalFrameworkOverrideName).Runtime.**RID**"
RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86;freebsd-x64;freebsd-arm64;linux-ppc64le;linux-riscv64;linux-musl-riscv64;linux-loongarch64;linux-musl-loongarch64"
RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86;freebsd-x64;freebsd-arm64;illumos-x64;solaris-x64;linux-ppc64le;linux-riscv64;linux-musl-riscv64;linux-loongarch64;linux-musl-loongarch64"
TargetFramework="$(NetCoreAppCurrent)"
TargetingPackName="$(LocalFrameworkOverrideName).Ref"
TargetingPackVersion="$(ProductVersion)"
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ CDAC_GLOBAL_STRING(RID, RID_STRING)
CDAC_GLOBAL(GCInfoVersion, uint32, GCINFO_VERSION)

CDAC_GLOBAL_POINTER(AppDomain, &AppDomain::m_pTheAppDomain)
CDAC_GLOBAL_POINTER(SystemDomain, cdac_data<SystemDomain>::SystemDomain)
CDAC_GLOBAL_POINTER(SystemDomain, cdac_data<SystemDomain>::SystemDomainPtr)
CDAC_GLOBAL_POINTER(ThreadStore, &ThreadStore::s_pThreadStore)
CDAC_GLOBAL_POINTER(FinalizerThread, &::g_pFinalizerThread)
CDAC_GLOBAL_POINTER(GCThread, &::g_pSuspensionThread)
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/pal/src/thread/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1330,10 +1330,9 @@ CorUnix::GetThreadTimesInternal(
CPalThread *pThread;
CPalThread *pTargetThread;
IPalObject *pobjThread = NULL;
clockid_t cid;
#ifdef __sun
int fd;
#else // __sun
clockid_t cid;
#endif // __sun

pThread = InternalGetCurrentThread();
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/runtime/amd64/AllocFast.S
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ LEAF_ENTRY RhpNewPtrArrayFast, _TEXT

// Delegate overflow handling to the generic helper conservatively

cmp rsi, (0x40000000 / 8) // sizeof(void*)
cmp rsi, 0x8000000 // (0x40000000 / sizeof(void*))
jae C_FUNC(RhpNewArrayFast)

// In this case we know the element size is sizeof(void *), or 8 for x64
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/tools/superpmi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
include(configure.cmake)
include_directories(${CMAKE_CURRENT_BINARY_DIR})

add_subdirectory(superpmi)
add_subdirectory(mcs)
add_subdirectory(superpmi-shim-collector)
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/tools/superpmi/config.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#ifndef __CONFIG_H__
#define __CONFIG_H__

#cmakedefine01 HAVE_DIRENT_D_TYPE

#endif // __CONFIG_H__
7 changes: 7 additions & 0 deletions src/coreclr/tools/superpmi/configure.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include(CheckStructHasMember)

check_struct_has_member ("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE)

configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)
56 changes: 49 additions & 7 deletions src/coreclr/tools/superpmi/mcs/verbmerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@
#include "simpletimer.h"
#include "logging.h"
#include "spmiutil.h"
#include "config.h"
#include <stdio.h>
#ifdef TARGET_UNIX
#include <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
#endif
#ifndef DT_UNKNOWN
#define DT_UNKNOWN 0
#define DT_DIR 4
#define DT_REG 8
#define DT_LNK 10
#endif // !DT_UNKNOWN
#endif // TARGET_UNIX

#include <utility>

Expand Down Expand Up @@ -187,9 +194,9 @@ bool verbMerge::DirectoryFilterDirectories(FilterArgType* findData)
#else // TARGET_WINDOWS
if (findData->d_type == DT_DIR)
{
if (strcmp(findData->d_name, ".") == 0)
if (u16_strcmp(findData->cFileName, W(".")) == 0)
return false;
if (strcmp(findData->d_name, "..") == 0)
if (u16_strcmp(findData->cFileName, W("..")) == 0)
return false;

return true;
Expand Down Expand Up @@ -281,12 +288,47 @@ int verbMerge::FilterDirectory(LPCWSTR dir,
dirent *pEntry = readdir(pDir);
while (pEntry != nullptr)
{
if ((fnmatch(searchPatternUtf8.c_str(), pEntry->d_name, 0) == 0) && filter(pEntry))
int dirEntryType;

#if HAVE_DIRENT_D_TYPE
dirEntryType = pEntry->d_type;
#else
struct stat sb;

if (fstatat(dirfd(pDir), pEntry->d_name, &sb, 0) == -1)
{
continue;
}

if (S_ISDIR(sb.st_mode)) {
dirEntryType = DT_DIR;
} else if (S_ISREG(sb.st_mode)) {
dirEntryType = DT_REG;
} else if (S_ISLNK(sb.st_mode)) {
dirEntryType = DT_LNK;
} else {
dirEntryType = DT_UNKNOWN;
}
#endif
if (dirEntryType == DT_UNKNOWN)
{
FindData findData(pEntry->d_type, ConvertMultiByteToWideChar(pEntry->d_name));
first = new findDataList(&findData, first);
++elemCount;
continue;
}

if (fnmatch(searchPatternUtf8.c_str(), pEntry->d_name, 0) != 0)
{
continue;
}

FindData findData(dirEntryType, ConvertMultiByteToWideChar(pEntry->d_name));
if (!filter(&findData))
{
continue;
}

first = new findDataList(&findData, first);
++elemCount;

errno = 0;
pEntry = readdir(pDir);
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/superpmi/mcs/verbmerge.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class verbMerge
#ifdef TARGET_WINDOWS
typedef _WIN32_FIND_DATAW FilterArgType;
#else
typedef struct dirent FilterArgType;
typedef struct FindData FilterArgType;
#endif

typedef bool (*DirectoryFilterFunction_t)(FilterArgType*);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/appdomain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1931,7 +1931,7 @@ inline static BOOL IsUnderDomainLock() { LIMITED_METHOD_CONTRACT; return m_Syste
template<>
struct cdac_data<SystemDomain>
{
static constexpr PTR_SystemDomain* SystemDomain = &SystemDomain::m_pSystemDomain;
static constexpr PTR_SystemDomain* SystemDomainPtr = &SystemDomain::m_pSystemDomain;
};
#endif // DACCESS_COMPILE

Expand Down
9 changes: 4 additions & 5 deletions src/installer/pkg/projects/netcoreappRIDs.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@
<OfficialBuildRID Include="osx-arm64">
<Platform>arm64</Platform>
</OfficialBuildRID>
<!-- Not currently built by CoreFX. -->
<!-- <OfficialBuildRID Include="netbsd-x64" /> -->
<!-- <OfficialBuildRID Include="illumos-x64" /> -->
<!-- <OfficialBuildRID Include="solaris-x64" /> -->
<!-- <OfficialBuildRID Include="haiku-x64" /> -->
<OfficialBuildRID Include="win-x86">
<Platform>x86</Platform>
</OfficialBuildRID>
Expand Down Expand Up @@ -51,6 +46,10 @@
in our runtime.json to enable others to provide them. -->
<UnofficialBuildRID Include="freebsd-x64" />
<UnofficialBuildRID Include="freebsd-arm64" />
<UnofficialBuildRID Include="illumos-x64" />
<UnofficialBuildRID Include="solaris-x64" />
<UnofficialBuildRID Include="netbsd-x64" />
<UnofficialBuildRID Include="haiku-x64" />
<UnofficialBuildRID Include="tizen.4.0.0-armel">
<Platform>armel</Platform>
</UnofficialBuildRID>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.InteropServices;

// C# equivalents for <sys/procfs.h> structures. See: struct lwpsinfo, struct psinfo.
// We read directly onto these from procfs, so the layouts and sizes of these structures
// must _exactly_ match those in <sys/procfs.h>

// analyzer incorrectly flags fixed buffer length const
// (https://github.com/dotnet/roslyn/issues/37593)
#pragma warning disable CA1823

internal static partial class Interop
{
internal static partial class @procfs
{
internal const string RootPath = "/proc/";
private const string psinfoFileName = "/psinfo";
private const string lwpDirName = "/lwp";
private const string lwpsinfoFileName = "/lwpsinfo";

// Constants from sys/procfs.h
private const int PRARGSZ = 80;
private const int PRCLSZ = 8;
private const int PRFNSZ = 16;

[StructLayout(LayoutKind.Sequential)]
internal struct @timestruc_t
{
public long tv_sec;
public long tv_nsec;
}

// lwp ps(1) information file. /proc/<pid>/lwp/<lwpid>/lwpsinfo
// Equivalent to sys/procfs.h struct lwpsinfo
// "unsafe" because it has fixed sized arrays.
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct @lwpsinfo
{
private int pr_flag; /* lwp flags (DEPRECATED; do not use) */
public uint pr_lwpid; /* lwp id */
private long pr_addr; /* internal address of lwp */
private long pr_wchan; /* wait addr for sleeping lwp */
public byte pr_stype; /* synchronization event type */
public byte pr_state; /* numeric lwp state */
public byte pr_sname; /* printable character for pr_state */
public byte pr_nice; /* nice for cpu usage */
private short pr_syscall; /* system call number (if in syscall) */
private byte pr_oldpri; /* pre-SVR4, low value is high priority */
private byte pr_cpu; /* pre-SVR4, cpu usage for scheduling */
public int pr_pri; /* priority, high value is high priority */
private ushort pr_pctcpu; /* fixed pt. % of recent cpu time */
private ushort pr_pad;
public timestruc_t pr_start; /* lwp start time, from the epoch */
public timestruc_t pr_time; /* usr+sys cpu time for this lwp */
private fixed byte pr_clname[PRCLSZ]; /* scheduling class name */
private fixed byte pr_name[PRFNSZ]; /* name of system lwp */
private int pr_onpro; /* processor which last ran this lwp */
private int pr_bindpro; /* processor to which lwp is bound */
private int pr_bindpset; /* processor set to which lwp is bound */
private int pr_lgrp; /* lwp home lgroup */
private fixed int pr_filler[4]; /* reserved for future use */
}
private const int PR_LWPSINFO_SIZE = 128; // for debug assertions

// process ps(1) information file. /proc/<pid>/psinfo
// Equivalent to sys/procfs.h struct psinfo
// "unsafe" because it has fixed sized arrays.
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct @psinfo
{
private int pr_flag; /* process flags (DEPRECATED; do not use) */
public int pr_nlwp; /* number of active lwps in the process */
public int pr_pid; /* unique process id */
public int pr_ppid; /* process id of parent */
public int pr_pgid; /* pid of process group leader */
public int pr_sid; /* session id */
public uint pr_uid; /* real user id */
public uint pr_euid; /* effective user id */
public uint pr_gid; /* real group id */
public uint pr_egid; /* effective group id */
private long pr_addr; /* address of process */
public ulong pr_size; /* size of process image in Kbytes */
public ulong pr_rssize; /* resident set size in Kbytes */
private ulong pr_pad1;
private ulong pr_ttydev; /* controlling tty device (or PRNODEV) */
private ushort pr_pctcpu; /* % of recent cpu time used by all lwps */
private ushort pr_pctmem; /* % of system memory used by process */
public timestruc_t pr_start; /* process start time, from the epoch */
public timestruc_t pr_time; /* usr+sys cpu time for this process */
public timestruc_t pr_ctime; /* usr+sys cpu time for reaped children */
public fixed byte pr_fname[PRFNSZ]; /* name of execed file */
public fixed byte pr_psargs[PRARGSZ]; /* initial characters of arg list */
public int pr_wstat; /* if zombie, the wait() status */
public int pr_argc; /* initial argument count */
private long pr_argv; /* address of initial argument vector */
private long pr_envp; /* address of initial environment vector */
private byte pr_dmodel; /* data model of the process */
private fixed byte pr_pad2[3];
public int pr_taskid; /* task id */
public int pr_projid; /* project id */
public int pr_nzomb; /* number of zombie lwps in the process */
public int pr_poolid; /* pool id */
public int pr_zoneid; /* zone id */
public int pr_contract; /* process contract */
private fixed int pr_filler[1]; /* reserved for future use */
public lwpsinfo pr_lwp; /* information for representative lwp */
// C# magic: Accessor method to get a Span for pr_psargs[]
// Does not affect the size or layout of this struct.
internal ReadOnlySpan<byte> PsArgsSpan =>
MemoryMarshal.CreateReadOnlySpan(ref pr_psargs[0], PRARGSZ);
}
private const int PR_PSINFO_SIZE = 416; // for debug assertions

// Ouput type for TryGetThreadInfoById()
internal struct ThreadInfo
{
internal uint Tid;
internal int Priority;
internal int NiceVal;
internal char Status;
internal Interop.Sys.TimeSpec StartTime;
internal Interop.Sys.TimeSpec CpuTotalTime; // user+sys
// add more fields when needed.
}

// Ouput type for TryGetProcessInfoById()
internal struct ProcessInfo
{
internal int Pid;
internal int ParentPid;
internal int SessionId;
internal int Priority;
internal int NiceVal;
internal nuint VirtualSize;
internal nuint ResidentSetSize;
internal Interop.Sys.TimeSpec StartTime;
internal Interop.Sys.TimeSpec CpuTotalTime; // user+sys
internal string? Args;
// add more fields when needed.
}

internal static string GetInfoFilePathForProcess(int pid) =>
$"{RootPath}{(uint)pid}{psinfoFileName}";

internal static string GetLwpDirForProcess(int pid) =>
$"{RootPath}{(uint)pid}{lwpDirName}";

internal static string GetInfoFilePathForThread(int pid, int tid) =>
$"{RootPath}{(uint)pid}{lwpDirName}/{(uint)tid}{lwpsinfoFileName}";

}
}
Loading
Loading