source: libcfa/src/bits/locks.hfa@ 34d194c

Last change on this file since 34d194c was 34d194c, checked in by Peter A. Buhr <pabuhr@…>, 4 days ago

move libcfa/src/concurrency/atomic.hfa to libcfa/src/bits/atomic.hfa, and update all the atomic operations

  • Property mode set to 100644
File size: 2.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// bits/locks.hfa -- Basic spinlocks that are reused in the system.
8// Used for locks that aren't specific to cforall threads and can be used anywhere
9//
10// *** Must not contain code specific to libcfathread ***
11//
12// Author : Thierry Delisle
13// Created On : Tue Oct 31 15:14:38 2017
14// Last Modified By : Peter A. Buhr
15// Last Modified On : Sat Jul 4 06:50:46 2026
16// Update Count : 21
17//
18
19#pragma once
20
21#include "bits/debug.hfa"
22#include "bits/defs.hfa"
23#include "bits/atomic.hfa"
24#include <assert.h>
25
26struct __spinlock_t {
27 // Wrap in struct to prevent false sharing with debug info
28 volatile bool lock;
29};
30
31#ifdef __cforall
32 extern "C" {
33 extern void disable_interrupts() OPTIONAL_THREAD;
34 extern void enable_interrupts( bool poll = true ) OPTIONAL_THREAD;
35 extern bool poll_interrupts() OPTIONAL_THREAD;
36 #define __cfaabi_dbg_record_lock(x, y)
37 }
38
39 static inline void ?{}( __spinlock_t & this ) {
40 this.lock = 0;
41 }
42
43 // Lock the spinlock, return false if already acquired
44 static inline bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
45 disable_interrupts();
46 bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
47 if( result ) {
48 __cfaabi_dbg_record_lock( this, caller );
49 } else {
50 enable_interrupts( false );
51 }
52 return result;
53 }
54
55 // Lock the spinlock, spin if already acquired
56 static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
57 #ifndef NOEXPBACK
58 enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
59 unsigned int spin = SPIN_START;
60 #endif
61
62 disable_interrupts();
63 for ( i; 1 ~ @ ) {
64 if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
65 #ifndef NOEXPBACK
66 // exponential spin
67 for ( volatile unsigned int s; 0 ~ spin ) Pause();
68
69 // slowly increase by powers of 2
70 if ( i % 64 == 0 ) spin += spin;
71
72 // prevent overflow
73 if ( spin > SPIN_END ) spin = SPIN_START;
74 #else
75 Pause();
76 #endif
77 }
78 __cfaabi_dbg_record_lock( this, caller );
79 }
80
81 static inline void unlock( __spinlock_t & this ) {
82 __atomic_clear( &this.lock, __ATOMIC_RELEASE );
83 enable_interrupts( false );
84 }
85#endif
Note: See TracBrowser for help on using the repository browser.