diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index a8dea8b41fd1b21270b2e56c8ec3df7a22a0dd73..dc39bd43c79f5aebfc9067e5a7da2e5a783dd78f 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -8078,6 +8078,46 @@ PMOD_EXPORT void f_gethrtime(INT32 args)
   }
 }
 
+/*! @decl int gethrdtime(void|int nsec)
+ *!
+ *! Return the high resolution real time spent with threads disabled
+ *! since the Pike interpreter was started. The time is normally
+ *! returned in microseconds, but if the optional argument @[nsec]
+ *! is nonzero it's returned in nanoseconds.
+ *!
+ *! @note
+ *!   The actual accuracy on many systems is significantly less than
+ *!   microseconds or nanoseconds. See @[System.REAL_TIME_RESOLUTION].
+ *!
+ *! @seealso
+ *!   @[_disable_threads()], @[gethrtime()]
+ */
+static void f_gethrdtime(INT32 args)
+{
+  int nsec = args && !UNSAFE_IS_ZERO(Pike_sp-args);
+  cpu_time_t time = threads_disabled_acc_time;
+  pop_n_elems(args);
+
+  if (threads_disabled) {
+    time += get_real_time() - threads_disabled_start;
+  }
+  if (nsec) {
+    push_int64(time);
+#ifndef LONG_CPU_TIME
+    push_int(1000000000 / CPU_TIME_TICKS);
+    o_multiply();
+#endif
+  } else {
+#if CPU_TIME_TICKS_LOW > 1000000
+    push_int64(time / (CPU_TIME_TICKS / 1000000));
+#else
+    push_int64 (time);
+    push_int (1000000 / CPU_TIME_TICKS);
+    o_multiply();
+#endif
+  }
+}
+
 #ifdef PROFILING
 /*! @decl array(int|mapping(string:array(int))) @
  *!           get_profiling_info(program prog)
@@ -9572,6 +9612,8 @@ void init_builtin_efuns(void)
 	   tFunc(tOr(tInt,tVoid),tInt), OPT_EXTERNAL_DEPEND);
   ADD_EFUN("gethrtime", f_gethrtime,
 	   tFunc(tOr(tInt,tVoid),tInt), OPT_EXTERNAL_DEPEND);
+  ADD_EFUN("gethrdtime", f_gethrdtime,
+	   tFunc(tOr(tInt,tVoid),tInt), OPT_EXTERNAL_DEPEND);
 
 #ifdef PROFILING
   ADD_EFUN("get_profiling_info", f_get_prof_info,
diff --git a/src/threads.c b/src/threads.c
index 4abd32c1e2cdc56f4838169af8d95296e6790553..80f9c78fbc8ec9e1a5d8af60ccd2902609dc538f 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -935,6 +935,9 @@ void low_init_threads_disable(void)
  *! memory structures, since those are only destructed by the periodic
  *! gc. (This advice applies to mutex locks in general, for that
  *! matter.)
+ *!
+ *! @seealso
+ *!   @[gethrdtime()]
  */
 void init_threads_disable(struct object *UNUSED(o))
 {