Skip to content

Windows support for Reconverse - #304

Open
ritvikrao wants to merge 15 commits into
mainfrom
windows-support
Open

ritvikrao wants to merge 15 commits into
mainfrom
windows-support

Conversation

@ritvikrao

Copy link
Copy Markdown
Collaborator

This PR allows Reconverse to run on Windows machines, with exactly 1 process but multithreading within the process. It's primarily needed to support NAMD on Windows.

ritvikrao and others added 10 commits October 23, 2026 15:06
boost-context chose the MASM fcontext sources only when Charm++ had set
CMK_COMPILER=msvc, and enabled the GAS assembler regardless, so a
standalone MSVC build could not assemble them. Select MASM whenever the
compiler is MSVC, enable ASM_MASM for it, and define BOOST_CONTEXT_EXPORT
empty, as Boost does for a static build.

Consumers linked with MSVC get an 8 MB main-thread stack (rank 0 runs on
it; Windows defaults to 1 MB) and /DEBUG, the Windows counterpart of the
-rdynamic Linux consumers get: it writes the PDB that lets stack traces
name the executable's own functions. /OPT:REF and /OPT:ICF are restored
outside Debug, since /DEBUG would otherwise turn them off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single-process build on Windows, with the 'none' communication backend
(LCI and LCW off). Non-Windows code paths are unchanged.

converse.h: CMI_MSVC marks the Microsoft compiler (not clang-cl), which
lacks __thread, __int128, the GCC atomic builtins and, in C, a usable
<stdatomic.h>. Under it the Cpv storage class is __declspec(thread), the
atomics are _Interlocked* intrinsics, and C's CsdNodeQueueLen is a
volatile long of the same layout. CmiInt16 is declared only where the
compiler has a 128-bit integer (Charm++ already gates its uses on
CMK_HAS_INT16). On Windows CmiNodeLock is an SRW lock, named by its struct
tag so that the header need not include <windows.h>.

convcore.cpp: PE threads come from _beginthreadex with an 8 MB stack
reservation (the Windows default is 1 MB); locks are SRW locks; the wall
clock is GetSystemTimePreciseAsFileTime; the cache-line check uses
GetLogicalProcessorInformation.

sockRoutines: poll is WSAPoll, getifaddrs is skipped, Winsock is started
before gethostname, and the public header keeps <windows.h> lean and free
of min/max macros. Elsewhere: unused POSIX includes removed,
_aligned_malloc for posix_memalign, __umulh for the 128-bit multiply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CmiPrintStackTrace walks the stack with CaptureStackBackTrace and names
frames through DbgHelp: function, and file:line when there is a PDB,
otherwise module+offset. Fatal faults are structured exceptions on
Windows, so an unhandled-exception filter takes the place of the signal
handler; it reports the fault with the POSIX signal it corresponds to,
traces from the faulting frame, and exits with the exception code.

The Windows Error Reporting and abort() dialogs are suppressed, so that
a crashed run exits rather than waiting for someone to dismiss a window.
+truecrash leaves all of this off, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Windows job is a single process, so the pool never has a peer. The
Windows backend does what the POSIX one does for a process alone on its
host -- maps only its own segment and marks the pool ready -- using
ordinary memory, so that Charm++'s CmiMakeIpcManager still works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop unused <pthread.h> includes, spell noinline as CMI_NOINLINE, and
replace usleep with std::this_thread::sleep_for. The tests that relied
on sh to swallow a crash's exit status use run_and_capture.cmake on
Windows instead, and abort_peer uses WILL_FAIL there, since abort() exits
with a status rather than a signal on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Charm++ on Windows compiles with MSVC from Cygwin through its unix2nt_cc
wrapper, which hands .asm sources to ml64 itself. Use ASM_MASM only for
a native MSVC build and the generic ASM language (the wrapper) otherwise,
as classic Charm++ did. FindThreads, run from Cygwin, looks for pthreads
and fails; Windows threads need no library, so do not require it there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Charm++ (CkAbort is CmiAbort) ends non-void functions with it, e.g. the
default LevelLogic methods in TreeLB.h. GCC only warns about the missing
return; MSVC rejects it (C4716). CMK_NORETURN moves up to be defined
before the declaration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
converse.h declares CmiSetCPUAffinity, CmiSetCPUAffinityLogical and
CmiPrintCPUAffinity unconditionally, but only the hwloc build defined
them, so a program calling one (CkLoop's simpleLoopBench does) failed
to link without hwloc, on any platform. Return -1, unsupported, as
classic Converse's unsupported platforms did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CkLoop.h declares the Cpv with CpvCExtern, but convcore.cpp defined it
with C++ linkage. GCC does not decorate variable names, so the two
matched anyway; MSVC does, and CkLoop programs failed to link. Declare
it CpvCExtern before the definition, as interopExitFlag already is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CmiMemoryUsage was a macro for 0 everywhere. On Windows, NAMD's memory
reports and Charm++'s load balancer printouts have nothing else to go
on (no /proc), so implement it there with GetProcessMemoryInfo,
returning committed private bytes as classic Converse did. Other
platforms keep the macro.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ritvikrao
ritvikrao requested review from ericjbohm and lvkale October 23, 2026 21:40
@github-actions

Copy link
Copy Markdown

Charm++ on this reconverse (advisory): Charm++ (recharm) builds and its reconverse test tier passes against this tree.

A windows-latest job: a Debug build with MSVC (cl, link and ml64 from
ilammy/msvc-dev-cmd) and no communication backend, then every test that
runs in a single process.

Tests that need the multi-process launcher (mpirun) are skipped by rule
rather than by name: those whose command CTest could not resolve, or
that pass the launcher to a script, are listed in the log and excluded,
so new tests need no edit here. The CCS tests are also left out: their
server listens on a TCP port, which on a Windows desktop raises a
firewall prompt only an administrator can answer.

Locally (VS 2022 17.12, MSVC 19.42): 67 tests pass, 54 skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lvkale

lvkale commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

If you are only supporting 1 process, why are there IPC changes here?

Reconverse on Windows runs a single process, so the shared-memory pool
never has a peer. cmishm-win32.cpp existed only so cmishmem.cpp had a
backend to compile against: it built an 8 MB pool that no message could
use, and its CmiNumNodes() == 1 check could not fail.

Only two paths reach the pool. +ipc already stops in CmiIpcStartup when
the job has one process, which on Windows it always does. The other is
Charm++ built with --enable-shmem calling CmiMakeIpcManager, which now
aborts on Windows with a message saying so. The stub file is gone,
cmishm.cpp is included only off Windows, and ipcInitShm_ is not
registered there.

Off Windows the code is unchanged (unifdef -U_WIN32 of the old and new
cmishmem.cpp differ only by a comment).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ritvikrao

Copy link
Copy Markdown
Collaborator Author

If you are only supporting 1 process, why are there IPC changes here?

i had added it to get it to compile, but it was never actually exercising an ipc path. i've swapped it with a better implementation

@lvkale lvkale 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.

Read-only review of the whole diff (no Windows machine here, so approval should come from someone who can run it). I found nothing that should block it.

What I checked: CMI_MSVC is true only for Microsoft's own compiler, so clang-cl keeps the GCC paths. Each MSVC substitute has the semantics of the original: _InterlockedExchangeAdd returns the previous value like __atomic_fetch_add; CmiTryLock inverts TryAcquireSRWLockExclusive to give pthread's 0-on-success; the C and C++ spellings of CsdNodeQueueLen_t have the same size, offset and alignment; __umulh matches the 128-bit multiply. CmiAbort is declared noreturn and its definition does end in abort(). PE threads get an 8 MB reservation and the main thread's stack is raised to match through the linker option. The crash handler turns off the abort and Windows Error Reporting dialogs, which is what a headless runner needs. The last commit answers the earlier IPC question: no shared-memory backend is compiled on Windows and CmiMakeIpcManager aborts with a clear message. The test changes (CMake script in place of sh -c, CMI_NOINLINE) and the CI job's exclusions are reasonable.

Two follow-up notes, neither blocking, on the lines they refer to.

Comment thread include/converse.h
// Windows. NAMD's memory reports rely on it there, having no /proc to read.
CmiUInt8 CmiMemoryUsage(void);
#else
#define CmiMemoryUsage() 0

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.

With this change CmiMemoryUsage is a real function on Windows and still a macro returning 0 everywhere else. Classic read /proc/self/statm on Linux and used mach_task_basic_info on macOS. A Linux and macOS implementation would be a natural follow-up, so NAMD's memory reports are not Windows-only on reconverse.

# A native Windows build (MSVC set) assembles them with ml64 directly. Charm++
# on Windows instead drives MSVC from Cygwin through its unix2nt_cc wrapper,
# which hands .asm sources to ml64 itself, so there they go through the
# generic ASM language with that wrapper as the assembler.

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.

Confirmed from the Charm++ Windows CI log (charm #4087): that build identifies the wrapper as MSVC but MSVC is not set under CYGWIN, so it takes the generic ASM path as this comment says; the configure got past this point without trouble. (The #4087 stall is later, in Charm++'s own configure, not here.)

ritvikrao and others added 3 commits October 27, 2026 15:09
Requirements, the x64 Native Tools prompt, the CMake configure CI uses,
running and testing single-process, linking from another CMake project,
Windows-specific behaviour, and limitations.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Stack traces show function names from the .pdb; file:line appears
  only for code compiled with debug information.
- CCS is excluded from Windows test runs, not untested: its test passed
  when run by hand.
- reduction_many-overflow runs through sh, which a default Git for
  Windows install does not put on PATH, so desktop counts differ from
  CI's.
- The CMake example declares the FetchContent dependency it makes
  available.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The note to check out windows-support came after the build commands, so
following the page from the top built main, which fails at once with
"Cannot open include file: 'pthread.h'". Put the checkout in the
command block and quote that error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants