Skip to content

Commit 758742c

Browse files
committed
databases/mongodb80: reimplement waitable_atomic.cpp
Reimplement src/mongo/platform/waitable_atomic.cpp using absolute time. This uses more simple conversions. The implementation is now similar to the Linux version instead of the MacOS version. It should not have any functional change. Reported by: https://infosec.exchange/@david_chisnall/113797905538197081 Reported by: mongodb/mongo#1607 (comment)
1 parent 3e36c6b commit 758742c

File tree

2 files changed

+27
-34
lines changed

2 files changed

+27
-34
lines changed

databases/mongodb80/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PORTNAME= mongodb
22
DISTVERSIONPREFIX= r
33
DISTVERSION= 8.0.4
4-
PORTREVISION= 2
4+
PORTREVISION= 3
55
CATEGORIES= databases net
66
MASTER_SITES= https://hg.mozilla.org/mozilla-central/raw-rev/:patches
77
PKGNAMESUFFIX= ${DISTVERSION:R:S/.//}
Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
--- src/mongo/platform/waitable_atomic.cpp.orig 2024-07-23 11:53:14 UTC
1+
--- src/mongo/platform/waitable_atomic.cpp.orig 2024-11-20 23:53:48 UTC
22
+++ src/mongo/platform/waitable_atomic.cpp
33
@@ -34,6 +34,9 @@
44
#ifdef __linux__
@@ -10,56 +10,49 @@
1010
#elif defined(_WIN32)
1111
#include <synchapi.h>
1212
#endif
13-
@@ -228,6 +231,52 @@ bool waitUntil(const void* uaddr,
14-
}
15-
16-
if (__ulock_wait(UL_COMPARE_AND_WAIT, const_cast<void*>(uaddr), old, timeoutMicros) != -1)
17-
+ return true;
18-
+
19-
+ // There isn't a good list of possible errors, so assuming that anything other than a timeout
20-
+ // error is a possible spurious wakeup.
21-
+ return timeoutOverflow || errno != ETIMEDOUT;
13+
@@ -233,6 +236,45 @@ bool waitUntil(const void* uaddr,
14+
// There isn't a good list of possible errors, so assuming that anything other than a timeout
15+
// error is a possible spurious wakeup.
16+
return timeoutOverflow || errno != ETIMEDOUT;
2217
+}
2318
+
2419
+#elif defined(__FreeBSD__)
2520
+
2621
+void notifyOne(const void* uaddr) {
27-
+ _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE, 1, NULL, NULL);
22+
+ _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE_PRIVATE, 1, NULL, NULL);
2823
+}
2924
+
3025
+void notifyMany(const void* uaddr, int nToWake) {
31-
+ _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE, nToWake, NULL, NULL);
26+
+ _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE_PRIVATE, nToWake, NULL, NULL);
3227
+}
3328
+
3429
+void notifyAll(const void* uaddr) {
35-
+ _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE, INT_MAX, NULL, NULL);
30+
+ _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE_PRIVATE, INT_MAX, NULL, NULL);
3631
+}
3732
+
3833
+bool waitUntil(const void* uaddr,
3934
+ uint32_t old,
4035
+ boost::optional<system_clock::time_point> deadline) {
41-
+ struct timespec timeout;
42-
+ bool timeoutOverflow = false;
36+
+ struct _umtx_time umtx_deadline;
37+
+ void* uaddr2 = nullptr;
38+
+
4339
+ if (deadline) {
44-
+ int64_t micros = durationCount<Microseconds>(*deadline - system_clock::now());
45-
+ if (micros <= 0) {
46-
+ return false; // Synthesize a timeout.
47-
+ }
40+
+ umtx_deadline._timeout.tv_sec = durationCount<Seconds>(deadline->time_since_epoch());
41+
+ umtx_deadline._timeout.tv_nsec = durationCount<Nanoseconds>(
42+
+ deadline->time_since_epoch() - stdx::chrono::seconds(umtx_deadline._timeout.tv_sec));
43+
+ umtx_deadline._flags = UMTX_ABSTIME;
44+
+ umtx_deadline._clockid = CLOCK_REALTIME_FAST;
45+
+ uaddr2 = &umtx_deadline;
46+
+ }
4847
+
49-
+ if (micros > int64_t(std::numeric_limits<uint32_t>::max())) {
50-
+ // 2**32 micros is a little over an hour. If this happens, we wait as long as we can,
51-
+ // then return as-if a spurious wakeup happened, rather than a timeout. This will cause
52-
+ // the caller to loop and we will compute a smaller time each pass, eventually reaching
53-
+ // a representable timeout.
54-
+ micros = std::numeric_limits<uint32_t>::max();
55-
+ timeoutOverflow = true;
48+
+ int umtxOpRet;
49+
+ if ((umtxOpRet = _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAIT_UINT_PRIVATE, old, (void*)sizeof(struct _umtx_time), uaddr2)) != 0) {
50+
+ if (errno == ETIMEDOUT) {
51+
+ return false;
5652
+ }
57-
+
58-
+ timeout.tv_sec = micros / 1000;
59-
+ timeout.tv_nsec = (micros % 1000) * 1000;
53+
+ invariant(umtxOpRet == 0, errorMessage(lastSystemError()));
6054
+ }
61-
+
62-
+ if (_umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAIT, old, (void*)sizeof(struct timespec), &timeout) != -1)
63-
return true;
55+
+ return true;
56+
}
6457

65-
// There isn't a good list of possible errors, so assuming that anything other than a timeout
58+
#else

0 commit comments

Comments
 (0)