source: libcfa/src/bits/locks.hfa @ 1f11818

Last change on this file since 1f11818 was 301071a, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

formatting

  • 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 : Tue Sep 20 22:09:50 2022
16// Update Count     : 18
17//
18
19#pragma once
20
21#include "bits/debug.hfa"
22#include "bits/defs.hfa"
23#include <assert.h>
24
25struct __spinlock_t {
26        // Wrap in struct to prevent false sharing with debug info
27        volatile bool lock;
28};
29
30#ifdef __cforall
31        extern "C" {
32                extern void disable_interrupts() OPTIONAL_THREAD;
33                extern void enable_interrupts( bool poll = true ) OPTIONAL_THREAD;
34                extern bool poll_interrupts() OPTIONAL_THREAD;
35                #define __cfaabi_dbg_record_lock(x, y)
36        }
37
38        static inline void ?{}( __spinlock_t & this ) {
39                this.lock = 0;
40        }
41
42        // Lock the spinlock, return false if already acquired
43        static inline bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
44                disable_interrupts();
45                bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
46                if( result ) {
47                        __cfaabi_dbg_record_lock( this, caller );
48                } else {
49                        enable_interrupts( false );
50                }
51                return result;
52        }
53
54        // Lock the spinlock, spin if already acquired
55        static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
56                #ifndef NOEXPBACK
57                        enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
58                        unsigned int spin = SPIN_START;
59                #endif
60
61                disable_interrupts();
62                for ( i; 1 ~ @ ) {
63                        if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
64                        #ifndef NOEXPBACK
65                                // exponential spin
66                                for ( volatile unsigned int s; 0 ~ spin ) Pause();
67
68                                // slowly increase by powers of 2
69                                if ( i % 64 == 0 ) spin += spin;
70
71                                // prevent overflow
72                                if ( spin > SPIN_END ) spin = SPIN_START;
73                        #else
74                                Pause();
75                        #endif
76                }
77                __cfaabi_dbg_record_lock( this, caller );
78        }
79
80        static inline void unlock( __spinlock_t & this ) {
81                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
82                enable_interrupts( false );
83        }
84#endif
Note: See TracBrowser for help on using the repository browser.