On Tue, Sep 22, 2026 at 09:17:19PM +0100, Stuart Henderson wrote:
> On 2026/09/22 21:04, Kirill A. Korinsky wrote:
> > Well, check-shlib-syms states that here no difference... probably
> > SHARED_LIBS really doesn't need a bump.
> 
> it seemed that way to me (and I was quite happy to get rid of all those
> patches!).
> 
> > Anyway, here a diff which a bit hacky and fixes regression in tdesktop and
> > 64gram, and I think in other similar places.
> 
> > Thoughts?
> 
> thanks, that makes sense. ok.

This looks like a more appropraite fix.


Index: Makefile
===================================================================
RCS file: /cvs/ports/devel/libdispatch/Makefile,v
retrieving revision 1.13
diff -u -p -u -p -r1.13 Makefile
--- Makefile    22 Sep 2026 20:26:42 -0000      1.13
+++ Makefile    23 Sep 2026 22:24:43 -0000
@@ -2,7 +2,7 @@ COMMENT =       support for concurrent code ex
 
 PKGNAME =      libdispatch-$V
 V =            6.4.0
-REVISION =     0
+REVISION =     1
 
 GH_ACCOUNT =   apple
 GH_PROJECT =   swift-corelibs-libdispatch
Index: patches/patch-src_event_event_config_h
===================================================================
RCS file: patches/patch-src_event_event_config_h
diff -N patches/patch-src_event_event_config_h
--- patches/patch-src_event_event_config_h      22 Sep 2026 20:26:42 -0000      
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,18 +0,0 @@
-https://github.com/swiftlang/swift-corelibs-libdispatch/pull/960
-
-Index: src/event/event_config.h
---- src/event/event_config.h.orig
-+++ src/event/event_config.h
-@@ -116,9 +116,10 @@
- #     define NOTE_FUNLOCK 0x00000100
- #     endif
- 
--// FreeBSD's kevent does not support those
-+// FreeBSD's and OpenBSD's kevent does not support those
-+// OpenBSD's NOTE_ABSTIME uses CLOCK_REALTIME
- #     ifndef NOTE_ABSOLUTE
--#             ifdef NOTE_ABSTIME
-+#             if defined(NOTE_ABSTIME) && !defined(__OpenBSD__)
- #                     define NOTE_ABSOLUTE NOTE_ABSTIME
- #             else
- #                     define NOTE_ABSOLUTE 0
Index: patches/patch-src_event_event_kevent_c
===================================================================
RCS file: patches/patch-src_event_event_kevent_c
diff -N patches/patch-src_event_event_kevent_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_event_event_kevent_c      23 Sep 2026 22:24:43 -0000
@@ -0,0 +1,41 @@
+- Use relative kqueue deadlines for BSD uptime and monotonic timers
+  https://github.com/swiftlang/swift-corelibs-libdispatch/pull/943
+
+Index: src/event/event_kevent.c
+--- src/event/event_kevent.c.orig
++++ src/event/event_kevent.c
+@@ -60,10 +60,22 @@ DISPATCH_STATIC_GLOBAL(struct dispatch_muxnote_bucket_
+ #define DISPATCH_NOTE_CLOCK_UPTIME    0
+ #endif
+ 
++#if defined(__FreeBSD__) || defined(__OpenBSD__)
++// BSD NOTE_ABSTIME deadlines use CLOCK_REALTIME.
++#define DISPATCH_NOTE_ABSOLUTE_WALL      NOTE_ABSOLUTE
++#define DISPATCH_NOTE_ABSOLUTE_MONOTONIC 0
++#define DISPATCH_NOTE_ABSOLUTE_UPTIME    0
++#else
++#define DISPATCH_NOTE_ABSOLUTE_WALL      NOTE_ABSOLUTE
++#define DISPATCH_NOTE_ABSOLUTE_MONOTONIC NOTE_ABSOLUTE
++#define DISPATCH_NOTE_ABSOLUTE_UPTIME    NOTE_ABSOLUTE
++#endif
++
+ static const uint32_t _dispatch_timer_index_to_fflags[] = {
+ #define DISPATCH_TIMER_FFLAGS_INIT(kind, qos, note) \
+       [DISPATCH_TIMER_INDEX(DISPATCH_CLOCK_##kind, DISPATCH_TIMER_QOS_##qos)] 
= \
+-                      DISPATCH_NOTE_CLOCK_##kind | NOTE_ABSOLUTE | 
NOTE_LEEWAY | (note)
++      DISPATCH_NOTE_CLOCK_##kind | DISPATCH_NOTE_ABSOLUTE_##kind | \
++      NOTE_LEEWAY | (note)
+       DISPATCH_TIMER_FFLAGS_INIT(WALL, NORMAL, 0),
+       DISPATCH_TIMER_FFLAGS_INIT(UPTIME, NORMAL, 0),
+       DISPATCH_TIMER_FFLAGS_INIT(MONOTONIC, NORMAL, 0),
+@@ -2406,6 +2418,10 @@ _dispatch_event_loop_timer_arm(dispatch_timer_heap_t d
+       }
+ #if !NOTE_ABSOLUTE
+       target = range.delay;
++#elif defined(__FreeBSD__) || defined(__OpenBSD__)
++      if (clock != DISPATCH_CLOCK_WALL) {
++              target -= _dispatch_time_now_cached(clock, nows);
++      }
+ #endif
+ 
+       _dispatch_event_loop_timer_program(dth, tidx, target, range.leeway,
Index: patches/patch-tests_CMakeLists_txt
===================================================================
RCS file: patches/patch-tests_CMakeLists_txt
diff -N patches/patch-tests_CMakeLists_txt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-tests_CMakeLists_txt  23 Sep 2026 22:24:43 -0000
@@ -0,0 +1,17 @@
+- Use relative kqueue deadlines for BSD uptime and monotonic timers
+  https://github.com/swiftlang/swift-corelibs-libdispatch/pull/943
+
+Index: tests/CMakeLists.txt
+--- tests/CMakeLists.txt.orig
++++ tests/CMakeLists.txt
+@@ -140,6 +140,10 @@ set(DISPATCH_C_TESTS
+     io_pipe_close
+     select)
+ 
++if(UNIX)
++  list(APPEND DISPATCH_C_TESTS timer_idle)
++endif()
++
+ # Tests that usually pass, but occasionally fail.
+ # Excluded by default for purposes of Swift CI
+ if(EXTENDED_TEST_SUITE)
Index: patches/patch-tests_dispatch_timer_idle_c
===================================================================
RCS file: patches/patch-tests_dispatch_timer_idle_c
diff -N patches/patch-tests_dispatch_timer_idle_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-tests_dispatch_timer_idle_c   23 Sep 2026 22:24:43 -0000
@@ -0,0 +1,157 @@
+- Use relative kqueue deadlines for BSD uptime and monotonic timers
+  https://github.com/swiftlang/swift-corelibs-libdispatch/pull/943
+
+Index: tests/dispatch_timer_idle.c
+--- tests/dispatch_timer_idle.c.orig
++++ tests/dispatch_timer_idle.c
+@@ -0,0 +1,150 @@
++/*
++ * This source file is part of the Swift.org open source project
++ *
++ * Copyright (c) 2026 Apple Inc. and the Swift project authors
++ *
++ * Licensed under Apache License v2.0 with Runtime Library Exception
++ *
++ * See https://swift.org/LICENSE.txt for license information
++ * See https://swift.org/CONTRIBUTORS.txt for the list of Swift project 
authors
++ *
++ */
++
++#include <dispatch/dispatch.h>
++
++#include <bsdtests.h>
++#include "dispatch_test.h"
++
++#include <errno.h>
++#include <stdatomic.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/resource.h>
++#include <time.h>
++
++#define OBSERVATION_SECONDS 0.25
++#define MAX_IDLE_CPU_RATIO 0.20
++
++static _Atomic int timer_fired;
++static volatile uint64_t spin_sink;
++
++static void
++monotonic_now(struct timespec *value)
++{
++      if (clock_gettime(CLOCK_MONOTONIC, value) != 0) {
++      perror("clock_gettime");
++              exit(EXIT_FAILURE);
++      }
++}
++
++static double
++seconds_between(struct timespec start, struct timespec end)
++{
++      return (double)(end.tv_sec - start.tv_sec) +
++              (double)(end.tv_nsec - start.tv_nsec) / (double)NSEC_PER_SEC;
++}
++
++static double
++timeval_seconds(struct timeval value)
++{
++      return (double)value.tv_sec +
++              (double)value.tv_usec / (double)USEC_PER_SEC;
++}
++
++static double
++process_cpu_seconds(void)
++{
++      struct rusage usage;
++
++      if (getrusage(RUSAGE_SELF, &usage) != 0) {
++              perror("getrusage");
++              exit(EXIT_FAILURE);
++      }
++      return timeval_seconds(usage.ru_utime) + 
timeval_seconds(usage.ru_stime);
++}
++
++static double
++measure_busy_cpu_ratio(void)
++{
++      struct timespec wall_start, wall_now;
++      double cpu_start, cpu_end;
++
++      monotonic_now(&wall_start);
++      cpu_start = process_cpu_seconds();
++      do {
++              spin_sink++;
++              monotonic_now(&wall_now);
++      } while (seconds_between(wall_start, wall_now) < OBSERVATION_SECONDS);
++      cpu_end = process_cpu_seconds();
++
++      return (cpu_end - cpu_start) / seconds_between(wall_start, wall_now);
++}
++
++static void
++unexpected_timer_fire(void *context)
++{
++      (void)context;
++      atomic_store_explicit(&timer_fired, 1, memory_order_relaxed);
++}
++
++static void
++observe_idle_timer(double *wall_seconds, double *cpu_seconds)
++{
++      struct timespec wall_start, wall_end;
++      struct timespec remaining = {
++              .tv_sec = 0,
++              .tv_nsec = (long)(OBSERVATION_SECONDS * (double)NSEC_PER_SEC),
++      };
++      dispatch_source_t timer;
++      double cpu_start;
++      int sleep_result;
++
++      timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
++                      
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
++      test_ptr_notnull("dispatch_source_create", timer);
++      dispatch_source_set_event_handler_f(timer, unexpected_timer_fire);
++      dispatch_source_set_timer(timer,
++                      dispatch_time(DISPATCH_TIME_NOW, 3600 * NSEC_PER_SEC),
++                      DISPATCH_TIME_FOREVER, 0);
++      dispatch_resume(timer);
++
++      monotonic_now(&wall_start);
++      cpu_start = process_cpu_seconds();
++      do {
++              sleep_result = nanosleep(&remaining, &remaining);
++      } while (sleep_result == -1 && errno == EINTR);
++      if (sleep_result != 0) {
++              perror("nanosleep");
++              exit(EXIT_FAILURE);
++      }
++      *cpu_seconds = process_cpu_seconds() - cpu_start;
++      monotonic_now(&wall_end);
++      *wall_seconds = seconds_between(wall_start, wall_end);
++
++      dispatch_source_cancel(timer);
++      dispatch_release(timer);
++}
++
++int
++main(void)
++{
++      double busy_cpu_ratio, idle_wall_seconds, idle_cpu_seconds;
++      double idle_cpu_ratio, relative_cpu_ratio;
++
++      dispatch_test_start("Dispatch idle timer CPU usage");
++
++      busy_cpu_ratio = measure_busy_cpu_ratio();
++      observe_idle_timer(&idle_wall_seconds, &idle_cpu_seconds);
++      idle_cpu_ratio = idle_cpu_seconds / idle_wall_seconds;
++      relative_cpu_ratio = idle_cpu_ratio / busy_cpu_ratio;
++
++      fprintf(stderr, "idle=%f busy=%f relative=%f\n",
++                      idle_cpu_ratio, busy_cpu_ratio, relative_cpu_ratio);
++      test_long("timer fired", atomic_load_explicit(&timer_fired,
++                      memory_order_relaxed), 0);
++      test_double_less_than("idle timer CPU ratio", relative_cpu_ratio,
++                      MAX_IDLE_CPU_RATIO);
++      test_stop();
++      return 0;
++}

Reply via email to