Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Jul 2024 18:09:11 +0200 (CEST)
From:      Ronald Klop <ronald-lists@klop.ws>
To:        freebsd-ports@freebsd.org
Cc:        Michael Gmelin <grembo@freebsd.org>
Subject:   Re: advice for implementing an atomics wrapper
Message-ID:  <649335513.7189.1721750951946@localhost>
In-Reply-To: <E0DA696F-F74E-4E93-B34F-3646169C3DBC@freebsd.org>
References:  <1711627700.7093.1721744204825@localhost> <E0DA696F-F74E-4E93-B34F-3646169C3DBC@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
------=_Part_7188_792930881.1721750951921
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

The __APPLE__ implementation also pointed to the implementation in that file and I used it to come up with a patch.

#elif defined(__FreeBSD__)

void notifyOne(const void* uaddr) {
    _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE, 1, NULL, NULL);
}

void notifyMany(const void* uaddr, int nToWake) {
    _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE, nToWake, NULL, NULL);
}

void notifyAll(const void* uaddr) {
    _umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAKE, INT_MAX, NULL, NULL);
}

bool waitUntil(const void* uaddr,
               uint32_t old,
               boost::optional<system_clock::time_point> deadline) {
    struct timespec timeout;
    bool timeoutOverflow = false;
    if (deadline) {
        int64_t micros = durationCount<Microseconds>(*deadline - system_clock::now());
        if (micros <= 0) {
            return false;  // Synthesize a timeout.
        }

        if (micros > int64_t(std::numeric_limits<uint32_t>::max())) {
            // 2**32 micros is a little over an hour. If this happens, we wait as long as we can,
            // then return as-if a spurious wakeup happened, rather than a timeout. This will cause
            // the caller to loop and we will compute a smaller time each pass, eventually reaching
            // a representable timeout.
            micros = std::numeric_limits<uint32_t>::max();
            timeoutOverflow = true;
        }

        timeout.tv_sec = micros / 1000;
        timeout.tv_nsec = (micros % 1000) * 1000;
    }

    if (_umtx_op(const_cast<void*>(uaddr), UMTX_OP_WAIT, old, (void*)sizeof(struct timespec), &timeout) != -1)
        return true;

    // There isn't a good list of possible errors, so assuming that anything other than a timeout
    // error is a possible spurious wakeup.
    return timeoutOverflow || errno != ETIMEDOUT;
}


It compiles and runs in my simple tests (although I don't know if my simple tests execute this part of mongodb code). Suggestions are of course welcome.

Regards,
Ronald.

 
Van: Michael Gmelin <grembo@freebsd.org>
Datum: dinsdag, 23 juli 2024 17:32
Aan: Ronald Klop <ronald-lists@klop.ws>
Onderwerp: Re: advice for implementing an atomics wrapper
> 
>  
> Does this help?
>  
> https://reviews.llvm.org/D142134
>  
>  
>> On 23. Jul 2024, at 16:17, Ronald Klop <ronald-lists@klop.ws> wrote:
>>  > 
>> 
>> Sorry,
>> 
>> Something broke the pasted URL.
>> https://github.com/mongodb/mongo/blob/master/src/mongo/platform/waitable_atomic.cpp
>> 
>> Another attempt.
>> 
>> Ronald.
>>  
>> Van: Ronald Klop <ronald-lists@klop.ws>
>> Datum: dinsdag, 23 juli 2024 16:14
>> Aan: freebsd-ports@freebsd.org
>> Onderwerp: advice for implementing an atomics wrapper
>>> 
>>> Hi,
>>> 
>>> For mongodb 8.0 I need to give a FreeBSD implementation of this file.
>>> 
>>> https://github.com/mongodb/mongo/blob/master/src/mongo/platform/waitable_atomic.cpp
>>> 
>>> Using the __Apple__ definition gives:
>>> ld.lld: error: undefined symbol: __ulock_wake
>>> ld.lld: error: undefined symbol: __ulock_wait
>>> 
>>> And the __linux__ definition uses futex which FreeBSD does not have AFAIK.
>>> 
>>> What is an easy way to port this file?
>>> 
>>> Regards,
>>> Ronald.
>>>  
>> 
>>  
> 

 
------=_Part_7188_792930881.1721750951921
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<html><head></head><body>Hi,<br>
<br>
The __APPLE__ implementation also pointed to the implementation in that file and I used it to come up with a patch.<br>
<br>
#elif defined(__FreeBSD__)<br>
<br>
void notifyOne(const void* uaddr) {<br>
&nbsp;&nbsp;&nbsp; _umtx_op(const_cast&lt;void*&gt;(uaddr), UMTX_OP_WAKE, 1, NULL, NULL);<br>
}<br>
<br>
void notifyMany(const void* uaddr, int nToWake) {<br>
&nbsp;&nbsp;&nbsp; _umtx_op(const_cast&lt;void*&gt;(uaddr), UMTX_OP_WAKE, nToWake, NULL, NULL);<br>
}<br>
<br>
void notifyAll(const void* uaddr) {<br>
&nbsp;&nbsp;&nbsp; _umtx_op(const_cast&lt;void*&gt;(uaddr), UMTX_OP_WAKE, INT_MAX, NULL, NULL);<br>
}<br>
<br>
bool waitUntil(const void* uaddr,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint32_t old,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boost::optional&lt;system_clock::time_point&gt; deadline) {<br>
&nbsp;&nbsp;&nbsp; struct timespec timeout;<br>
&nbsp;&nbsp;&nbsp; bool timeoutOverflow = false;<br>
&nbsp;&nbsp;&nbsp; if (deadline) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int64_t micros = durationCount&lt;Microseconds&gt;(*deadline - system_clock::now());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (micros &lt;= 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp; // Synthesize a timeout.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (micros &gt; int64_t(std::numeric_limits&lt;uint32_t&gt;::max())) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 2**32 micros is a little over an hour. If this happens, we wait as long as we can,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // then return as-if a spurious wakeup happened, rather than a timeout. This will cause<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // the caller to loop and we will compute a smaller time each pass, eventually reaching<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // a representable timeout.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; micros = std::numeric_limits&lt;uint32_t&gt;::max();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeoutOverflow = true;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout.tv_sec = micros / 1000;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout.tv_nsec = (micros % 1000) * 1000;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; if (_umtx_op(const_cast&lt;void*&gt;(uaddr), UMTX_OP_WAIT, old, (void*)sizeof(struct timespec), &amp;timeout) != -1)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>
<br>
&nbsp;&nbsp;&nbsp; // There isn't a good list of possible errors, so assuming that anything other than a timeout<br>
&nbsp;&nbsp;&nbsp; // error is a possible spurious wakeup.<br>
&nbsp;&nbsp;&nbsp; return timeoutOverflow || errno != ETIMEDOUT;<br>
}<br>
<br>
<br>
It compiles and runs in my simple tests (although I don't know if my simple tests execute this part of mongodb code). Suggestions are of course welcome.<br>
<br>
Regards,<br>
Ronald.<br>
<br>
&nbsp;
<p><strong>Van:</strong> Michael Gmelin &lt;grembo@freebsd.org&gt;<br>
<strong>Datum:</strong> dinsdag, 23 juli 2024 17:32<br>
<strong>Aan:</strong> Ronald Klop &lt;ronald-lists@klop.ws&gt;<br>
<strong>Onderwerp:</strong> Re: advice for implementing an atomics wrapper</p>

<blockquote style="padding-right: 0px; padding-left: 5px; margin-left: 5px; border-left: #000000 2px solid; margin-right: 0px">
<div class="MessageRFC822Viewer" id="P">
<div class="MultipartAlternativeViewer">
<div class="TextHTMLViewer" id="P.P.P">
<div>&nbsp;</div>

<div>Does this help?</div>

<div>&nbsp;</div>

<div><a href="https://reviews.llvm.org/D142134">https://reviews.llvm.org/D142134</a></div>;

<div>&nbsp;
<div>&nbsp;</div>

<blockquote>On 23. Jul 2024, at 16:17, Ronald Klop &lt;ronald-lists@klop.ws&gt; wrote:<br>
&nbsp;</blockquote>
</div>

<blockquote>
<div>Sorry,<br>
<br>
Something broke the pasted URL.<br>
<a href="https://github.com/mongodb/mongo/blob/master/src/mongo/platform/waitable_atomic.cpp">https://github.com/mongodb/mongo/blob/master/src/mongo/platform/waitable_atomic.cpp</a><br>;
<br>
Another attempt.<br>
<br>
Ronald.<br>
&nbsp;
<p><strong>Van:</strong> Ronald Klop &lt;ronald-lists@klop.ws&gt;<br>
<strong>Datum:</strong> dinsdag, 23 juli 2024 16:14<br>
<strong>Aan:</strong> freebsd-ports@freebsd.org<br>
<strong>Onderwerp:</strong> advice for implementing an atomics wrapper</p>

<blockquote style="padding-right: 0px; padding-left: 5px; margin-left: 5px; border-left: #000000 2px solid; margin-right: 0px">
<div class="MessageRFC822Viewer" id="P">
<div class="MultipartAlternativeViewer">
<div class="TextHTMLViewer" id="P.P.P">Hi,<br>
<br>
For mongodb 8.0 I need to give a FreeBSD implementation of this file.<br>
<br>
<a href="https://github.com/mongodb/mongo/blob/master/src/mongo/platform/waitable_atomic.cpp">https://github.com/mongodb/mongo/blob/master/src/mongo/platform/waitable_atomic.cpp</a><br>;
<br>
Using the __Apple__ definition gives:<br>
ld.lld: error: undefined symbol: __ulock_wake<br>
ld.lld: error: undefined symbol: __ulock_wait<br>
<br>
And the __linux__ definition uses futex which FreeBSD does not have AFAIK.<br>
<br>
What is an easy way to port this file?<br>
<br>
Regards,<br>
Ronald.<br>
&nbsp;</div>
</div>
</div>
</blockquote>
<br>
&nbsp;</div>
</blockquote>
</div>
</div>
</div>
</blockquote>
<br>
&nbsp;</body></html>
------=_Part_7188_792930881.1721750951921--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?649335513.7189.1721750951946>