* [PATCH 0/3] Add compatibility definitions for C++ thread support
@ 2025-10-01 18:57 Tom Tromey
2025-10-01 18:57 ` [PATCH 1/3] Remove an unused include Tom Tromey
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Tom Tromey @ 2025-10-01 18:57 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This series adds some C++ compatibility support code, with the goal of
removing most checks of CXX_STD_THREAD -- while it's not really
practical to remove all the checks from gdb, the majority can be
removed using this technique. This makes the code somewhat cleaner,
at the expense of having to remember to use the "gdb" namespace rather
than "std". Perhaps some day we could remove the shims as well.
Regression tested on x86-64 Fedora 41, both with an ordinary build and
with a --disable-threading build. The latter has one pre-existing
failure.
Signed-off-by: Tom Tromey <tromey@adacore.com>
---
Tom Tromey (3):
Remove an unused include
Don't rely on deduction in run-on-main-thread.c
Introduce gdbsupport/cxx-thread.h and use it
gdb/complaints.c | 16 +--
gdb/dwarf2/cooked-index-worker.c | 17 +--
gdb/dwarf2/cooked-index-worker.h | 17 +--
gdb/dwarf2/read.c | 36 ++----
gdb/dwarf2/read.h | 8 +-
gdb/gdb_bfd.c | 47 ++------
gdb/minsyms.c | 37 ++----
gdb/run-on-main-thread.c | 38 ++----
gdbsupport/cxx-thread.h | 243 +++++++++++++++++++++++++++++++++++++++
gdbsupport/thread-pool.h | 91 +--------------
10 files changed, 297 insertions(+), 253 deletions(-)
---
base-commit: 52ca3d3fe6139ec45e04b4cfb1b5e244a8459586
change-id: 20251001-isolate-cxx-thread-ee03d199ab5b
Best regards,
--
Tom Tromey <tromey@adacore.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] Remove an unused include
2025-10-01 18:57 [PATCH 0/3] Add compatibility definitions for C++ thread support Tom Tromey
@ 2025-10-01 18:57 ` Tom Tromey
2025-10-01 20:04 ` Simon Marchi
2025-10-01 18:57 ` [PATCH 2/3] Don't rely on deduction in run-on-main-thread.c Tom Tromey
2025-10-01 18:57 ` [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it Tom Tromey
2 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2025-10-01 18:57 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
dwarf2/read.c no longer uses gdb::task_group, so the include isn't
needed.
---
gdb/dwarf2/read.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index bf982f9404287ee90f13b93f45869ad224893a63..05f8452895a0d7e2f7e53a3c45c5a0317d27c995 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -53,7 +53,6 @@
#include "event-top.h"
#include "exceptions.h"
#include "gdbsupport/parallel-for.h"
-#include "gdbsupport/task-group.h"
#include "maint.h"
#include "symtab.h"
#include "gdbtypes.h"
--
2.51.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/3] Don't rely on deduction in run-on-main-thread.c
2025-10-01 18:57 [PATCH 0/3] Add compatibility definitions for C++ thread support Tom Tromey
2025-10-01 18:57 ` [PATCH 1/3] Remove an unused include Tom Tromey
@ 2025-10-01 18:57 ` Tom Tromey
2025-10-01 18:57 ` [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it Tom Tromey
2 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2025-10-01 18:57 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This changes one spot in run-on-main-thread.c to use an explicit
template argument, rather than relying on deduction. The deduction
would otherwise fail with the next patch.
---
gdb/run-on-main-thread.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/run-on-main-thread.c b/gdb/run-on-main-thread.c
index bf53163b6b717bc7101619da15ce45810952284d..0cfe4716c24739f4de3daacff555e546ea2e5925 100644
--- a/gdb/run-on-main-thread.c
+++ b/gdb/run-on-main-thread.c
@@ -151,7 +151,7 @@ INIT_GDB_FILE (run_on_main_thread)
add_final_cleanup ([] ()
{
#if CXX_STD_THREAD
- std::lock_guard lock (runnable_mutex);
+ std::lock_guard<std::mutex> lock (runnable_mutex);
#endif
runnables.clear ();
});
--
2.51.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it
2025-10-01 18:57 [PATCH 0/3] Add compatibility definitions for C++ thread support Tom Tromey
2025-10-01 18:57 ` [PATCH 1/3] Remove an unused include Tom Tromey
2025-10-01 18:57 ` [PATCH 2/3] Don't rely on deduction in run-on-main-thread.c Tom Tromey
@ 2025-10-01 18:57 ` Tom Tromey
2025-10-01 20:16 ` Simon Marchi
2 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2025-10-01 18:57 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This introduces a new file, gdbsupport/cxx-thread.h, which provides
stubs for the C++ threading functionality on systems that don't
support it.
On fully-working ports, this header just supplies a number of aliases
in the gdb namespace. So, for instance, gdb::mutex is just an alias
for std::mutex.
For non-working ports, compatibility stubs are provided for the subset
of threading functionality that's used in gdb. These generally do
nothing and assume single-threaded operation.
The idea behind this is to reduce the number of checks of
CXX_STD_THREAD, making the code cleaner.
Not all spots using CXX_STD_THREAD could readily be converted.
In particular:
* Unit tests
* --config output
* Code manipulating threads themselves
* The extension interrupting handling code
These all seem fine to me.
Note there's also a check in py-dap.c. This one is perhaps slightly
subtle: DAP starts threads on the Python side, but it relies on gdb
itself being thread-savvy, for instance in gdb.post_event.
---
gdb/complaints.c | 16 +--
gdb/dwarf2/cooked-index-worker.c | 17 +--
gdb/dwarf2/cooked-index-worker.h | 17 +--
gdb/dwarf2/read.c | 35 ++----
gdb/dwarf2/read.h | 8 +-
gdb/gdb_bfd.c | 47 ++------
gdb/minsyms.c | 37 ++----
gdb/run-on-main-thread.c | 38 ++----
gdbsupport/cxx-thread.h | 243 +++++++++++++++++++++++++++++++++++++++
gdbsupport/thread-pool.h | 91 +--------------
10 files changed, 297 insertions(+), 252 deletions(-)
diff --git a/gdb/complaints.c b/gdb/complaints.c
index 3c7f9bc7c89604de766672ef0f4c78005ed7d83b..03d27d615a58e6e5e7d89cda951bbbb2ae9c53a2 100644
--- a/gdb/complaints.c
+++ b/gdb/complaints.c
@@ -22,11 +22,9 @@
#include "cli/cli-cmds.h"
#include "run-on-main-thread.h"
#include "top.h"
+#include "gdbsupport/cxx-thread.h"
#include "gdbsupport/selftest.h"
#include "gdbsupport/unordered_map.h"
-#if CXX_STD_THREAD
-#include <mutex>
-#endif
/* Map format strings to counters. */
@@ -38,9 +36,7 @@ static gdb::unordered_map<const char *, int> counters;
int stop_whining = 0;
-#if CXX_STD_THREAD
-static std::mutex complaint_mutex;
-#endif /* CXX_STD_THREAD */
+static gdb::mutex complaint_mutex;
/* See complaints.h. */
@@ -50,9 +46,7 @@ complaint_internal (const char *fmt, ...)
va_list args;
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (complaint_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (complaint_mutex);
if (++counters[fmt] > stop_whining)
return;
}
@@ -126,9 +120,7 @@ re_emit_complaints (const complaint_collection &complaints)
void
complaint_interceptor::warn (const char *fmt, va_list args)
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (complaint_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (complaint_mutex);
g_complaint_interceptor->m_complaints.insert (string_vprintf (fmt, args));
}
diff --git a/gdb/dwarf2/cooked-index-worker.c b/gdb/dwarf2/cooked-index-worker.c
index 09d80eff629c4d168e3108e5ee5d9bd082be6543..abaf41fb00c315e2e3261d0293e25faed4a147c9 100644
--- a/gdb/dwarf2/cooked-index-worker.c
+++ b/gdb/dwarf2/cooked-index-worker.c
@@ -132,9 +132,8 @@ bool
cooked_index_worker::wait (cooked_state desired_state, bool allow_quit)
{
bool done;
-#if CXX_STD_THREAD
{
- std::unique_lock<std::mutex> lock (m_mutex);
+ gdb::unique_lock<gdb::mutex> lock (m_mutex);
/* This may be called from a non-main thread -- this functionality
is needed for the index cache -- but in this case we require
@@ -146,7 +145,7 @@ cooked_index_worker::wait (cooked_state desired_state, bool allow_quit)
if (allow_quit)
{
std::chrono::milliseconds duration { 15 };
- if (m_cond.wait_for (lock, duration) == std::cv_status::timeout)
+ if (m_cond.wait_for (lock, duration) == gdb::cv_status::timeout)
QUIT;
}
else
@@ -154,11 +153,6 @@ cooked_index_worker::wait (cooked_state desired_state, bool allow_quit)
}
done = m_state == cooked_state::CACHE_DONE;
}
-#else
- /* Without threads, all the work is done immediately on the main
- thread, and there is never anything to wait for. */
- done = desired_state == cooked_state::CACHE_DONE;
-#endif /* CXX_STD_THREAD */
/* Only the main thread is allowed to report complaints and the
like. */
@@ -213,15 +207,10 @@ cooked_index_worker::set (cooked_state desired_state)
{
gdb_assert (desired_state != cooked_state::INITIAL);
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (m_mutex);
+ gdb::lock_guard<gdb::mutex> guard (m_mutex);
gdb_assert (desired_state > m_state);
m_state = desired_state;
m_cond.notify_one ();
-#else
- /* Without threads, all the work is done immediately on the main
- thread, and there is never anything to do. */
-#endif /* CXX_STD_THREAD */
}
/* See cooked-index-worker.h. */
diff --git a/gdb/dwarf2/cooked-index-worker.h b/gdb/dwarf2/cooked-index-worker.h
index dfdc82f52744ec36e626ab883d31a5d44071b063..4213b4e12b7214520f3856494777bee8aa9e2e01 100644
--- a/gdb/dwarf2/cooked-index-worker.h
+++ b/gdb/dwarf2/cooked-index-worker.h
@@ -27,11 +27,7 @@
#include "dwarf2/read.h"
#include "maint.h"
#include "run-on-main-thread.h"
-
-#if CXX_STD_THREAD
-#include <mutex>
-#include <condition_variable>
-#endif /* CXX_STD_THREAD */
+#include "gdbsupport/cxx-thread.h"
using cutu_reader_up = std::unique_ptr<cutu_reader>;
@@ -300,11 +296,9 @@ class cooked_index_worker
/* Result of each worker task. */
std::vector<cooked_index_worker_result> m_results;
-#if CXX_STD_THREAD
/* Mutex to synchronize access to M_RESULTS when workers append their
result. */
- std::mutex m_results_mutex;
-#endif /* CXX_STD_THREAD */
+ gdb::mutex m_results_mutex;
/* Any warnings emitted. For the time being at least, this only
needed in do_reading, not in every worker. Note that
@@ -317,13 +311,12 @@ class cooked_index_worker
parent relationships. */
parent_map_map m_all_parents_map;
-#if CXX_STD_THREAD
/* Current state of this object. */
cooked_state m_state = cooked_state::INITIAL;
/* Mutex and condition variable used to synchronize. */
- std::mutex m_mutex;
- std::condition_variable m_cond;
-#endif /* CXX_STD_THREAD */
+ gdb::mutex m_mutex;
+ gdb::condition_variable m_cond;
+
/* This flag indicates whether any complaints or exceptions that
arose during scanning have been reported by 'wait'. This may
only be modified on the main thread. */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 05f8452895a0d7e2f7e53a3c45c5a0317d27c995..6618b2242ff8e6106e81a3d72cac504725be561d 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -605,10 +605,8 @@ struct dwp_file
dwo_unit_set loaded_cus;
dwo_unit_set loaded_tus;
-#if CXX_STD_THREAD
/* Mutex to synchronize access to LOADED_CUS and LOADED_TUS. */
- std::mutex loaded_cutus_lock;
-#endif
+ gdb::mutex loaded_cutus_lock;
/* Table to map ELF section numbers to their sections.
This is only needed for the DWP V1 file format. */
@@ -3327,9 +3325,7 @@ class cooked_index_worker_debug_info : public cooked_index_worker
m_thread_storage.done_reading (m_complaint_handler.release ());
/* Append the results of this worker to the parent instance. */
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> lock (m_parent->m_results_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> lock (m_parent->m_results_mutex);
m_parent->m_results.emplace_back (std::move (m_thread_storage));
}
@@ -6318,12 +6314,8 @@ static dwo_file *
lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name,
const char *comp_dir)
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (per_bfd->dwo_files_lock);
-#endif
-
+ gdb::lock_guard<gdb::mutex> guard (per_bfd->dwo_files_lock);
auto it = per_bfd->dwo_files.find (dwo_file_search {dwo_name, comp_dir});
-
return it != per_bfd->dwo_files.end () ? it->get() : nullptr;
}
@@ -6338,10 +6330,7 @@ lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name,
static dwo_file *
add_dwo_file (dwarf2_per_bfd *per_bfd, dwo_file_up dwo_file)
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> lock (per_bfd->dwo_files_lock);
-#endif
-
+ gdb::lock_guard<gdb::mutex> lock (per_bfd->dwo_files_lock);
return per_bfd->dwo_files.emplace (std::move (dwo_file)).first->get ();
}
@@ -7473,10 +7462,7 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
= is_debug_types ? dwp_file->loaded_tus : dwp_file->loaded_cus;
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock);
-#endif
-
+ gdb::lock_guard<gdb::mutex> guard (dwp_file->loaded_cutus_lock);
if (auto it = dwo_unit_set.find (signature);
it != dwo_unit_set.end ())
return it->get ();
@@ -7511,10 +7497,7 @@ lookup_dwo_unit_in_dwp (dwarf2_per_bfd *per_bfd,
/* If another thread raced with this one, opening the exact same
DWO unit, then we'll keep that other thread's copy. */
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (dwp_file->loaded_cutus_lock);
-#endif
-
+ gdb::lock_guard<gdb::mutex> guard (dwp_file->loaded_cutus_lock);
auto it = dwo_unit_set.emplace (std::move (dwo_unit)).first;
return it->get ();
}
@@ -7594,12 +7577,10 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp,
return NULL;
{
-#if CXX_STD_THREAD
/* The operations below are not thread-safe, use a lock to synchronize
concurrent accesses. */
- static std::mutex mutex;
- std::lock_guard<std::mutex> lock (mutex);
-#endif
+ static gdb::mutex mutex;
+ gdb::lock_guard<gdb::mutex> lock (mutex);
if (!bfd_check_format (sym_bfd.get (), bfd_object))
return NULL;
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 2f9ad05b792bfeeb059229274fd43d2dc6ebc3d3..f0d46f6acc6cd95381c53c7b21876df9b2087661 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -20,9 +20,6 @@
#ifndef GDB_DWARF2_READ_H
#define GDB_DWARF2_READ_H
-#if CXX_STD_THREAD
-#include <mutex>
-#endif
#include <queue>
#include "dwarf2/abbrev.h"
#include "dwarf2/unit-head.h"
@@ -32,6 +29,7 @@
#include "dwarf2/section.h"
#include "dwarf2/cu.h"
#include "dwarf2/dwz.h"
+#include "gdbsupport/cxx-thread.h"
#include "gdbsupport/gdb_obstack.h"
#include "gdbsupport/function-view.h"
#include "gdbsupport/packed.h"
@@ -618,10 +616,8 @@ struct dwarf2_per_bfd
/* Set of dwo_file objects. */
dwo_file_up_set dwo_files;
-#if CXX_STD_THREAD
/* Mutex to synchronize access to DWO_FILES. */
- std::mutex dwo_files_lock;
-#endif
+ gdb::mutex dwo_files_lock;
/* The DWP file if there is one, or NULL. */
dwp_file_up dwp_file;
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 2e477eba6a9b8f31c558aeb6d37cdeeed369a6e6..4c641fe4c7b88094003b47ca77040b533f039453 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -33,18 +33,15 @@
#include "gdbsupport/fileio.h"
#include "inferior.h"
#include "cli/cli-style.h"
+#include "gdbsupport/cxx-thread.h"
#include "gdbsupport/unordered_map.h"
#include "gdbsupport/unordered_set.h"
-#if CXX_STD_THREAD
-
-#include <mutex>
-
/* Lock held when doing BFD operations. A recursive mutex is used
because we use this mutex internally and also for BFD, just to make
life a bit simpler, and we may sometimes hold it while calling into
BFD. */
-static std::recursive_mutex gdb_bfd_mutex;
+static gdb::recursive_mutex gdb_bfd_mutex;
/* BFD locking function. */
@@ -64,8 +61,6 @@ gdb_bfd_unlock (void *ignore)
return true;
}
-#endif /* CXX_STD_THREAD */
-
/* An object of this type is stored in the section's user data when
mapping a section. */
@@ -153,7 +148,6 @@ struct gdb_bfd_data
/* The registry. */
registry<bfd> registry_fields;
-#if CXX_STD_THREAD
/* Most of the locking needed for multi-threaded operation is
handled by BFD itself. However, the current BFD model is that
locking is only needed for global operations -- but it turned out
@@ -163,8 +157,7 @@ struct gdb_bfd_data
This lock is the fix: wrappers for important BFD functions will
acquire this lock before performing operations that might modify
the state of this BFD. */
- std::mutex per_bfd_mutex;
-#endif
+ gdb::mutex per_bfd_mutex;
};
registry<bfd> *
@@ -548,9 +541,7 @@ gdb_bfd_open (const char *name, const char *target, int fd,
name += strlen (TARGET_SYSROOT_PREFIX);
}
-#if CXX_STD_THREAD
- std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::recursive_mutex> guard (gdb_bfd_mutex);
if (fd == -1)
{
@@ -677,9 +668,7 @@ gdb_bfd_ref (struct bfd *abfd)
if (abfd == NULL)
return;
-#if CXX_STD_THREAD
- std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::recursive_mutex> guard (gdb_bfd_mutex);
gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
@@ -709,9 +698,7 @@ gdb_bfd_unref (struct bfd *abfd)
if (abfd == NULL)
return;
-#if CXX_STD_THREAD
- std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::recursive_mutex> guard (gdb_bfd_mutex);
gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd);
gdb_assert (gdata->refc >= 1);
@@ -779,10 +766,8 @@ gdb_bfd_map_section (asection *sectp, bfd_size_type *size)
abfd = sectp->owner;
-#if CXX_STD_THREAD
gdb_bfd_data *gdata = (gdb_bfd_data *) bfd_usrdata (abfd);
- std::lock_guard<std::mutex> guard (gdata->per_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (gdata->per_bfd_mutex);
descriptor = get_section_descriptor (sectp);
@@ -1115,10 +1100,8 @@ bool
gdb_bfd_get_full_section_contents (bfd *abfd, asection *section,
gdb::byte_vector *contents)
{
-#if CXX_STD_THREAD
gdb_bfd_data *gdata = (gdb_bfd_data *) bfd_usrdata (abfd);
- std::lock_guard<std::mutex> guard (gdata->per_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (gdata->per_bfd_mutex);
bfd_size_type section_size = bfd_section_size (section);
@@ -1133,10 +1116,8 @@ gdb_bfd_get_full_section_contents (bfd *abfd, asection *section,
int
gdb_bfd_stat (bfd *abfd, struct stat *sbuf)
{
-#if CXX_STD_THREAD
gdb_bfd_data *gdata = (gdb_bfd_data *) bfd_usrdata (abfd);
- std::lock_guard<std::mutex> guard (gdata->per_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (gdata->per_bfd_mutex);
return bfd_stat (abfd, sbuf);
}
@@ -1146,10 +1127,8 @@ gdb_bfd_stat (bfd *abfd, struct stat *sbuf)
long
gdb_bfd_get_mtime (bfd *abfd)
{
-#if CXX_STD_THREAD
gdb_bfd_data *gdata = (gdb_bfd_data *) bfd_usrdata (abfd);
- std::lock_guard<std::mutex> guard (gdata->per_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (gdata->per_bfd_mutex);
return bfd_get_mtime (abfd);
}
@@ -1290,9 +1269,7 @@ get_bfd_inferior_data (struct inferior *inf)
static unsigned long
increment_bfd_error_count (const std::string &str)
{
-#if CXX_STD_THREAD
- std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex);
-#endif
+ gdb::lock_guard<gdb::recursive_mutex> guard (gdb_bfd_mutex);
struct bfd_inferior_data *bid = get_bfd_inferior_data (current_inferior ());
auto &map = bid->bfd_error_string_counts;
@@ -1337,9 +1314,7 @@ gdb_bfd_init ()
{
if (bfd_init () == BFD_INIT_MAGIC)
{
-#if CXX_STD_THREAD
if (bfd_thread_init (gdb_bfd_lock, gdb_bfd_unlock, nullptr))
-#endif
return;
}
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index d3a8d670d1b5b8daa3266b69a371ba197ec2aba8..c23d170663744a03bda2a7ccec7e3a0763aace60 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -51,13 +51,10 @@
#include "cli/cli-utils.h"
#include "gdbsupport/symbol.h"
#include <algorithm>
+#include "gdbsupport/cxx-thread.h"
#include "gdbsupport/parallel-for.h"
#include "inferior.h"
-#if CXX_STD_THREAD
-#include <mutex>
-#endif
-
/* Return true if MINSYM is a cold clone symbol.
Recognize f.i. these symbols (mangled/demangled):
- _ZL3foov.cold
@@ -1398,18 +1395,13 @@ class minimal_symbol_install_worker
minimal_symbol_install_worker
(minimal_symbol *msymbols,
gdb::array_view<computed_hash_values> hash_values,
- objfile_per_bfd_storage *per_bfd
-#if CXX_STD_THREAD
- , std::mutex &demangled_mutex
-#endif
- )
+ objfile_per_bfd_storage *per_bfd,
+ gdb::mutex &demangled_mutex)
: m_time_it ("minsym install worker"),
m_msymbols (msymbols),
m_hash_values (hash_values),
- m_per_bfd (per_bfd)
-#if CXX_STD_THREAD
- , m_demangled_mutex (demangled_mutex)
-#endif
+ m_per_bfd (per_bfd),
+ m_demangled_mutex (demangled_mutex)
{}
void operator() (iterator_range<minimal_symbol *> msym_range) noexcept
@@ -1447,9 +1439,7 @@ class minimal_symbol_install_worker
{
/* To limit how long we hold the lock, we only acquire it here
and not while we demangle the names above. */
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> guard (m_demangled_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> guard (m_demangled_mutex);
for (minimal_symbol &msym : msym_range)
{
size_t idx = &msym - m_msymbols;
@@ -1467,9 +1457,7 @@ class minimal_symbol_install_worker
minimal_symbol *m_msymbols;
gdb::array_view<computed_hash_values> m_hash_values;
objfile_per_bfd_storage *m_per_bfd;
-#if CXX_STD_THREAD
- std::mutex &m_demangled_mutex;
-#endif
+ gdb::mutex &m_demangled_mutex;
};
/* Add the minimal symbols in the existing bunches to the objfile's official
@@ -1549,11 +1537,9 @@ minimal_symbol_reader::install ()
m_objfile->per_bfd->minimal_symbol_count = mcount;
m_objfile->per_bfd->msymbols = std::move (msym_holder);
-#if CXX_STD_THREAD
/* Mutex that is used when modifying or accessing the demangled
hash table. */
- std::mutex demangled_mutex;
-#endif
+ gdb::mutex demangled_mutex;
std::vector<computed_hash_values> hash_values (mcount);
@@ -1562,11 +1548,8 @@ minimal_symbol_reader::install ()
gdb::parallel_for_each<1000, minimal_symbol *, minimal_symbol_install_worker>
(&msymbols[0], &msymbols[mcount], msymbols,
gdb::array_view<computed_hash_values> (hash_values),
- m_objfile->per_bfd
-#if CXX_STD_THREAD
- , demangled_mutex
-#endif
- );
+ m_objfile->per_bfd,
+ demangled_mutex);
build_minimal_symbol_hash_tables (m_objfile, hash_values);
}
diff --git a/gdb/run-on-main-thread.c b/gdb/run-on-main-thread.c
index 0cfe4716c24739f4de3daacff555e546ea2e5925..d68811bebddcd8522c812930e8eec2efc3c462fe 100644
--- a/gdb/run-on-main-thread.c
+++ b/gdb/run-on-main-thread.c
@@ -18,11 +18,8 @@
#include "run-on-main-thread.h"
#include "ser-event.h"
-#if CXX_STD_THREAD
-#include <thread>
-#include <mutex>
-#endif
#include "gdbsupport/cleanups.h"
+#include "gdbsupport/cxx-thread.h"
#include "gdbsupport/event-loop.h"
/* The serial event used when posting runnables. */
@@ -33,17 +30,13 @@ static struct serial_event *runnable_event;
static std::vector<std::function<void ()>> runnables;
-#if CXX_STD_THREAD
-
/* Mutex to hold when handling RUNNABLE_EVENT or RUNNABLES. */
-static std::mutex runnable_mutex;
+static gdb::mutex runnable_mutex;
/* The main thread's thread id. */
-static std::thread::id main_thread_id;
-
-#endif
+static gdb::thread::id main_thread_id;
/* Run all the queued runnables. */
@@ -55,9 +48,7 @@ run_events (int error, gdb_client_data client_data)
/* Hold the lock while changing the globals, but not while running
the runnables. */
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> lock (runnable_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> lock (runnable_mutex);
/* Clear the event fd. Do this before flushing the events list,
so that any new event post afterwards is sure to re-awaken the
@@ -100,47 +91,38 @@ run_events (int error, gdb_client_data client_data)
void
run_on_main_thread (std::function<void ()> &&func)
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> lock (runnable_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> lock (runnable_mutex);
runnables.emplace_back (std::move (func));
serial_event_set (runnable_event);
}
-#if CXX_STD_THREAD
static bool main_thread_id_initialized = false;
-#endif
/* See run-on-main-thread.h. */
bool
is_main_thread ()
{
-#if CXX_STD_THREAD
/* Initialize main_thread_id on first use of is_main_thread. */
if (!main_thread_id_initialized)
{
main_thread_id_initialized = true;
- main_thread_id = std::this_thread::get_id ();
+ main_thread_id = gdb::this_thread::get_id ();
}
- return std::this_thread::get_id () == main_thread_id;
-#else
- return true;
-#endif
+ return gdb::this_thread::get_id () == main_thread_id;
}
INIT_GDB_FILE (run_on_main_thread)
{
-#if CXX_STD_THREAD
/* The variable main_thread_id should be initialized when entering main, or
at an earlier use, so it should already be initialized here. */
gdb_assert (main_thread_id_initialized);
/* Assume that we execute this in the main thread. */
gdb_assert (is_main_thread ());
-#endif
+
runnable_event = make_serial_event ();
add_file_handler (serial_event_fd (runnable_event), run_events, nullptr,
"run-on-main-thread");
@@ -150,9 +132,7 @@ INIT_GDB_FILE (run_on_main_thread)
languages are shut down. */
add_final_cleanup ([] ()
{
-#if CXX_STD_THREAD
- std::lock_guard<std::mutex> lock (runnable_mutex);
-#endif
+ gdb::lock_guard<gdb::mutex> lock (runnable_mutex);
runnables.clear ();
});
}
diff --git a/gdbsupport/cxx-thread.h b/gdbsupport/cxx-thread.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4061ebef9dfbc4287c258ac4c4754a3a41cf410
--- /dev/null
+++ b/gdbsupport/cxx-thread.h
@@ -0,0 +1,243 @@
+/* Wrappers for C++ threading
+
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDBSUPPORT_CXX_THREAD_H
+#define GDBSUPPORT_CXX_THREAD_H
+
+/* This header implements shims for the parts of the C++ threading
+ library that are needed by gdb.
+
+ The reason this exists is that some versions of libstdc++ do not
+ supply a working C++ thread implementation. In particular this was
+ true for several versions of the Windows compiler. See
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93687.
+
+ For systems where this works, this header just supplies aliases of
+ the standard functionality, in the "gdb" namespace. For example,
+ "gdb::mutex" is an alias for "std::mutex".
+
+ For non-working ports, shims are provided. These are just the
+ subset needed by gdb, and they generally do nothing, or as little
+ as possible. In particular they all simply assume single-threaded
+ operation. */
+
+#if CXX_STD_THREAD
+
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <future>
+
+namespace gdb
+{
+
+using condition_variable = std::condition_variable;
+using cv_status = std::cv_status;
+using future_status = std::future_status;
+using mutex = std::mutex;
+using recursive_mutex = std::recursive_mutex;
+using thread = std::thread;
+
+namespace this_thread = std::this_thread;
+
+template<typename T>
+using lock_guard = std::lock_guard<T>;
+
+template<typename T>
+using unique_lock = std::unique_lock<T>;
+
+template<typename T>
+using future = std::future<T>;
+
+} /* namespace gdb*/
+
+#else
+
+#include <chrono>
+
+namespace gdb
+{
+
+/* A do-nothing replacement for std::mutex. */
+struct mutex
+{
+ mutex () = default;
+
+ DISABLE_COPY_AND_ASSIGN (mutex);
+
+ void lock ()
+ {
+ }
+
+ void unlock ()
+ {
+ }
+};
+
+/* A do-nothing replacement for std::recursive_mutex. */
+struct recursive_mutex
+{
+ recursive_mutex () = default;
+
+ DISABLE_COPY_AND_ASSIGN (recursive_mutex);
+
+ void lock ()
+ {
+ }
+
+ void unlock ()
+ {
+ }
+};
+
+/* A do-nothing replacement for std::lock_guard. */
+template<typename T>
+struct lock_guard
+{
+ explicit lock_guard (T &m)
+ {
+ }
+
+ DISABLE_COPY_AND_ASSIGN (lock_guard);
+};
+
+/* A do-nothing replacement for std::unique_lock. */
+template<typename T>
+struct unique_lock
+{
+ explicit unique_lock (T &m)
+ {
+ }
+
+ DISABLE_COPY_AND_ASSIGN (unique_lock);
+};
+
+/* A compatibility enum for std::cv_status. */
+enum class cv_status
+{
+ no_timeout,
+ timeout,
+};
+
+/* A do-nothing replacement for std::condition_variable. */
+struct condition_variable
+{
+ condition_variable () = default;
+
+ DISABLE_COPY_AND_ASSIGN (condition_variable);
+
+ void notify_one () noexcept
+ {
+ }
+
+ void wait (unique_lock<mutex> &lock)
+ {
+ }
+
+ template<class Rep, class Period>
+ cv_status wait_for (unique_lock<mutex> &lock,
+ const std::chrono::duration<Rep, Period> &rel_time)
+ {
+ return cv_status::no_timeout;
+ }
+};
+
+/* A compatibility enum for std::future_status. This is just the
+ subset needed by gdb. */
+enum class future_status
+{
+ ready,
+ timeout,
+};
+
+/* A compatibility implementation of std::future. */
+template<typename T>
+class future
+{
+public:
+
+ explicit future (T value)
+ : m_value (std::move (value))
+ {
+ }
+
+ future () = default;
+ future (future &&other) = default;
+ future (const future &other) = delete;
+ future &operator= (future &&other) = default;
+ future &operator= (const future &other) = delete;
+
+ void wait () const { }
+
+ template<class Rep, class Period>
+ future_status wait_for (const std::chrono::duration<Rep,Period> &duration)
+ const
+ {
+ return future_status::ready;
+ }
+
+ T get () { return std::move (m_value); }
+
+private:
+
+ T m_value;
+};
+
+/* A specialization for void. */
+
+template<>
+class future<void>
+{
+public:
+ void wait () const { }
+
+ template<class Rep, class Period>
+ future_status wait_for (const std::chrono::duration<Rep,Period> &duration)
+ const
+ {
+ return future_status::ready;
+ }
+
+ void get () { }
+};
+
+/* Rather than try to write a gdb::thread class, we just use a
+ namespace since only the 'id' type is needed. Code manipulating
+ actual std::thread objects has to be wrapped in a check anyway. */
+namespace thread
+{
+/* Replacement for std::thread::id. */
+using id = int;
+}
+
+/* Replacement for std::this_thread. */
+namespace this_thread
+{
+static inline thread::id
+get_id ()
+{
+ return 0;
+}
+}
+
+} /* namespace gdb */
+
+#endif /* CXX_STD_THREAD */
+
+#endif /* GDBSUPPORT_CXX_THREAD_H */
diff --git a/gdbsupport/thread-pool.h b/gdbsupport/thread-pool.h
index f3ac94bf5882cb4233a5d4857449e41f48b9125f..b5b2934b8c3f8b56fbbe766b556a0ba808186a6c 100644
--- a/gdbsupport/thread-pool.h
+++ b/gdbsupport/thread-pool.h
@@ -24,99 +24,12 @@
#include <vector>
#include <functional>
#include <chrono>
-#if CXX_STD_THREAD
-#include <thread>
-#include <mutex>
-#include <condition_variable>
-#include <future>
-#endif
#include <optional>
-namespace gdb
-{
-
-#if CXX_STD_THREAD
-
-/* Simply use the standard future. */
-template<typename T>
-using future = std::future<T>;
-
-/* ... and the standard future_status. */
-using future_status = std::future_status;
-
-#else /* CXX_STD_THREAD */
-
-/* A compatibility enum for std::future_status. This is just the
- subset needed by gdb. */
-enum class future_status
-{
- ready,
- timeout,
-};
-
-/* A compatibility wrapper for std::future. Once <thread> and
- <future> are available in all GCC builds -- should that ever happen
- -- this can be removed. GCC does not implement threading for
- MinGW, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93687.
-
- Meanwhile, in this mode, there are no threads. Tasks submitted to
- the thread pool are invoked immediately and their result is stored
- here. The base template here simply wraps a T and provides some
- std::future compatibility methods. The provided methods are chosen
- based on what GDB needs presently. */
-
-template<typename T>
-class future
-{
-public:
-
- explicit future (T value)
- : m_value (std::move (value))
- {
- }
-
- future () = default;
- future (future &&other) = default;
- future (const future &other) = delete;
- future &operator= (future &&other) = default;
- future &operator= (const future &other) = delete;
+#include "gdbsupport/cxx-thread.h"
- void wait () const { }
-
- template<class Rep, class Period>
- future_status wait_for (const std::chrono::duration<Rep,Period> &duration)
- const
- {
- return future_status::ready;
- }
-
- T get () { return std::move (m_value); }
-
-private:
-
- T m_value;
-};
-
-/* A specialization for void. */
-
-template<>
-class future<void>
+namespace gdb
{
-public:
- void wait () const { }
-
- template<class Rep, class Period>
- future_status wait_for (const std::chrono::duration<Rep,Period> &duration)
- const
- {
- return future_status::ready;
- }
-
- void get () { }
-};
-
-#endif /* CXX_STD_THREAD */
-
/* A thread pool.
--
2.51.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] Remove an unused include
2025-10-01 18:57 ` [PATCH 1/3] Remove an unused include Tom Tromey
@ 2025-10-01 20:04 ` Simon Marchi
2025-10-02 12:59 ` Tom Tromey
0 siblings, 1 reply; 9+ messages in thread
From: Simon Marchi @ 2025-10-01 20:04 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 10/1/25 2:57 PM, Tom Tromey wrote:
> dwarf2/read.c no longer uses gdb::task_group, so the include isn't
> needed.
clangd also points out that gdbsupport/thread-pool.h is also unused now.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it
2025-10-01 18:57 ` [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it Tom Tromey
@ 2025-10-01 20:16 ` Simon Marchi
2025-10-02 16:58 ` Tom Tromey
0 siblings, 1 reply; 9+ messages in thread
From: Simon Marchi @ 2025-10-01 20:16 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
On 10/1/25 2:57 PM, Tom Tromey wrote:
> This introduces a new file, gdbsupport/cxx-thread.h, which provides
> stubs for the C++ threading functionality on systems that don't
> support it.
>
> On fully-working ports, this header just supplies a number of aliases
> in the gdb namespace. So, for instance, gdb::mutex is just an alias
> for std::mutex.
>
> For non-working ports, compatibility stubs are provided for the subset
> of threading functionality that's used in gdb. These generally do
> nothing and assume single-threaded operation.
>
> The idea behind this is to reduce the number of checks of
> CXX_STD_THREAD, making the code cleaner.
>
> Not all spots using CXX_STD_THREAD could readily be converted.
> In particular:
>
> * Unit tests
> * --config output
> * Code manipulating threads themselves
> * The extension interrupting handling code
>
> These all seem fine to me.
>
> Note there's also a check in py-dap.c. This one is perhaps slightly
> subtle: DAP starts threads on the Python side, but it relies on gdb
> itself being thread-savvy, for instance in gdb.post_event.
I think this looks good. The remaining uses of CXX_STD_THREAD appear to
be in areas we don't touch often. I like that we no longer need to wrap
all uses of std::mutex:w
Did you get a chance to validate your change on one of those toolchains
that don't have std::thread support?
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] Remove an unused include
2025-10-01 20:04 ` Simon Marchi
@ 2025-10-02 12:59 ` Tom Tromey
0 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2025-10-02 12:59 UTC (permalink / raw)
To: Simon Marchi; +Cc: Tom Tromey, gdb-patches
>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:
Simon> On 10/1/25 2:57 PM, Tom Tromey wrote:
>> dwarf2/read.c no longer uses gdb::task_group, so the include isn't
>> needed.
Simon> clangd also points out that gdbsupport/thread-pool.h is also unused now.
I made this change.
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it
2025-10-01 20:16 ` Simon Marchi
@ 2025-10-02 16:58 ` Tom Tromey
2025-10-02 18:09 ` Tom Tromey
0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2025-10-02 16:58 UTC (permalink / raw)
To: Simon Marchi; +Cc: Tom Tromey, gdb-patches
Simon> Did you get a chance to validate your change on one of those toolchains
Simon> that don't have std::thread support?
I don't seem to have access to one any more. I thought perhaps my older
(Fedora 40) machine had a mingw toolchain without this support, but the
build still manages to define CXX_STD_THREAD.
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it
2025-10-02 16:58 ` Tom Tromey
@ 2025-10-02 18:09 ` Tom Tromey
0 siblings, 0 replies; 9+ messages in thread
From: Tom Tromey @ 2025-10-02 18:09 UTC (permalink / raw)
To: Tom Tromey; +Cc: Simon Marchi, gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:
Simon> Did you get a chance to validate your change on one of those toolchains
Simon> that don't have std::thread support?
Tom> I don't seem to have access to one any more. I thought perhaps my older
Tom> (Fedora 40) machine had a mingw toolchain without this support, but the
Tom> build still manages to define CXX_STD_THREAD.
I'm going to check this in regardless.
If there's a problem, let me know and I will fix it ASAP.
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-10-02 18:09 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-01 18:57 [PATCH 0/3] Add compatibility definitions for C++ thread support Tom Tromey
2025-10-01 18:57 ` [PATCH 1/3] Remove an unused include Tom Tromey
2025-10-01 20:04 ` Simon Marchi
2025-10-02 12:59 ` Tom Tromey
2025-10-01 18:57 ` [PATCH 2/3] Don't rely on deduction in run-on-main-thread.c Tom Tromey
2025-10-01 18:57 ` [PATCH 3/3] Introduce gdbsupport/cxx-thread.h and use it Tom Tromey
2025-10-01 20:16 ` Simon Marchi
2025-10-02 16:58 ` Tom Tromey
2025-10-02 18:09 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox