Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
47248f6
Replace CoreCLR SList with NativeAOT-style design
max-charlamb Apr 15, 2026
01dfe53
Remove HISTORY comment from slist.h
Copilot Apr 15, 2026
b31145d
Address review feedback
max-charlamb Apr 15, 2026
bb6dec2
Add SList linkage comments to all m_pNext fields
max-charlamb Apr 16, 2026
7200f54
Unify SList: NativeAOT now redirects to shared inc/slist.h
max-charlamb Apr 16, 2026
eb14292
Address PR review feedback
max-charlamb Apr 18, 2026
d1cf683
Address review feedback: init m_pNext, static_asserts, cleanup
max-charlamb Apr 19, 2026
ca33b85
Remove redundant typedefs, use SListTail<> directly
max-charlamb Apr 20, 2026
5de94d5
Initialize Thread::m_pNext, add braces to RemoveFirst tail update
max-charlamb Apr 20, 2026
5737775
Remove FEATURE_NATIVEAOT guard from SListElem
max-charlamb Apr 20, 2026
6f3cb4c
Remove unnecessary comment from NativeAOT slist.h forwarder
max-charlamb Apr 20, 2026
678b61f
Remove rh::std helpers from NativeAOT slist.inl
max-charlamb Apr 20, 2026
d3db95c
Replace debug count loop with assert on RemoveFirst result
max-charlamb Apr 20, 2026
e08a0d1
Rename begin()/end() to Begin()/End() for runtime conventions
max-charlamb Apr 20, 2026
3e6e068
Update src/coreclr/inc/slist.h
max-charlamb Apr 20, 2026
e720a0f
Update src/coreclr/inc/slist.h
max-charlamb Apr 20, 2026
d6e78f1
Make slist.inl self-contained with platform includes
max-charlamb Apr 20, 2026
29787bb
Guard InsertHeadInterlocked definition with DACCESS_COMPILE
max-charlamb Apr 20, 2026
9d01a16
Fix stale SLink documentation
max-charlamb Apr 20, 2026
77daca2
Remove interlocked SList support, delete slist.inl files
max-charlamb Apr 21, 2026
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
6 changes: 3 additions & 3 deletions docs/design/datacontracts/SyncBlock.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Data descriptors used:
| `SyncTableEntry` | `SyncBlock` | Pointer to the sync block for a sync table entry |
| `SyncTableEntry` | `Object` | Pointer to the object associated with a sync table entry |
| `SyncBlockCache` | `FreeSyncTableIndex` | One past the highest sync table entry index allocated |
| `SyncBlockCache` | `CleanupBlockList` | Head of the `SLink` cleanup list (points into `SyncBlock.m_Link`) |
| `SyncBlockCache` | `CleanupBlockList` | Head of the cleanup list (points to the first `SyncBlock` in the chain) |
| `SyncBlock` | `Lock` | Optional pointer to a `System.Threading.Lock` object payload |
| `SyncBlock` | `ThinLock` | Thin-lock state bits |
| `SyncBlock` | `LinkNext` | Head pointer for cleanup list link |
Expand Down Expand Up @@ -149,7 +149,7 @@ TargetPointer GetSyncBlockFromCleanupList()
TargetPointer cleanupBlockList = target.ReadPointer(syncBlockCache + /* SyncBlockCache::CleanupBlockList offset */);
if (cleanupBlockList == TargetPointer.Null)
return TargetPointer.Null;
return cleanupBlockList - /* SyncBlock::LinkNext offset */;
return cleanupBlockList;
}

// Returns the next sync block in the cleanup list after syncBlock, or TargetPointer.Null if there is none.
Expand All @@ -158,7 +158,7 @@ TargetPointer GetNextSyncBlock(TargetPointer syncBlock)
TargetPointer linkNext = target.ReadPointer(syncBlock + /* SyncBlock::LinkNext offset */);
if (linkNext == TargetPointer.Null)
return TargetPointer.Null;
return linkNext - /* SyncBlock::LinkNext offset */;
return linkNext;
}

// Gets the built-in COM interop data directly from a sync block.
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3822,9 +3822,9 @@ ClrDataAccess::GetSyncBlockData(unsigned int SBNumber, struct DacpSyncBlockData
// TODO: Microsoft, implement the wait list
pSyncBlockData->AdditionalThreadCount = 0;

if (pBlock->m_Link.m_pNext != NULL)
if (pBlock->m_pNext != NULL)
{
PTR_SLink pLink = pBlock->m_Link.m_pNext;
PTR_SyncBlock pLink = pBlock->m_pNext;
do
{
pSyncBlockData->AdditionalThreadCount++;
Expand Down Expand Up @@ -3855,7 +3855,7 @@ ClrDataAccess::GetSyncBlockCleanupData(CLRDATA_ADDRESS syncBlock, struct DacpSyn
if (syncBlock == (CLRDATA_ADDRESS)NULL && SyncBlockCache::s_pSyncBlockCache->m_pCleanupBlockList)
{
pBlock = (SyncBlock *) PTR_SyncBlock(
PTR_HOST_TO_TADDR(SyncBlockCache::s_pSyncBlockCache->m_pCleanupBlockList) - offsetof(SyncBlock, m_Link));
PTR_HOST_TO_TADDR(SyncBlockCache::s_pSyncBlockCache->m_pCleanupBlockList));
}
else
{
Expand All @@ -3865,10 +3865,10 @@ ClrDataAccess::GetSyncBlockCleanupData(CLRDATA_ADDRESS syncBlock, struct DacpSyn
if (pBlock)
{
syncBlockCData->SyncBlockPointer = HOST_CDADDR(pBlock);
if (pBlock->m_Link.m_pNext)
if (pBlock->m_pNext)
{
syncBlockCData->nextSyncBlock = (CLRDATA_ADDRESS)
(PTR_HOST_TO_TADDR(pBlock->m_Link.m_pNext) - offsetof(SyncBlock, m_Link));
PTR_HOST_TO_TADDR(pBlock->m_pNext);
}

#ifdef FEATURE_COMINTEROP
Expand Down
18 changes: 4 additions & 14 deletions src/coreclr/inc/daccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,10 @@
// instance pointers should be held across a Flush().
//
// Accessing into an object can lead to some unusual behavior. For
// example, the SList class relies on objects to contain an SLink
// instance that it uses for list maintenance. This SLink can be
// embedded anywhere in the larger object. The SList access is always
// purely to an SLink, so when using the access layer it will only
// retrieve an SLink's worth of data. The SList template will then
// do some address arithmetic to determine the start of the real
// object and cast the resulting pointer to the final object type.
// When using the access layer this results in a new ?PTR being
// created and used, so a new instance will result. The internal
// SLink instance will have no relation to the new object instance
// even though in target address terms one is embedded in the other.
// The assumption of data stability means that this won't cause
// a problem, but care must be taken with the address arithmetic,
// as laid out in rules #2 and #3.
// example, the SList class uses an intrusive m_pNext pointer
// embedded in each object for list maintenance. The SList access is
// always to the object itself, so when using the access layer it will
// retrieve the full object's data.
//
// 4. Global address references cannot be used. Any reference to a
// global piece of code or data, such as a function address, global
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/inc/profilepriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,11 @@ struct StoredProfilerNode
{
CLSID guid;
SString path;
SLink m_Link;
// Next pointer for SList linkage.
DPTR(StoredProfilerNode) m_pNext;
};

typedef SList<StoredProfilerNode, true> STOREDPROFILERLIST;
typedef SList<StoredProfilerNode> STOREDPROFILERLIST;
// ---------------------------------------------------------------------------------------
// Global struct that lets the EE see the load status of the profiler, and provides a
// pointer (pProfInterface) through which profiler calls can be made
Expand Down
Loading
Loading