Skip to content

Commit

Permalink
Qthreads 1.22 (chapel-lang#26744)
Browse files Browse the repository at this point in the history
This updates the bundled copy of qthreads to 1.22. It also switches to
using the new qthreads cmake build config. Currently this is using the
latest 1.22 release candidate and shouldn't be merged until the 1.22
release is finalized there. I'm submitting it now for testing so there's
some time to fix anything that comes up before the release.

[Contributed by @insertinterestingnamehere, reviewed and merged by @jabraham17]
  • Loading branch information
jabraham17 authored Feb 28, 2025
2 parents cb4cae9 + 441bb44 commit 8637c0a
Show file tree
Hide file tree
Showing 311 changed files with 3,537 additions and 76,059 deletions.
107 changes: 32 additions & 75 deletions third-party/qthread/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ endif
CHPL_MAKE_HOST_TARGET = --target
include $(CHPL_MAKE_HOME)/make/Makefile.base

CMAKE ?= cmake

export CHPL_MAKE_LOCALE_MODEL

#
Expand All @@ -15,33 +17,18 @@ QTHREAD_INSTALL_DIR = $(QTHREAD_ABS_DIR)/$(QTHREAD_INSTALL_SUBDIR)
QTHREAD_BUILD_DIR = $(QTHREAD_ABS_DIR)/$(QTHREAD_BUILD_SUBDIR)
QTHREAD_DIR = $(QTHREAD_ABS_DIR)

#
# Cray builds are cross-compilations
#
ifneq (, $(filter cray-x%,$(CHPL_MAKE_TARGET_PLATFORM)))
CHPL_QTHREAD_CFG_OPTIONS += --host=$(CHPL_MAKE_TARGET_ARCH)-cle-linux-gnu
else ifneq (, $(filter cray-cs hpe-cray-ex,$(CHPL_MAKE_TARGET_PLATFORM)))
CHPL_QTHREAD_CFG_OPTIONS += --host=$(CHPL_MAKE_TARGET_ARCH)-unknown-linux-gnu
endif

ifneq ($(CHPL_MAKE_HWLOC),none)
# Have Qthreads get its hwloc topology from the Chapel runtime,
# unless directed not to.
TOPOLOGY=binders
ifeq (, $(call isTrue, $(CHPL_QTHREAD_DONT_GET_TOPO_FROM_RT)))
CFLAGS_NEEDS_RT_INCLUDES = y
CHPL_QTHREAD_CFG_OPTIONS += --with-hwloc-get-topology-function="chpl_topo_getHwlocTopology()"
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_HWLOC_GET_TOPOLOGY_FUNCTION="chpl_topo_getHwlocTopology()"
endif
ifeq ($(CHPL_MAKE_HWLOC),bundled)
CHPL_QTHREAD_CFG_OPTIONS += --with-hwloc=$(HWLOC_INSTALL_DIR)
ifdef CHPL_HWLOC_PREFIX
CHPL_QTHREAD_CFG_OPTIONS += --with-hwloc-symbol-prefix=$(CHPL_HWLOC_PREFIX)hwloc_
endif
# don't bother checking if we can link against hwloc
CHPL_QTHREAD_CFG_OPTIONS += --disable-hwloc-configure-checks
CHPL_QTHREAD_CFG_OPTIONS += -DHWLOC_INSTALL_DIR=$(HWLOC_INSTALL_DIR)
else ifeq ($(CHPL_MAKE_HWLOC),system)
CHPL_QTHREAD_CFG_OPTIONS += --with-hwloc=$(shell $(CHPL_MAKE_PYTHON) $(CHPL_MAKE_HOME)/util/chplenv/chpl_hwloc.py --prefix)
CHPL_QTHREAD_CFG_OPTIONS += --disable-hwloc-configure-checks
CHPL_QTHREAD_CFG_OPTIONS += -DHWLOC_INSTALL_DIR=$(shell $(CHPL_MAKE_PYTHON) $(CHPL_MAKE_HOME)/util/chplenv/chpl_hwloc.py --prefix)
endif
endif

Expand All @@ -50,7 +37,7 @@ TOPOLOGY = $(CHPL_QTHREAD_TOPOLOGY)
endif

ifneq (, $(TOPOLOGY))
CHPL_QTHREAD_CFG_OPTIONS += --with-topology=$(TOPOLOGY)
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_TOPOLOGY=$(TOPOLOGY)
endif

# Used to create qthread-chapel.h
Expand All @@ -62,7 +49,7 @@ endif

# Have qthreads use Chapel's allocator, unless directed not to
ifeq (, $(call isTrue, $(CHPL_QTHREAD_NO_CHPL_ALLOC)))
CHPL_QTHREAD_CFG_OPTIONS += --with-alloc=chapel
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_ALLOC=chapel
CFLAGS_NEEDS_RT_INCLUDES = y
endif

Expand Down Expand Up @@ -120,17 +107,13 @@ endif
HAVE_GUARD_PAGES = 0
ifeq (, $(call isTrue, $(CHPL_QTHREAD_NO_GUARD_PAGES)))
HAVE_GUARD_PAGES = 1
CHPL_QTHREAD_CFG_OPTIONS += --enable-guard-pages
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_GUARD_PAGES=ON
endif

# optionally enable printing compilation commands, etc. (to help diagnose
# build problems)
ifneq (, $(CHPL_QTHREAD_LOUD_RULES))
CHPL_QTHREAD_CFG_OPTIONS += --disable-silent-rules
CHPL_QTHREAD_CFG_OPTIONS += -DCMAKE_VERBOSE_MAKEFILE=ON
endif

CHPL_QTHREAD_CFG_OPTIONS += --enable-static --disable-shared

# determine which scheduler to use based on locale model. Override with a user
# provided option if they requested one.
SCHEDULER = nemesis
Expand All @@ -144,33 +127,17 @@ endif
ifneq (, $(CHPL_QTHREAD_SCHEDULER))
SCHEDULER = $(CHPL_QTHREAD_SCHEDULER)
endif
CHPL_QTHREAD_CFG_OPTIONS += --with-scheduler=$(SCHEDULER)
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_SCHEDULER=$(SCHEDULER)

# only do this on M1+ Macs
ifeq ($(CHPL_MAKE_TARGET_ARCH),arm64)
ifeq ($(CHPL_MAKE_TARGET_PLATFORM),darwin)
CHPL_QTHREAD_CFG_OPTIONS += --with-cacheline-width=128
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_CACHELINE_SIZE_ESTIMATE=128
endif
endif

# reduce performance penalty in cases where numChapelTasks < numQthreadWorkers
CHPL_QTHREAD_CFG_OPTIONS += --enable-condwait-queue

# pgi doesn't support the proper atomic intrinsics that are required for
# spinlocks to be fast, so disable them for pgi, and PrgEnv-pgi
ifneq (, $(findstring pgi,$(CHPL_MAKE_TARGET_COMPILER)))
CHPL_QTHREAD_CFG_OPTIONS += --disable-internal-spinlock
endif

# Address sanitizer doesn't work with asm context switching so try
# makecontext/swapcontext (which may have false-positives, but doesn't
# immediately fail)
ifneq (,$(CHPL_QTHREAD_SANITIZER_SUPPORT))
CHPL_QTHREAD_CFG_OPTIONS += --disable-fastcontext
ifeq ($(CHPL_MAKE_TARGET_ARCH),arm64)
CFLAGS += -D_XOPEN_SOURCE
endif
endif
CHPL_QTHREAD_CFG_OPTIONS += -DQTHREADS_CONDWAIT_QUEUE=ON

ifeq ($(CHPL_LIB_PIC),pic)
CFLAGS += $(SHARED_LIB_CFLAGS)
Expand All @@ -193,35 +160,28 @@ clobber: FORCE


qthread-config: FORCE
@test -z "$(FAILBUILD)" || ( echo 'compileline failed!' && false )

#
# These first few lines touch a bunch of autoconf-oriented files in a
# certain order to prevent autoconf from running again; otherwise, we
# ran into issues if a user's autoconf environment was not as far
# ahead in version numbers as that which was used when packaging the
# Qthreads release
#
cd $(QTHREAD_SUBDIR) && touch -c configure.ac
cd $(QTHREAD_SUBDIR) && find . -name "*.m4" | xargs touch
sleep 1
cd $(QTHREAD_SUBDIR) && touch -c aclocal.m4
sleep 1
cd $(QTHREAD_SUBDIR) && touch configure
cd $(QTHREAD_SUBDIR) && find . -name "*.in" | xargs touch

#
# Then configure
#
mkdir -p $(QTHREAD_BUILD_DIR)
cd $(QTHREAD_BUILD_DIR) \
&& $(QTHREAD_SUBDIR)/configure CC='$(CC)' CFLAGS='$(CFLAGS)' \
CXX='$(CXX)' CXXFLAGS='$(CFLAGS)' LDFLAGS='$(RUNTIME_LFLAGS) $(LDFLAGS)' \
--prefix=$(QTHREAD_INSTALL_DIR) $(CHPL_QTHREAD_CFG_OPTIONS)
$(CMAKE) -B $(QTHREAD_BUILD_DIR) -S $(QTHREAD_SUBDIR) \
$(CHPL_QTHREAD_CFG_OPTIONS) \
-DQTHREADS_BUILD_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX='$(QTHREAD_INSTALL_DIR)' \
-DCMAKE_INSTALL_LIBDIR='$(QTHREAD_LIB_DIR)' \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_C_COMPILER='$(CC)' \
-DCMAKE_C_FLAGS='$(CFLAGS)' \
-DCMAKE_CXX_COMPILER='$(CXX)' \
-DCMAKE_CXX_FLAGS='$(CXXFLAGS)' \
-DCMAKE_MAKE_PROGRAM='$(MAKE)'

qthread-build: FORCE
cd $(QTHREAD_BUILD_DIR) && $(MAKE)
cd $(QTHREAD_BUILD_DIR) && $(MAKE) install
if [ -f $(QTHREAD_BUILD_DIR)/Makefile ]; then cd $(QTHREAD_BUILD_DIR) && $(MAKE); else $(CMAKE) --build $(QTHREAD_BUILD_DIR); fi

qthread-install: FORCE
if [ -f $(QTHREAD_BUILD_DIR)/Makefile ]; then cd $(QTHREAD_BUILD_DIR) && $(MAKE) install; else $(CMAKE) --install $(QTHREAD_BUILD_DIR); fi

FORCE:

.NOTPARALLEL:

#
# The two variables here answer different questions even though they're
Expand Down Expand Up @@ -258,10 +218,7 @@ qthread-chapel-h: FORCE
$(USE_TOPOLOGY_BINDERS) \
>> $(QTHREAD_INSTALL_DIR)/include/qthread-chapel.h

qthread: qthread-config qthread-build qthread-chapel-h

qthread-reconfig:
cd $(QTHREAD_SUBDIR) && autoreconf -f -i
qthread: qthread-config qthread-build qthread-install qthread-chapel-h

FORCE:

Expand Down
100 changes: 12 additions & 88 deletions third-party/qthread/README
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Qthreads README for Chapel
==========================

This copy of Qthreads 1.21 is being released with Chapel for
This copy of Qthreads 1.22 is being released with Chapel for
convenience and was obtained from:

https://github.com/sandialabs/qthreads
Expand All @@ -11,95 +11,19 @@ Any Chapel issues that seem to be related to Qthreads should be directed
to the Chapel team at https://chapel-lang.org/bugs.html.


Upgrading qthread versions
Upgrading versions
============================

The directory $CHPL_HOME/third-party/qthread/qthread-src contains the
un-tarballed qthread package contents. Version updates should be done as
follows, assuming the CWD is $CHPL_HOME/third-party/qthread/:
The directory $CHPL_HOME/third-party/qthread/qthread-src contains
a copy of the Qthreads repository. Version updates should be done
as follows, assuming the CWD is $CHPL_HOME/third-party/qthread/:

1. download the latest qthread version: e.g. `wget https://github.com/sandialabs/qthreads/releases/download/1.21/qthreads-1.21.tar.gz`
2. `tar xf qthreads-1.21.tar.gz`
3. `git rm -r qthread-src`
4. `mv qthreads-1.21 qthread-src`
5. `git add --force qthread-src` (--force to ignore our .gitignore)
6. update the version number mentioned above
7. test
8. commit, PR, merge, etc
1. download the latest qthread version: e.g. `wget https://github.com/sandialabs/qthreads/archive/refs/tags/1.22.tar.gz -O qthread-src.tar.gz`
2. `git rm -r qthread-src`
3. `tar xf qthread-src.tar.gz`
4. `git add --force qthread-src` (--force to ignore our .gitignore)
5. update the version number mentioned above
6. test
7. commit, PR, merge, etc

Chapel modifications to Qthreads
================================

The modifications that we have made to the official Qthreads release are
as follows:

* Do not #include "qthread.hpp" ifdef CHPL_AVOID_CPP_CODE
https://github.com/chapel-lang/chapel/pull/25507

```
diff --git a/third-party/qthread/qthread-src/include/qthread/qthread.h b/third-party/qthread/qthread-src/include/qthread/qthread.h
index 8269aa0949..bf022bc243 100644
--- a/third-party/qthread/qthread-src/include/qthread/qthread.h
+++ b/third-party/qthread/qthread-src/include/qthread/qthread.h
@@ -709,7 +709,7 @@ uint64_t qthread_syncvar_incrF(syncvar_t *restrict operand, uint64_t inc);

Q_ENDCXX /* */

-#ifndef __cplusplus
+#if !defined __cplusplus || defined CHPL_AVOID_CPP_CODE

#define qthread_incr(ADDR, INCVAL) __sync_fetch_and_add(ADDR, INCVAL)

```
* Backport a few performance fixes from the development version of qthreads.
https://github.com/chapel-lang/chapel/pull/26138

```
diff --git a/include/qt_atomics.h b/include/qt_atomics.h
index 2ac887ed..2312c954 100644
--- a/include/qt_atomics.h
+++ b/include/qt_atomics.h
@@ -21,8 +21,24 @@
#define THREAD_FENCE_MEM_RELEASE THREAD_FENCE_MEM_RELEASE_IMPL
#endif

+#if QTHREAD_ASSEMBLY_ARCH == QTHREAD_IA32 || \
+ QTHREAD_ASSEMBLY_ARCH == QTHREAD_AMD64
#define SPINLOCK_BODY() \
- do { MACHINE_FENCE; } while (0)
+ do { __asm__ __volatile__("pause" ::: "memory"); } while (0)
+#elif QTHREAD_ASSEMBLY_ARCH == QTHREAD_ARM || \
+ QTHREAD_ASSEMBLY_ARCH == QTHREAD_ARMV8_A64
+#define SPINLOCK_BODY() \
+ do { __asm__ __volatile__("yield" ::: "memory"); } while (0)
+#elif QTHREAD_ASSEMBLY_ARCH == QTHREAD_POWERPC64 || \
+ QTHREAD_ASSEMBLY_ARCH == QTHREAD_POWERPC32
+// For whatever reason the 29 (mdoio) version of this instruction performed
+// better in some back-of-the-envelope benchmarking so we're using that.
+#define SPINLOCK_BODY() \
+ do { __asm__ __volatile__("or 29,29,29" ::: "memory"); } while (0)
+#else
+#define SPINLOCK_BODY() \
+ do { atomic_thread_fence(memory_order_acq_rel); } while (0)
+#endif

#define QTHREAD_FASTLOCK_SETUP() \
do { \
```

* Backport a few performance fixes from the development version of qthreads.
part of https://github.com/chapel-lang/chapel/pull/26328, the rest was
reverted in https://github.com/chapel-lang/chapel/pull/26468

```
--- a/src/io.c
+++ b/src/io.c
@@ -74,7 +74,6 @@ static void qt_blocking_subsystem_internal_freemem(void) { /*{{{*/
static void *qt_blocking_subsystem_proxy_thread(void *Q_UNUSED(arg)) { /*{{{*/
while (!atomic_load_explicit(&proxy_exit, memory_order_relaxed)) {
if (qt_process_blocking_call()) { break; }
- MACHINE_FENCE;
}
atomic_fetch_sub_explicit(&io_worker_count, 1, memory_order_relaxed);
pthread_exit(NULL);
```
1 change: 0 additions & 1 deletion third-party/qthread/qthread-src/.autogen-version

This file was deleted.

Loading

0 comments on commit 8637c0a

Please sign in to comment.