diff --git a/src/mongo/platform/waitable_atomic.cpp b/src/mongo/platform/waitable_atomic.cpp index 36e85fe6dfaa5..b62f52738873f 100644 --- a/src/mongo/platform/waitable_atomic.cpp +++ b/src/mongo/platform/waitable_atomic.cpp @@ -34,6 +34,9 @@ #ifdef __linux__ #include #include +#elif defined(__FreeBSD__) +#include +#include #elif defined(_WIN32) #include #endif @@ -235,6 +238,45 @@ bool waitUntil(const void* uaddr, return timeoutOverflow || errno != ETIMEDOUT; } +#elif defined(__FreeBSD__) + +void notifyOne(const void* uaddr) { + _umtx_op(const_cast(uaddr), UMTX_OP_WAKE_PRIVATE, 1, NULL, NULL); +} + +void notifyMany(const void* uaddr, int nToWake) { + _umtx_op(const_cast(uaddr), UMTX_OP_WAKE_PRIVATE, nToWake, NULL, NULL); +} + +void notifyAll(const void* uaddr) { + _umtx_op(const_cast(uaddr), UMTX_OP_WAKE_PRIVATE, INT_MAX, NULL, NULL); +} + +bool waitUntil(const void* uaddr, + uint32_t old, + boost::optional deadline) { + struct _umtx_time umtx_deadline; + void* uaddr2 = nullptr; + + if (deadline) { + umtx_deadline._timeout.tv_sec = durationCount(deadline->time_since_epoch()); + umtx_deadline._timeout.tv_nsec = durationCount( + deadline->time_since_epoch() - stdx::chrono::seconds(umtx_deadline._timeout.tv_sec)); + umtx_deadline._flags = UMTX_ABSTIME; + umtx_deadline._clockid = CLOCK_REALTIME_FAST; + uaddr2 = &umtx_deadline; + } + + int umtxOpRet; + if ((umtxOpRet = _umtx_op(const_cast(uaddr), UMTX_OP_WAIT_UINT_PRIVATE, old, (void*)sizeof(struct _umtx_time), uaddr2)) != 0) { + if (errno == ETIMEDOUT) { + return false; + } + invariant(umtxOpRet == 0, errorMessage(lastSystemError())); + } + return true; +} + #else #error "Need an implementation of waitUntil(), notifyOne(), notifyMany(), notifyAll() for this OS" #endif