Skip to content

Commit c4ea288

Browse files
committed
Add Mercury pthread implementation and C compatibility fixes
Port simulated pthread support from sst-macro into Mercury, enabling skeleton apps (e.g. MVAPICH2) to use pthreads in the SST simulator.
1 parent d113c8a commit c4ea288

14 files changed

Lines changed: 1446 additions & 21 deletions

File tree

src/sst/elements/iris/libfabric/Makefile.am

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,30 @@ libfabric_la_SOURCES = \
192192
$(libfabric_headers) \
193193
$(rdmainclude_headers) \
194194
$(nodist_rdmainclude_headers)
195+
196+
# Standalone libfabric install for mvapich2 (--with-ofi= prefix)
197+
# Install standard libfabric headers to $(includedir)/rdma/ so that
198+
# -I$(prefix)/include gives #include <rdma/fabric.h>
199+
ofi_standalone_rdmadir = $(includedir)/rdma
200+
ofi_standalone_rdma_HEADERS = \
201+
include/rdma/fabric.h \
202+
include/rdma/fi_atomic.h \
203+
include/rdma/fi_cm.h \
204+
include/rdma/fi_collective.h \
205+
include/rdma/fi_domain.h \
206+
include/rdma/fi_endpoint.h \
207+
include/rdma/fi_eq.h \
208+
include/rdma/fi_errno.h \
209+
include/rdma/fi_rma.h \
210+
include/rdma/fi_tagged.h \
211+
include/rdma/fi_trigger.h
212+
213+
# Symlink libfabric from extdir to libdir so -lfabric finds it (e.g. mvapich2 --with-ofi=)
214+
install-exec-hook:
215+
$(MKDIR_P) $(DESTDIR)$(libdir)
216+
-if test -f $(DESTDIR)$(pkglibdir)/ext/libfabric.so; then \
217+
$(LN_S) -f '$(DESTDIR)$(pkglibdir)/ext/libfabric.so' $(DESTDIR)$(libdir)/libfabric.so; \
218+
elif test -f $(DESTDIR)$(pkglibdir)/ext/libfabric.so.0; then \
219+
$(LN_S) -f '$(DESTDIR)$(pkglibdir)/ext/libfabric.so.0' $(DESTDIR)$(libdir)/libfabric.so.0; \
220+
$(LN_S) -f libfabric.so.0 $(DESTDIR)$(libdir)/libfabric.so; \
221+
fi

src/sst/elements/mercury/Makefile.am

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ libhg_la_SOURCES = \
2626
common/timestamp.cc \
2727
common/connection.cc \
2828
common/skeleton.cc \
29+
common/hgcc_wrappers.cc \
2930
components/compute_library/node_cl.cc \
3031
components/compute_library/operating_system_cl.cc \
3132
components/compute_library/operating_system_cl_api.cc \
@@ -46,6 +47,8 @@ libhg_la_SOURCES = \
4647
operating_system/launch/app_launcher.cc \
4748
operating_system/libraries/library.cc \
4849
operating_system/libraries/unblock_event.cc \
50+
operating_system/libraries/pthread/hg_pthread.cc \
51+
operating_system/libraries/pthread/hg_pthread_runner.cc \
4952
operating_system/process/app.cc \
5053
operating_system/process/global.cc \
5154
operating_system/process/progress_queue.cc \
@@ -172,6 +175,11 @@ nobase_library_include_HEADERS = \
172175
operating_system/libraries/library.h \
173176
operating_system/libraries/library_fwd.h \
174177
operating_system/libraries/unblock_event.h \
178+
operating_system/libraries/pthread/hg_pthread.h \
179+
operating_system/libraries/pthread/hg_pthread_impl.h \
180+
operating_system/libraries/pthread/hg_pthread_macro.h \
181+
operating_system/libraries/pthread/hg_pthread_clear_macros.h \
182+
operating_system/libraries/pthread/hg_pthread_runner.h \
175183
operating_system/threading/context_util.h \
176184
operating_system/threading/thread_lock.h \
177185
operating_system/threading/stack_alloc.h \
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2009-2025 NTESS. Under the terms
2+
// of Contract DE-NA0003525 with NTESS, the U.S.
3+
// Government retains certain rights in this software.
4+
//
5+
// Copyright (c) 2009-2025, NTESS
6+
// All rights reserved.
7+
//
8+
// C-linkage wrappers for hgcc replacement headers (sleep, usleep, gettimeofday,
9+
// clock_gettime, nanosleep, getenv). These bridge to mercury's simulated time
10+
// and environment when running under SST.
11+
// Do not include skeleton.h here (it redefines main and breaks SST core headers).
12+
13+
#include <mercury/common/timestamp.h>
14+
#include <mercury/operating_system/process/thread.h>
15+
16+
#include <sys/time.h>
17+
#include <time.h>
18+
#include <cstdint>
19+
20+
namespace SST::Hg {
21+
extern unsigned int ssthg_sleep(unsigned int secs);
22+
extern unsigned int ssthg_usleep(unsigned int usecs);
23+
extern unsigned int ssthg_nanosleep(unsigned int nsecs);
24+
}
25+
26+
extern "C" char* ssthg_getenv(const char* name);
27+
28+
extern "C" {
29+
30+
unsigned int hgcc_sleep(unsigned int secs)
31+
{
32+
return SST::Hg::ssthg_sleep(secs);
33+
}
34+
35+
int hgcc_usleep(unsigned int usecs)
36+
{
37+
SST::Hg::ssthg_usleep(usecs);
38+
return 0;
39+
}
40+
41+
char* hgcc_getenv(const char* name)
42+
{
43+
return ssthg_getenv(name);
44+
}
45+
46+
int SSTMAC_gettimeofday(struct timeval* tv, struct timezone* tz)
47+
{
48+
if (!tv) return 0;
49+
SST::Hg::Thread* t = SST::Hg::Thread::current();
50+
if (!t) return -1;
51+
SST::Hg::Timestamp now = t->now();
52+
uint64_t usec = now.usecRounded();
53+
tv->tv_sec = static_cast<time_t>(usec / 1000000ULL);
54+
tv->tv_usec = static_cast<suseconds_t>(usec % 1000000ULL);
55+
if (tz) {
56+
tz->tz_minuteswest = 0;
57+
tz->tz_dsttime = 0;
58+
}
59+
return 0;
60+
}
61+
62+
int HGCC_clock_gettime(clockid_t /*id*/, struct timespec* ts)
63+
{
64+
if (!ts) return 0;
65+
SST::Hg::Thread* t = SST::Hg::Thread::current();
66+
if (!t) return -1;
67+
SST::Hg::Timestamp now = t->now();
68+
uint64_t nsec = now.nsecRounded();
69+
ts->tv_sec = static_cast<time_t>(nsec / 1000000000ULL);
70+
ts->tv_nsec = static_cast<long>(nsec % 1000000000ULL);
71+
return 0;
72+
}
73+
74+
int hgcc_ts_nanosleep(const struct timespec* req, struct timespec* rem)
75+
{
76+
if (!req) return -1;
77+
uint64_t total_nsec = static_cast<uint64_t>(req->tv_sec) * 1000000000ULL
78+
+ static_cast<uint64_t>(req->tv_nsec);
79+
const unsigned int max_nsec = static_cast<unsigned int>(-1);
80+
unsigned int nsecs = (total_nsec > max_nsec) ? max_nsec : static_cast<unsigned int>(total_nsec);
81+
SST::Hg::ssthg_nanosleep(nsecs);
82+
if (rem) {
83+
rem->tv_sec = 0;
84+
rem->tv_nsec = 0;
85+
}
86+
return 0;
87+
}
88+
89+
} // extern "C"

src/sst/elements/mercury/common/skeleton.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@
2323

2424
#if SST_HG_EXTERNAL
2525
#define SST_APP_NAME_QUOTED __FILE__ __DATE__
26+
#ifdef __cplusplus
2627
#define SST_DEFINE_EXE_NAME extern "C" const char exe_main_name[] = SST_APP_NAME_QUOTED;
2728
#else
29+
#define SST_DEFINE_EXE_NAME extern const char exe_main_name[] = SST_APP_NAME_QUOTED;
30+
#endif
31+
#else
2832
#define SST_APP_NAME_QUOTED SSTPP_STR(ssthg_app_name)
2933
#define SST_DEFINE_EXE_NAME
3034
#endif
@@ -33,6 +37,9 @@
3337
typedef int (*main_fxn)(int,char**);
3438
typedef int (*empty_main_fxn)();
3539

40+
#ifndef __cplusplus
41+
#include <stdbool.h>
42+
#else
3643
/* hate that I have to do this for cmake */
3744
#if __cplusplus < 201103L
3845
#define char16_t char16type
@@ -49,10 +56,14 @@ namespace SST {
4956
class Params;
5057
}
5158
#endif
59+
#endif /* __cplusplus */
5260

5361
#define define_var_name_pass_through(x) ssthg_dont_ignore_this##x
5462
#define define_var_name(x) define_var_name_pass_through(x)
5563

64+
#ifdef __cplusplus
65+
/* Main refactoring uses a static initializer with a function call, which is not
66+
* valid in C (compile-time constant required). Only apply for C++. */
5667
#ifndef SSTHG_NO_REFACTOR_MAIN
5768
#undef main
5869
#define main USER_MAIN
@@ -68,24 +79,35 @@ class Params;
6879
#else
6980
#define main ssthg_ignore_for_app_name(); int main
7081
#endif
82+
#endif /* __cplusplus */
7183

84+
#ifdef __cplusplus
7285
extern "C" {
86+
#endif
7387
extern int ssthg_global_stacksize;
7488
extern char* static_init_glbls_segment;
7589
extern char* static_init_tls_segment;
7690
void sst_hg_init_global_space(void* ptr, int size, int offset, bool tls);
7791
void sst_hg_advance_time(const char* param_name);
7892
void sst_hg_blocking_call(int condition, double timeout, const char* api);
93+
/* Alias for hgcc-generated pragma: ssthg_blocking_call -> sst_hg_blocking_call */
94+
#define ssthg_blocking_call sst_hg_blocking_call
95+
#ifdef __cplusplus
7996
}
97+
#endif
8098

81-
namespace SST::Hg {
99+
#ifdef __cplusplus
100+
namespace SST {
101+
namespace Hg {
82102

83103
unsigned int ssthg_sleep(unsigned int secs);
84104
unsigned int ssthg_usleep(unsigned int usecs);
85105
unsigned int ssthg_nanosleep(unsigned int nsecs);
86106

87-
} //end namespace SST::Hg
107+
} // namespace Hg
108+
} // namespace SST
88109

89110
#include <mercury/common/skeleton_tls.h>
90-
#include <mercury/common/null_buffer.h>
111+
#endif /* __cplusplus */
91112

113+
#include <mercury/common/null_buffer.h>

src/sst/elements/mercury/common/skeleton_tls.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@
2828
#endif
2929

3030

31+
#ifdef __cplusplus
3132
extern "C" {
33+
#endif
3234
extern char* static_init_glbls_segment;
3335
extern char* static_init_tls_segment;
3436
void allocate_static_init_glbls_segment();
3537
void allocate_static_init_tls_segment();
38+
#ifdef __cplusplus
3639
}
40+
#endif
3741

3842
SST_HG_MAYBE_UNUSED
3943
static SST_HG_INLINE char* get_sst_hg_global_data(){

src/sst/elements/mercury/components/operating_system_impl.cc

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -191,21 +191,13 @@ OperatingSystemImpl::startThread(Thread* t)
191191
void
192192
OperatingSystemImpl::joinThread(Thread* t)
193193
{
194-
sst_hg_abort_printf("OperatingSystem::joinThread not fully implemented");
195-
if (t->getState() != Thread::DONE) {
196-
// key* k = key::construct();
197-
// os_debug("joining thread %ld - thread not done so blocking on
198-
// thread %p",
199-
// t->threadId(), active_thread_);
200-
t->joiners_.push(active_thread_);
201-
// int ncores = active_thread_->numActiveCcores();
202-
// //when joining - release all cores
203-
// compute_sched_->releaseCores(ncores, active_thread_);
204-
// block();
205-
// compute_sched_->reserveCores(ncores, active_thread_);
206-
} else {
207-
// os_debug("joining completed thread %ld", t->threadId());
194+
if (t->getState() == Thread::DONE) {
195+
running_threads_.erase(t->tid());
196+
delete t;
197+
return;
208198
}
199+
t->joiners_.push(active_thread_);
200+
block();
209201
running_threads_.erase(t->tid());
210202
delete t;
211203
}

0 commit comments

Comments
 (0)