diff --git a/libstdc++-v3/include/bits/std_thread.h b/libstdc++-v3/include/bits/std_thread.h
index dd625de3bc3..f67bc114591 100644
--- a/libstdc++-v3/include/bits/std_thread.h
+++ b/libstdc++-v3/include/bits/std_thread.h
@@ -57,7 +57,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  @{
    */
 
-  /// thread
+  /** A std::thread represents a new thread of execution.
+   *
+   * The default constructor creates an object that does not own a thread.
+   * The `thread(F&&, Args&&...)` constructor invokes a callable in a new
+   * thread, and owns that new thread. A `std::thread` that owns a thread
+   * is *joinable*. Joining a thread waits for it to finish executing,
+   * which happens when the callable running in that thread returns.
+   *
+   * A `std::thread` cannot be copied, but can be moved. Moving a joinable
+   * object transfers ownership of its thread to another object.
+   *
+   * A joinable `std::thread` must be explicitly joined (or detached) before
+   * it is destroyed or assigned to. Attempting to destroy a joinable thread
+   * will terminate the whole process.
+   *
+   * @headerfile thread
+   * @since C++11
+   */
   class thread
   {
   public:
@@ -76,7 +93,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using native_handle_type = int;
 #endif
 
-    /// thread::id
+    /** A std::thread::id is a unique identifier for a thread.
+     *
+     * @headerfile thread
+     * @since C++11
+     */
     class id
     {
       native_handle_type	_M_thread;
@@ -261,8 +282,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       };
 
   public:
+    /// @cond undocumented
     template<typename... _Tp>
       using _Call_wrapper = _Invoker<tuple<typename decay<_Tp>::type...>>;
+    /// @endcond
 #endif // _GLIBCXX_HAS_GTHREADS
   };
 
@@ -272,10 +295,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline unsigned int thread::hardware_concurrency() noexcept { return 0; }
 #endif
 
+  /// @relates std::thread
   inline void
   swap(thread& __x, thread& __y) noexcept
   { __x.swap(__y); }
 
+  /// @relates std::thread::id
   inline bool
   operator==(thread::id __x, thread::id __y) noexcept
   {
@@ -301,7 +326,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   namespace this_thread
   {
-    /// this_thread::get_id
+    /// The unique identifier of the current thread.
     inline thread::id
     get_id() noexcept
     {
@@ -314,7 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
     }
 
-    /// this_thread::yield
+    /// Allow the implementation to schedule a different thread.
     inline void
     yield() noexcept
     {
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index a9268cade91..3d5d793a08e 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -58,7 +58,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    * @defgroup futures Futures
    * @ingroup concurrency
    *
-   * Classes for futures support.
+   * Futures and promises provide support for retrieving the result from
+   * an asynchronous function, e.g. one that is running in another thread.
+   * A `std::future` represents an asynchronous result that will become
+   * ready at some later time. A consumer can wait on a future until the
+   * result is ready to be accessed.
+   *
+   * @since C++11
    * @{
    */
 
@@ -71,7 +77,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     broken_promise
   };
 
-  /// Specialization.
+  /// Specialization that allows `future_errc` to convert to `error_code`.
   template<>
     struct is_error_code_enum<future_errc> : public true_type { };
 
@@ -79,12 +85,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   const error_category&
   future_category() noexcept;
 
-  /// Overload for make_error_code.
+  /// Overload of make_error_code for `future_errc`.
   inline error_code
   make_error_code(future_errc __errc) noexcept
   { return error_code(static_cast<int>(__errc), future_category()); }
 
-  /// Overload for make_error_condition.
+  /// Overload of make_error_condition for `future_errc`.
   inline error_condition
   make_error_condition(future_errc __errc) noexcept
   { return error_condition(static_cast<int>(__errc), future_category()); }
@@ -92,6 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /**
    *  @brief Exception type thrown by futures.
    *  @ingroup exceptions
+   *  @since C++11
    */
   class future_error : public logic_error
   {
@@ -178,11 +185,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     deferred
   };
 
+  /// @cond undocumented
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // 2021. Further incorrect usages of result_of
   template<typename _Fn, typename... _Args>
     using __async_result_of = typename __invoke_result<
       typename decay<_Fn>::type, typename decay<_Args>::type...>::type;
+  /// @endcond
 
   template<typename _Fn, typename... _Args>
     future<__async_result_of<_Fn, _Args...>>
@@ -194,6 +203,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if defined(_GLIBCXX_HAS_GTHREADS)
 
+  /// @cond undocumented
+
   /// Base class and enclosing scope.
   struct __future_base
   {
@@ -655,8 +666,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void _M_destroy() { delete this; }
     };
 
+  /// @endcond
+
 #ifndef _GLIBCXX_ASYNC_ABI_COMPAT
 
+  /// @cond undocumented
   // Allow _Setter objects to be stored locally in std::function
   template<typename _Res, typename _Arg>
     struct __is_location_invariant
@@ -668,6 +682,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_location_invariant
     <__future_base::_Task_setter<_Res_ptr, _Fn, _Res>>
     : true_type { };
+  /// @endcond
 
   /// Common implementation for future and shared_future.
   template<typename _Res>
@@ -1376,6 +1391,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
     };
 
+  /// @cond undocumented
   template<typename _Ptr_type, typename _Fn, typename _Res>
     struct __future_base::_Task_setter
     {
@@ -1512,6 +1528,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __create_task_state<_Res(_Args...)>(std::move(_M_impl._M_fn),
 						 static_cast<_Alloc&>(_M_impl));
     }
+  /// @endcond
 
   /// packaged_task
   template<typename _Res, typename... _ArgTypes>
@@ -1648,6 +1665,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public true_type { };
 #endif
 
+  /// @cond undocumented
+
   // Shared state created by std::async().
   // Holds a deferred function and storage for its result.
   template<typename _BoundFn, typename _Res>
@@ -1761,7 +1780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _Ptr_type _M_result;
       _BoundFn _M_fn;
     };
-
+  /// @endcond
 
   /// async
   template<typename _Fn, typename... _Args>
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index 92b24268ffe..82f191afe2d 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -50,6 +50,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /**
    * @defgroup threads Threads
    * @ingroup concurrency
+   * @since C++11
    *
    * Classes for thread support.
    * @{
@@ -57,6 +58,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // std::thread is defined in <bits/std_thread.h>
 
+  /// @relates std::thread::id @{
+
 #if __cpp_lib_three_way_comparison
   inline strong_ordering
   operator<=>(thread::id __x, thread::id __y) noexcept
@@ -96,9 +99,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       else
 	return __out << __id._M_thread;
     }
+  /// @}
 
 #ifdef __cpp_lib_jthread
 
+  /// @cond undocumented
 #ifndef __STRICT_ANSI__
     template<typename _Callable, typename... _Args>
       constexpr bool __pmf_expects_stop_token = false;
@@ -108,8 +113,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	= __and_<is_member_function_pointer<remove_reference_t<_Callable>>,
 		 is_invocable<_Callable, _Obj, stop_token, _Args...>>::value;
 #endif
+    /// @endcond
 
-  /// A thread that can be requested to stop and automatically joined.
+  /** A thread with cancellation and automatic joining.
+   *
+   * Unlike `std::thread`, destroying a joinable `std::jthread` will not
+   * terminate the process. Instead, it will try to request its thread to
+   * stop, then will join it.
+   *
+   * A `std::jthread` has a `std::stop_source` member which will be passed
+   * as the first argument to the callable that runs in the new thread
+   * (as long as the callable will accept that argument). That can then
+   * be used to send a stop request that the new thread can test for.
+   *
+   * @headerfile thread
+   * @since C++20
+   */
   class jthread
   {
   public:
