- A Java- / .NET-like monitor - 14 Updates
| Bonita Montero <Bonita.Montero@gmail.com>: Nov 16 03:59AM +0100 Am 15.11.2023 um 21:08 schrieb Chris M. Thomasson: > Are you sure its 100% atomic for use in multi-thread sync algorithms? If MSVC generates that code it's atomic. |
| Bonita Montero <Bonita.Montero@gmail.com>: Nov 16 04:00AM +0100 Am 15.11.2023 um 21:21 schrieb Chris M. Thomasson: > Correction? Just post the 100% finished code in a brand new thread. I've postet everything that is necessary, you only have to add a "!". |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Nov 15 07:10PM -0800 On 11/15/2023 7:00 PM, Bonita Montero wrote: > Am 15.11.2023 um 21:21 schrieb Chris M. Thomasson: >> Correction? Just post the 100% finished code in a brand new thread. > I've postet everything that is necessary, you only have to add a "!". Wow... Anyway, where do I add this "!"? |
| Kaz Kylheku <864-117-4973@kylheku.com>: Nov 16 03:21AM >>> Correction? Just post the 100% finished code in a brand new thread. >> I've postet everything that is necessary, you only have to add a "!". > Wow... Anyway, where do I add this "!"? I would guess, in front of "necessary". |
| Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo>: Nov 15 11:07PM -0500 Chris M. Thomasson wrote: >> according to the spec. > Just as long as the implementation works wrt calling > pthread_cond_signal/broadcast outside of the mutex. If not, it is broken. I am unsure where from that discussion of implementation came. The *spec* permits this (signalling without holding the mutex), just warns that a predictable scheduling behavior cannot be achieved then. What would you consider an example of a "non-working" implementation? Does my example that illustrates how a higher-prio thread may never make progress is of a broken implementation in your opinion? |
| Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo>: Nov 16 12:25AM -0500 Kaz Kylheku wrote: > concrete requirements about what it is that I'm supposed to do in > pthread_cond_signal to bring about more predictable scheduling. > Specifications should give specific requirements, not vague opinions. POSIX *specifies* exactly what scheduling policies a compliant implementation shall support (SCHED_OTHER, SCHED_FIFO, SCHED_RR, and SCHED_SPORADIC) and how exactly each of these shall behave. In addition to specifying the behavior, the spec *explains* the purpose of some policies so programmers would know when they were meant to be used. Explanations are there to be helpful, they are not specs. In C++ Standard, they would be formatted as a non-normative Notes. For example, SCHED_RR, under some conditions, has an effect "to ensure.. that one of them [the threads] does not monopolize the processor". To me, this is clearly an example of "predictable scheduling behavior". The spec for pthread_cond_signal and broadast further simply adds one more condition required to achieve such behavior, namely "the signalling thread owns the mutex that the waiter threads used to start waiting". If your doesn't need a predictable scheduling behavior, your app doesn't have to do that. For an implementer, this statement is actually very useful: it permits them to not ensure "predictable scheduling behavior" when the cond waiter is signaled from a thread not owning the mutex. Could this statement be thrown away? -- Yes. Would this make implementor's life easier? -- No, it would make it much harder. The implementor could be bugged by the user complaints like "Your implementation must be broken, else why my higher-prio thread is starving?". With the current spec, they could answer: "This is because the spec allows my implementation to starve your higher-prio thread to death -- or exhibit any other unpredictable scheduling behavior -- if your condvar-signalling thread does not own the mutex that the higher-prio thread used to start waiting for the condvar". |
| Bonita Montero <Bonita.Montero@gmail.com>: Nov 16 06:36AM +0100 Am 16.11.2023 um 04:10 schrieb Chris M. Thomasson: > Wow... Anyway, where do I add this "!"? You don't have to change it because the Windows code was correct anyway. |
| Kaz Kylheku <864-117-4973@kylheku.com>: Nov 16 06:39AM > I am unsure where from that discussion of implementation came. The > *spec* permits this (signalling without holding the mutex), just warns > that a predictable scheduling behavior cannot be achieved then. The spec is supposed to tell implementors what to make. Loose wording like this is dangerous. An implementor is free to interpret it like this: whenever a program calls pthread_cond_signal, and it so happens that the calling threads owns no mutex whatsoever, the implementation is free to set a flag somewhere, based on which it will willfully damage the integrity of the scheduling implementation somehow, so that it behaves like crap. -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal Mastodon: @Kazinator@mstdn.ca NOTE: If you use Google Groups, I don't see you, unless you're whitelisted. |
| Bonita Montero <Bonita.Montero@gmail.com>: Nov 16 11:11AM +0100 Am 13.11.2023 um 05:50 schrieb Kaz Kylheku: > is still holding. So, oops, back it goes into suspended state, and > we have to context switch to the mutex holder which has to release > the mutex and then switch to that signaled thread again. As I've shown with the comparison of my monitor against a C++ mutex along with a condition variable there are no additional context swit- ches with that. The number of voluntary context switches is about the same as with my monitor, which comprehensibly waits for the mutex and the condition variable in one step. As the mutex part and the condition variable part are separate there's no opportunity to implement that the way I did with a SysV semaphore set. I guess the backing of the mutex and condition variable on Linux is the glibc-implementation and it uses signals for that as when you use a pure mutex; with that you can have an aribitrary state combina- tion to wake up a thread even if the states are managed separately as with a mutex and a condition variable. I simulated that with the follwing code: #include <iostream> #include <thread> #include <vector> #include <pthread.h> #include <sys/resource.h> using namespace std; int main() { constexpr size_t ROUNDS = 1'000; struct state { pthread_mutex_t mtx; pthread_cond_t cv; } a, b; auto init = []( state &s ) { if( pthread_mutex_init( &s.mtx, nullptr ) || pthread_cond_init( &s.cv, nullptr ) ) terminate(); }; init( a ); init( b ); auto switches = []() { rusage ru; if( getrusage( RUSAGE_THREAD, &ru ) ) terminate(); return ru.ru_nvcsw; }; atomic_uint64_t sumSwitches( 0 ); auto thr = [&]( state &my, state &yours ) { uint64_t before = switches(); for( size_t r = ROUNDS; r--; ) if( pthread_mutex_lock( &my.mtx ) || pthread_cond_wait( &my.cv, &my.mtx ) || pthread_mutex_unlock( &my.mtx ) || pthread_mutex_lock( &yours.mtx ) || pthread_cond_signal( &yours.cv ) || pthread_mutex_unlock( &yours.mtx ) ) terminate(); sumSwitches.fetch_add( switches() - before, memory_order_relaxed ); }; vector<jthread> threads; threads.emplace_back( thr, ref( a ), ref( b ) ); threads.emplace_back( thr, ref( b ), ref( a ) ); if( pthread_cond_signal( &a.cv ) ) terminate(); threads.resize( 0 ); cout << sumSwitches << endl; } The result is about 2'000 voluntary context switches. So no need to signal from outside. |
| scott@slp53.sl.home (Scott Lurndal): Nov 16 03:02PM >Am 15.11.2023 um 21:08 schrieb Chris M. Thomasson: >> Are you sure its 100% atomic for use in multi-thread sync algorithms? >If MSVC generates that code it's atomic. No, if Intel architecture documentation specifies that it is single-copy atomic, then it is single-copy atomic. MSVC is just a poor-to-middling C compiler. |
| Bonita Montero <Bonita.Montero@gmail.com>: Nov 16 06:12PM +0100 Am 16.11.2023 um 16:02 schrieb Scott Lurndal: >> If MSVC generates that code it's atomic. > No, if Intel architecture documentation specifies that it is > single-copy atomic, then it is single-copy atomic. MSVC relies for sure on the right behaviour. > MSVC is just a poor-to-middling C compiler. MSVC has the strongest C++20-conformance but the weakest optimizer. |
| scott@slp53.sl.home (Scott Lurndal): Nov 16 05:45PM >> No, if Intel architecture documentation specifies that it is >> single-copy atomic, then it is single-copy atomic. >MSVC relies for sure on the right behaviour. Right. Keep thinking that. >> MSVC is just a poor-to-middling C compiler. >MSVC has the strongest C++20-conformance but the weakest optimizer. Faint praise, indeed. Nobody other than Herb cares about C++20 conformance. Most real world C++ code relies on C++11 for portability. Most of our systems and our customers systems don't even support C++17. |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Nov 16 01:06PM -0800 On 11/15/2023 9:36 PM, Bonita Montero wrote: >> Wow... Anyway, where do I add this "!"? > You don't have to change it because the Windows code was correct > anyway. Huh? Do I have to correct your code with that "!" or not? |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Nov 16 02:16PM -0800 On 11/12/2023 4:44 PM, Chris M. Thomasson wrote: > signalling thread, instant contention. However, wait morphing techniques > can be used to handle this since a mutex and a condvar are very intimate > with each other anyway. Usually, signalling outside of the mutex is ideal. Actually, for some damn reason this is making me think about the pass-the-buck algorithm, iirc, its from SUN. A signal to a thread means the signaled thread already owns the mutex. |
| You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment