MADNESS 0.10.1
worldmutex.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30
31 $Id$
32*/
33#ifndef MADNESS_WORLD_WORLDMUTEX_H__INCLUDED
34#define MADNESS_WORLD_WORLDMUTEX_H__INCLUDED
35
36#include <atomic>
38#include <pthread.h>
39#include <thread>
40#include <cstdio>
41
42// Ensures compiler does not migrate memory instructions past the barrier --- but does NOT enforce HW ordering
43#define MADNESS_COMPILER_BARRIER std::atomic_signal_fence(std::memory_order_seq_cst)
44//#define MADNESS_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
45
46// Has effect of compiler barrier and ensures ordering of stores
47#define MADNESS_MEMORY_STORE_BARRIER std::atomic_thread_fence(std::memory_order_release)
48
49// Has effect of compiler barrier and ensures ordering of loads. A store barrier
50// on the producing side orders nothing unless the consuming side pairs it with
51// this (or with an acquire load); one-sided use is not a barrier.
52#define MADNESS_MEMORY_LOAD_BARRIER std::atomic_thread_fence(std::memory_order_acquire)
53//#if defined(__aarch64__) || defined(_M_ARM64)
54//#define MADNESS_MEMORY_STORE_BARRIER __asm__ __volatile__("dmb ish" : : : "memory")
55//#else
56//#define MADNESS_MEMORY_STORE_BARRIER __asm__ __volatile__("" : : : "memory")
57//#endif
58
59#ifdef ON_A_MAC
60#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
61
62#include <os/lock.h>
63#include <type_traits>
64
65typedef std::remove_pointer<os_unfair_lock_t>::type pthread_spinlock_t;
66
67inline void pthread_spin_init(pthread_spinlock_t* p, int /*mode*/) {
68 *p = OS_UNFAIR_LOCK_INIT;
69}
70inline int pthread_spin_trylock(pthread_spinlock_t* p) {
71 return !os_unfair_lock_trylock(p);
72}
73inline int pthread_spin_lock(pthread_spinlock_t* p) {
74 os_unfair_lock_lock(p);
75 return 0;
76}
77inline int pthread_spin_unlock(pthread_spinlock_t* p) {
78 os_unfair_lock_unlock(p);
79 return 0;
80}
81
82inline int pthread_spin_destroy(pthread_spinlock_t*) {
83 return 0;
84}
85
86#else
87
88#include <libkern/OSAtomic.h>
89typedef OSSpinLock pthread_spinlock_t;
90
91inline void pthread_spin_init(pthread_spinlock_t* p, int /*mode*/) {
92 *p=0;
93}
94inline int pthread_spin_trylock(pthread_spinlock_t* p) {
95 return !OSSpinLockTry(p);
96}
97inline int pthread_spin_lock(pthread_spinlock_t* p) {
98 OSSpinLockLock(p);
99 return 0;
100}
101inline int pthread_spin_unlock(pthread_spinlock_t* p) {
102 OSSpinLockUnlock(p);
103 return 0;
104}
105inline void pthread_spin_destroy(pthread_spinlock_t* /*p*/) {}
106#endif // __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
107#endif // ON_A_MAC
108
109
111#include <madness/world/timers.h>
114
115/// \file worldmutex.h
116/// \brief Implements Mutex, MutexFair, Spinlock, ConditionVariable
117/// \addtogroup mutexes
118///@{
119
120
121
122namespace madness {
123
124 namespace detail {
125 void print_mutex_error(int error_number);
126 }
127
129 private:
130 unsigned int count;
131
132 /// Yield for specified number of microseconds unless dedicated CPU
133 /// Blue Gene always has a dedicated hw thread
134 void yield(int us) {
135#if !defined(HAVE_IBMBGP) && !defined(HAVE_IBMBGQ)
136 myusleep(us);
137#endif
138 }
139
140 public:
142
143 void reset() { count = 0; }
144
145 void wait();
146 }; // class MutexWaiter
147
148
149 /// Mutex using pthread mutex operations
150 class Mutex {
151 private:
152 mutable pthread_mutex_t mutex;
153
154 /// Copy constructor is forbidden
155 Mutex(const Mutex&);
156
157 /// Assignment is forbidden
158 void operator=(const Mutex&);
159
160 public:
161 /// Make and initialize a mutex ... initial state is unlocked
162 Mutex(int junk=0) // Junk so that can force initializer in mraX.cc
163 {
164 const int result = pthread_mutex_init(&mutex, 0);
165 if (result) MADNESS_EXCEPTION("failed to initialize mutex", result);
166 }
167
168 /// Try to acquire the mutex ... return true on success, false on failure
169 bool try_lock() const {
170 return pthread_mutex_trylock(&mutex)==0;
171 }
172
173 /// Acquire the mutex waiting if necessary
174 void lock() const {
175 const int result = pthread_mutex_lock(&mutex);
176 if (result) {
177 fprintf(stderr, "!! MADNESS ERROR: Mutex::lock() failed acquiring mutex\n");
179 MADNESS_EXCEPTION("Mutex::lock() failed acquiring mutex", result);
180 }
181 }
182
183 /// Free a mutex owned by this thread
184 void unlock() const {
185 const int result = pthread_mutex_unlock(&mutex);
186 if (result) {
187 fprintf(stderr, "!! MADNESS ERROR: Mutex::unlock() failed releasing mutex\n");
189 MADNESS_EXCEPTION("Mutex::unlock() failed releasing mutex", result);
190 }
191 }
192
193 /// Return a pointer to the pthread mutex for use by a condition variable
194 pthread_mutex_t* ptr() const {
195 return &mutex;
196 }
197
198 virtual ~Mutex() {
199 pthread_mutex_destroy(&mutex);
200 }
201 }; // class Mutex
202
203 /// Recursive mutex using pthread mutex operations
205 private:
206 mutable pthread_mutex_t mutex;
207
208 /// Copy constructor is forbidden
210
211 /// Assignment is forbidden
213
214 public:
215 /// Make and initialize a mutex ... initial state is unlocked
217
218 /// Try to acquire the mutex ... return true on success, false on failure
219 bool try_lock() const {
220 return pthread_mutex_trylock(&mutex)==0;
221 }
222
223 /// Acquire the mutex waiting if necessary
224 void lock() const {
225 int result = pthread_mutex_lock(&mutex);
226 if (result) {
227 fprintf(stderr, "!! MADNESS ERROR: RecursiveMutex::lock() failed acquiring mutex\n");
229 MADNESS_EXCEPTION("RecursiveMutex::lock() failed acquiring mutex", result);
230 }
231 }
232
233 /// Free a mutex owned by this thread
234 void unlock() const {
235 int result = pthread_mutex_unlock(&mutex);
236 if (result) {
237 fprintf(stderr, "!! MADNESS ERROR: RecursiveMutex::unlock() failed releasing mutex\n");
239 MADNESS_EXCEPTION("RecursiveMutex::unlock() failed releasing mutex", result);
240 }
241 }
242
243 /// Return a pointer to the pthread mutex for use by a condition variable
244 pthread_mutex_t* ptr() const {
245 return &mutex;
246 }
247
249 pthread_mutex_destroy(&mutex);
250 }
251 }; // class Mutex
252
253
254 /// Mutex that is applied/released at start/end of a scope
255
256 /// The mutex must provide lock and unlock methods
257 template <class mutexT = Mutex>
259 const mutexT* mutex;
260 public:
261 ScopedMutex(const mutexT* m) : mutex(m) { mutex->lock(); }
262
263 ScopedMutex(const mutexT& m) : mutex(&m) { mutex->lock(); }
264
265 virtual ~ScopedMutex() { mutex->unlock(); }
266 }; // class ScopedMutex
267
268#ifdef NEVER_SPIN
269 typedef Mutex Spinlock;
270#else
271 /// Spinlock using pthread spinlock operations
272 class Spinlock {
273 private:
274 //mutable pthread_spinlock_t spinlock __attribute__ ((aligned (64)));
275 mutable pthread_spinlock_t spinlock;
276
277 /// Copy constructor is forbidden
279
280 /// Assignment is forbidden
281 void operator=(const Spinlock&);
282
283 public:
284 /// Make and initialize a spinlock ... initial state is unlocked
285 Spinlock(int junk=0) // Junk so that can force initializer in mraX.cc
286 {
287 pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);
288 }
289
290 /// Try to acquire the spinlock ... return true on success, false on failure
291 bool try_lock() const {
292 return pthread_spin_trylock(&spinlock)==0;
293 }
294
295 /// Acquire the spinlock waiting if necessary
296 void lock() const {
297 int result = pthread_spin_lock(&spinlock);
298 if (result) {
299 fprintf(stderr, "!! MADNESS ERROR: Spinlock::lock() failed acquiring spinlock\n");
301 MADNESS_EXCEPTION("Spinlock::lock() failed acquiring spinlock", result);
302 }
303 }
304
305 /// Free a spinlock owned by this thread
306 void unlock() const {
307 int result = pthread_spin_unlock(&spinlock);
308 if (result) {
309 fprintf(stderr, "!! MADNESS ERROR: Spinlock::unlock() failed releasing spinlock\n");
311 MADNESS_EXCEPTION("Spinlock::unlock() failed releasing spinlock", result);
312 }
313 }
314
315 virtual ~Spinlock() {
316 pthread_spin_destroy(&spinlock);
317 }
318 }; // class Spinlock
319#endif
320
321
322#define OLDXXX
323#ifdef OLDXXX
324 // This version uses a spin lock
325 class MutexReaderWriter : private Spinlock, private NO_DEFAULTS {
326 mutable int nreader; // used to be volatile but is protected by mutex and associated barriers
327 mutable bool writeflag; // ditto
328 public:
329 static const int NOLOCK=0;
330 static const int READLOCK=1;
331 static const int WRITELOCK=2;
332
334
335 bool try_read_lock() const {
336 ScopedMutex<Spinlock> protect(this);
337 bool gotit = !writeflag;
338 if (gotit) ++nreader;
339 return gotit;
340 }
341
342 bool try_write_lock() const {
343 ScopedMutex<Spinlock> protect(this);
344 bool gotit = (!writeflag) && (nreader==0);
345 if (gotit) writeflag = true;
346 return gotit;
347 }
348
349 bool try_lock(int lockmode) const {
350 if (lockmode == READLOCK) {
351 return try_read_lock();
352 }
353 else if (lockmode == WRITELOCK) {
354 return try_write_lock();
355 }
356 else if (lockmode == NOLOCK) {
357 return true;
358 }
359 else {
360 MADNESS_EXCEPTION("MutexReaderWriter: try_lock: invalid lock mode", lockmode);
361 }
362 }
363
365 ScopedMutex<Spinlock> protect(this);
366 bool gotit = (!writeflag) && (nreader==1);
367 if (gotit) {
368 nreader = 0;
369 writeflag = true;
370 }
371 return gotit;
372 }
373
374 void read_lock() const {
375 while (!try_read_lock()) cpu_relax();
376 }
377
378 void write_lock() const {
379 while (!try_write_lock()) cpu_relax();
380 }
381
382 void lock(int lockmode) const {
383 while (!try_lock(lockmode)) cpu_relax();
384 }
385
386 void read_unlock() const {
387 ScopedMutex<Spinlock> protect(this);
388 nreader--;
389 }
390
391 void write_unlock() const {
392 // Only a single thread should be setting writeflag but
393 // probably still need the mutex just to get memory fence?
394 ScopedMutex<Spinlock> protect(this);
395 writeflag = false;
396 }
397
398 void unlock(int lockmode) const {
399 if (lockmode == READLOCK) read_unlock();
400 else if (lockmode == WRITELOCK) write_unlock();
401 else if (lockmode != NOLOCK) MADNESS_EXCEPTION("MutexReaderWriter: try_lock: invalid lock mode", lockmode);
402 }
403
404 /// Converts read to write lock without releasing the read lock
405
406 /// Note that deadlock is guaranteed if two+ threads wait to convert at the same time.
410
411 /// Always succeeds immediately
413 ScopedMutex<Spinlock> protect(this);
414 ++nreader;
415 writeflag=false;
416 }
418 };
419
420#else
421
422 // This version uses AtomicInt and CAS
423 class MutexReaderWriter : private NO_DEFAULTS {
424 mutable AtomicInt nreader;
425 mutable AtomicInt writeflag;
426 enum {UNLOCKED, LOCKED};
427
428 public:
429 enum lockT {NOLOCK, READLOCK, WRITELOCK};
430
432
433 bool try_read_lock() const {
434 nreader++;
435 if (writeflag == UNLOCKED) return true;
436 nreader--;
437 return false;
438 }
439
440 bool try_write_lock() const {
441 return (writeflag.compare_and_swap((int) UNLOCKED, (int) LOCKED) == 0);
442 }
443
444 bool try_lock(int lockmode) const {
445 if (lockmode == READLOCK) {
446 return try_read_lock();
447 }
448 else if (lockmode == WRITELOCK) {
449 return try_write_lock();
450 }
451 else if (lockmode == NOLOCK) {
452 return true;
453 }
454 else {
455 MADNESS_EXCEPTION("MutexReaderWriter: try_lock: invalid lock mode", lockmode);
456 }
457 }
458
460 if (!try_write_lock()) return false;
461 if (nreader > 1) {
462 write_unlock();
463 return false;
464 }
465 nreader = 0;
466 return true;
467 }
468
469 void read_lock() const {
470 while (!try_read_lock()) cpu_relax();
471 }
472
473 void write_lock() const {
474 while (!try_write_lock()) cpu_relax();
475 }
476
477 void lock(int lockmode) const {
478 while (!try_lock(lockmode)) cpu_relax();
479 }
480
481 void read_unlock() const {
482 nreader--;
483 }
484
485 void write_unlock() const {
486 writeflag = UNLOCKED;
487 }
488
489 void unlock(int lockmode) const {
490 if (lockmode == READLOCK) read_unlock();
491 else if (lockmode == WRITELOCK) write_unlock();
492 else if (lockmode != NOLOCK) MADNESS_EXCEPTION("MutexReaderWriter: try_lock: invalid lock mode", lockmode);
493 }
494
495 /// Converts read to write lock without releasing the read lock
496
497 /// Note that deadlock is guaranteed if two+ threads wait to convert at the same time.
500 }
501
502 /// Always succeeds immediately
504 nreader++;
505 writeflag = UNLOCKED;
506 }
507 };
508#endif
509
510 /// wait policies supported by ConditionVariable/DQueue/ThreadPool
511 enum class WaitPolicy {
512 Busy = 1, Yield, Sleep
513 };
514
515 /// Scalable and fair condition variable (spins on local value)
517 public:
518 static const int MAX_NTHREAD = 128;
519 mutable int back; // used to be volatile, but is protected by mutex and associated barriers
520 mutable int front; // ditto
521 mutable volatile bool* fifo[MAX_NTHREAD]; // volatile needed here; Circular buffer of flags
522
523 void set_wait_policy(WaitPolicy p, int us = 0) {
524 wait_policy_ = p;
525 wait_usleep_ = std::chrono::microseconds(us);
526 }
527
528 public:
530
531 /// You should acquire the mutex before waiting
532 void wait() const {
533 // We put a pointer to a thread-local variable at the
534 // end of the queue and wait for that value to be set,
535 // thus generate no memory traffic while waiting.
536 volatile bool myturn = false;
537 int b = this->back;
538 fifo[b] = &myturn;
539 this->back = (b+1 < MAX_NTHREAD ? b+1 : 0);
540
541 unlock(); // Release lock before blocking
542 switch (this->wait_policy_) {
544 while (!myturn) std::this_thread::yield();
546 while (!myturn) std::this_thread::sleep_for(this->wait_usleep_);
547 default:
548 while (!myturn) cpu_relax();
549 }
550 lock();
551 }
552
553 /// You should acquire the mutex before signalling
554 void signal() const {
555 int f = this->front;
556 if (f == this->back) return;
557 *fifo[f] = true;
558 int next = (f+1 < MAX_NTHREAD ? f+1 : 0);
559 this->front = next;
560 }
561
562 /// You should acquire the mutex before broadcasting
563 void broadcast() const {
564 while (front != back)
565 signal();
566 }
567
569
570 private:
572 std::chrono::microseconds wait_usleep_ = std::chrono::microseconds(0);
573
574 };
575
576
577 /// A scalable and fair mutex (not recursive)
578
579 /// Needs rewriting to use the CV above and do we really
580 /// need this if using pthread_mutex .. why not pthread_cv?
581 class MutexFair : private Spinlock {
582 private:
583 static const int MAX_NTHREAD = 128;
584 mutable volatile bool* q[MAX_NTHREAD]; // volatile needed
585 mutable int n; // volatile not needed due to use of spinlock and associated barriers
586 mutable int front;
587 mutable int back;
588
589 public:
590 MutexFair() : n(0), front(0), back(0) {};
591
592 void lock() const {
593 volatile bool myturn = false;
595 ++n;
596 if (n == 1) {
597 myturn = true;
598 }
599 else {
600 int b = back + 1;
601 if (b >= MAX_NTHREAD) b = 0;
602 q[b] = &myturn;
603 back = b;
604 }
606
607 while (!myturn) cpu_relax();
608 }
609
610 void unlock() const {
611 volatile bool* p = 0;
613 n--;
614 if (n > 0) {
615 int f = front + 1;
616 if (f >= MAX_NTHREAD) f = 0;
617 p = q[f];
618 front = f;
619 }
621 if (p) *p = true;
622 }
623
624 bool try_lock() const {
625 bool got_lock;
626
628 int nn = n;
629 got_lock = (nn == 0);
630 if (got_lock) n = nn + 1;
632
633 return got_lock;
634 }
635 };
636
637
638 /// Attempt to acquire two locks without blocking holding either one
639
640 /// The code will first attempt to acquire mutex m1 and if successful
641 /// will then attempt to acquire mutex m2.
642 inline bool try_two_locks(const Mutex& m1, const Mutex& m2) {
643 if (!m1.try_lock()) return false;
644 if (m2.try_lock()) return true;
645 m1.unlock();
646 return false;
647 }
648
649
650 /// Simple wrapper for Pthread condition variable with its own mutex
651
652 /// Use this when you need to block without consuming cycles.
653 /// Scheduling granularity is at the level of kernel ticks.
655 private:
656 mutable pthread_cond_t cv;
657 mutable pthread_mutex_t mutex;
658
659 public:
661 pthread_cond_init(&cv, nullptr);
662 pthread_mutex_init(&mutex, 0);
663 }
664
665 pthread_mutex_t& get_pthread_mutex() {
666 return mutex;
667 }
668
669 void lock() const {
670 int result = pthread_mutex_lock(&mutex);
671 if (result) {
672 fprintf(stderr, "!! MADNESS ERROR: PthreadConditionVariable::lock() failed acquiring mutex\n");
674 MADNESS_EXCEPTION("PthreadConditionVariable::lock() failed acquiring mutex", result);
675 }
676 }
677
678 void unlock() const {
679 int result = pthread_mutex_unlock(&mutex);
680 if (result) {
681 fprintf(stderr, "!! MADNESS ERROR: PthreadConditionVariable::unlock() failed releasing mutex\n");
683 MADNESS_EXCEPTION("PthreadConditionVariable::unlock() failed releasing mutex", result);
684 }
685 }
686
687 /// You should have acquired the mutex before entering here
688 void wait() const {
689 pthread_cond_wait(&cv,&mutex);
690 }
691
692 void signal() const {
693 int result = pthread_cond_signal(&cv);
694 if (result) MADNESS_EXCEPTION("ConditionalVariable: signalling failed", result);
695 }
696
697 void broadcast() const {
698 int result = pthread_cond_broadcast(&cv);
699 if (result) MADNESS_EXCEPTION("ConditionalVariable: signalling failed", result);
700 }
701
703 pthread_mutex_destroy(&mutex);
704 pthread_cond_destroy(&cv);
705 }
706 }; // class PthreadConditionVariable
707
708#ifdef USE_SPINLOCKS
709 typedef ConditionVariable CONDITION_VARIABLE_TYPE ;
710 typedef Spinlock SPINLOCK_TYPE;
711 typedef MutexFair SCALABLE_MUTEX_TYPE;
712#else
716#endif
717
718 // Fast barrier for nthread threads --- uses sense-changing barrier in which threads spin on cache-local value --- used in tensor/systolic.h
719 //
720 // The per-thread flags and the shared sense are std::atomic, not volatile:
721 // volatile provides neither atomicity nor inter-thread ordering. Ordering
722 // comes from a fence pair -- a release fence before the notifier's relaxed
723 // flag stores, an acquire fence after the waiter's relaxed spin -- which is
724 // what establishes happens-before across the barrier ([atomics.fences]).
725 // The fence form is used rather than store-release/load-acquire on each
726 // flag because it pays for ordering once instead of per spin iteration.
727 // Without the acquire on the waiting side, weakly-ordered machines (AArch64)
728 // may reorder a waiter's post-barrier loads ahead of the flag load and so
729 // observe stale data written by its peers before the barrier.
730 class Barrier {
731 static const int MAX_NTHREAD = 128;
732 const int nthread;
733 std::atomic<bool> sense;
735 std::atomic<bool>* pflags[MAX_NTHREAD];
736
737 public:
740 , sense(true)
741 {
743 }
744
745 /// Each thread calls this once before first use
746
747 /// id should be the thread id (0,..,nthread-1) and pflag a pointer to
748 /// a thread-local atomic flag (probably in the thread's stack)
749 void register_thread(int id, std::atomic<bool>* pflag) {
750 if (id < 0 || id >= MAX_NTHREAD) MADNESS_EXCEPTION("Barrier : hard dimension failed", id);
751 pflags[id] = pflag;
752 pflag->store(!sense.load(std::memory_order_relaxed), std::memory_order_relaxed);
753 }
754
755 /// Each thread calls this with its id (0,..,nthread-1) to enter the barrier
756
757 /// The thread last to enter the barrier returns true. Others return false.
758 ///
759 /// All calls to the barrier must use the same value of nthread.
760 bool enter(const int id) {
761 if (nthread <= 1) {
762 return true;
763 }
764 else {
765 if (id < 0 || id >= MAX_NTHREAD) MADNESS_EXCEPTION("Barrier : hard dimension failed", id);
766 const bool lsense = sense.load(std::memory_order_relaxed); // Local copy of sense
767 const bool result = nworking.dec_and_test();
768 if (result) {
769 // Reset counter and sense for next entry. AtomicInt is
770 // seq_cst, so this thread has already acquired the work of
771 // every other thread via their decrements.
773 sense.store(!lsense, std::memory_order_relaxed);
774
775 // One release fence, then relaxed stores -- cheaper than
776 // nthread release stores, and it publishes everything
777 // sequenced before it: this thread's work, the sense and
778 // nworking resets, and (via dec_and_test) transitively the
779 // other threads' pre-barrier work.
781
782 // Notify everyone including me
783 for (int i = 0; i < nthread; ++i)
784 pflags[i]->store(lsense, std::memory_order_relaxed);
785
786 } else {
787 std::atomic<bool>* myflag = pflags[id]; // Local flag;
788 // Spin on cheap relaxed loads and pay for ordering exactly
789 // once, on exit. The relaxed load that finally observes
790 // lsense, followed by this acquire fence, synchronizes with
791 // the release fence above ([atomics.fences]) -- so the other
792 // threads' pre-barrier work is visible from here on.
793 while (myflag->load(std::memory_order_relaxed) != lsense) {
794 cpu_relax();
795 }
797 }
798 return result;
799 }
800 }
801 }; // class Barrier
802
803 namespace detail {
804 extern Mutex printmutex;
805 }
806}
807
808///@}
809
810
811#endif // MADNESS_WORLD_WORLDMUTEX_H__INCLUDED
Implements AtomicInt.
Disables default copy constructor and assignment operators.
Definition nodefaults.h:49
An integer with atomic set, get, read+increment, read+decrement, and decrement+test operations.
Definition atomicint.h:126
bool dec_and_test()
Decrements the counter and returns true if the new value is zero,.
Definition atomicint.h:297
Definition worldmutex.h:730
const int nthread
Definition worldmutex.h:732
void register_thread(int id, std::atomic< bool > *pflag)
Each thread calls this once before first use.
Definition worldmutex.h:749
std::atomic< bool > * pflags[MAX_NTHREAD]
Definition worldmutex.h:735
static const int MAX_NTHREAD
Definition worldmutex.h:731
AtomicInt nworking
Definition worldmutex.h:734
bool enter(const int id)
Each thread calls this with its id (0,..,nthread-1) to enter the barrier.
Definition worldmutex.h:760
Barrier(int nthread)
Definition worldmutex.h:738
std::atomic< bool > sense
Definition worldmutex.h:733
Scalable and fair condition variable (spins on local value)
Definition worldmutex.h:516
void wait() const
You should acquire the mutex before waiting.
Definition worldmutex.h:532
int front
Definition worldmutex.h:520
void signal() const
You should acquire the mutex before signalling.
Definition worldmutex.h:554
void broadcast() const
You should acquire the mutex before broadcasting.
Definition worldmutex.h:563
int back
Definition worldmutex.h:519
static const int MAX_NTHREAD
Definition worldmutex.h:518
virtual ~ConditionVariable()
Definition worldmutex.h:568
volatile bool * fifo[MAX_NTHREAD]
Definition worldmutex.h:521
ConditionVariable()
Definition worldmutex.h:529
std::chrono::microseconds wait_usleep_
Definition worldmutex.h:572
void set_wait_policy(WaitPolicy p, int us=0)
Definition worldmutex.h:523
WaitPolicy wait_policy_
Definition worldmutex.h:571
A scalable and fair mutex (not recursive)
Definition worldmutex.h:581
bool try_lock() const
Definition worldmutex.h:624
void lock() const
Definition worldmutex.h:592
int front
Definition worldmutex.h:586
MutexFair()
Definition worldmutex.h:590
static const int MAX_NTHREAD
Definition worldmutex.h:583
void unlock() const
Definition worldmutex.h:610
int n
Definition worldmutex.h:585
int back
Definition worldmutex.h:587
volatile bool * q[MAX_NTHREAD]
Definition worldmutex.h:584
Definition worldmutex.h:325
void convert_read_lock_to_write_lock() const
Converts read to write lock without releasing the read lock.
Definition worldmutex.h:407
void write_unlock() const
Definition worldmutex.h:391
static const int WRITELOCK
Definition worldmutex.h:331
void convert_write_lock_to_read_lock() const
Always succeeds immediately.
Definition worldmutex.h:412
virtual ~MutexReaderWriter()
Definition worldmutex.h:417
bool try_read_lock() const
Definition worldmutex.h:335
MutexReaderWriter()
Definition worldmutex.h:333
static const int READLOCK
Definition worldmutex.h:330
void lock(int lockmode) const
Definition worldmutex.h:382
int nreader
Definition worldmutex.h:326
bool try_lock(int lockmode) const
Definition worldmutex.h:349
void unlock(int lockmode) const
Definition worldmutex.h:398
static const int NOLOCK
Definition worldmutex.h:329
void write_lock() const
Definition worldmutex.h:378
void read_lock() const
Definition worldmutex.h:374
bool try_write_lock() const
Definition worldmutex.h:342
bool writeflag
Definition worldmutex.h:327
bool try_convert_read_lock_to_write_lock() const
Definition worldmutex.h:364
void read_unlock() const
Definition worldmutex.h:386
Definition worldmutex.h:128
void wait()
Definition worldmutex.cc:103
MutexWaiter()
Definition worldmutex.h:141
unsigned int count
Definition worldmutex.h:130
void yield(int us)
Definition worldmutex.h:134
void reset()
Definition worldmutex.h:143
Mutex using pthread mutex operations.
Definition worldmutex.h:150
pthread_mutex_t mutex
Definition worldmutex.h:152
pthread_mutex_t * ptr() const
Return a pointer to the pthread mutex for use by a condition variable.
Definition worldmutex.h:194
void operator=(const Mutex &)
Assignment is forbidden.
Mutex(const Mutex &)
Copy constructor is forbidden.
Mutex(int junk=0)
Make and initialize a mutex ... initial state is unlocked.
Definition worldmutex.h:162
void unlock() const
Free a mutex owned by this thread.
Definition worldmutex.h:184
virtual ~Mutex()
Definition worldmutex.h:198
bool try_lock() const
Try to acquire the mutex ... return true on success, false on failure.
Definition worldmutex.h:169
void lock() const
Acquire the mutex waiting if necessary.
Definition worldmutex.h:174
Simple wrapper for Pthread condition variable with its own mutex.
Definition worldmutex.h:654
pthread_mutex_t mutex
Definition worldmutex.h:657
void lock() const
Definition worldmutex.h:669
pthread_cond_t cv
Definition worldmutex.h:656
virtual ~PthreadConditionVariable()
Definition worldmutex.h:702
void unlock() const
Definition worldmutex.h:678
void broadcast() const
Definition worldmutex.h:697
void signal() const
Definition worldmutex.h:692
pthread_mutex_t & get_pthread_mutex()
Definition worldmutex.h:665
void wait() const
You should have acquired the mutex before entering here.
Definition worldmutex.h:688
PthreadConditionVariable()
Definition worldmutex.h:660
Recursive mutex using pthread mutex operations.
Definition worldmutex.h:204
void operator=(const RecursiveMutex &)
Assignment is forbidden.
void lock() const
Acquire the mutex waiting if necessary.
Definition worldmutex.h:224
RecursiveMutex(const RecursiveMutex &)
Copy constructor is forbidden.
pthread_mutex_t * ptr() const
Return a pointer to the pthread mutex for use by a condition variable.
Definition worldmutex.h:244
void unlock() const
Free a mutex owned by this thread.
Definition worldmutex.h:234
bool try_lock() const
Try to acquire the mutex ... return true on success, false on failure.
Definition worldmutex.h:219
pthread_mutex_t mutex
Definition worldmutex.h:206
~RecursiveMutex()
Definition worldmutex.h:248
RecursiveMutex()
Make and initialize a mutex ... initial state is unlocked.
Definition worldmutex.cc:127
Mutex that is applied/released at start/end of a scope.
Definition worldmutex.h:258
const mutexT * mutex
Definition worldmutex.h:259
ScopedMutex(const mutexT &m)
Definition worldmutex.h:263
ScopedMutex(const mutexT *m)
Definition worldmutex.h:261
virtual ~ScopedMutex()
Definition worldmutex.h:265
Spinlock using pthread spinlock operations.
Definition worldmutex.h:272
void lock() const
Acquire the spinlock waiting if necessary.
Definition worldmutex.h:296
bool try_lock() const
Try to acquire the spinlock ... return true on success, false on failure.
Definition worldmutex.h:291
void operator=(const Spinlock &)
Assignment is forbidden.
Spinlock(int junk=0)
Make and initialize a spinlock ... initial state is unlocked.
Definition worldmutex.h:285
void unlock() const
Free a spinlock owned by this thread.
Definition worldmutex.h:306
Spinlock(const Spinlock &)
Copy constructor is forbidden.
virtual ~Spinlock()
Definition worldmutex.h:315
pthread_spinlock_t spinlock
Definition worldmutex.h:275
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
Macros and tools pertaining to the configuration of MADNESS.
Defines madness::MadnessException for exception handling.
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
Definition potentialmanager.cc:41
void print_mutex_error(int error_number)
Definition worldmutex.cc:44
Mutex printmutex
Definition worldmutex.cc:146
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
PthreadConditionVariable CONDITION_VARIABLE_TYPE
Definition worldmutex.h:713
WaitPolicy
wait policies supported by ConditionVariable/DQueue/ThreadPool
Definition worldmutex.h:511
bool try_two_locks(const Mutex &m1, const Mutex &m2)
Attempt to acquire two locks without blocking holding either one.
Definition worldmutex.h:642
Mutex SPINLOCK_TYPE
Definition worldmutex.h:714
static void myusleep(unsigned int us)
Sleep or spin for specified number of microseconds.
Definition timers.h:186
NDIM & f
Definition mra.h:2668
void cpu_relax()
Do nothing and especially do not touch memory.
Definition timers.h:166
Mutex SCALABLE_MUTEX_TYPE
Definition worldmutex.h:715
Implements NO_DEFAULTS.
static const double b
Definition nonlinschro.cc:119
static const double m
Definition relops.cc:9
Wrappers around platform dependent timers and performance info.
#define MADNESS_MEMORY_STORE_BARRIER
Definition worldmutex.h:47
#define MADNESS_MEMORY_LOAD_BARRIER
Definition worldmutex.h:52