source: src/libcfa/bits/locks.h @ 490d9972

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 490d9972 was c2b9f21, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Removed libhdr, moved its content to bits

  • Property mode set to 100644
File size: 3.2 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.h -- Fast internal locks.
8//
9// Author           : Thierry Delisle
10// Created On       : Tue Oct 31 15:14:38 2017
11// Last Modified By : --
12// Last Modified On : --
13// Update Count     : 0
14//
15
16#pragma once
17
18#include "bits/debug.h"
19#include "bits/defs.h"
20
21// pause to prevent excess processor bus usage
22#if defined( __sparc )
23        #define Pause() __asm__ __volatile__ ( "rd %ccr,%g0" )
24#elif defined( __i386 ) || defined( __x86_64 )
25        #define Pause() __asm__ __volatile__ ( "pause" : : : )
26#else
27        #error unsupported architecture
28#endif
29
30#if defined( __i386 ) || defined( __x86_64 )
31        // Intel recommendation
32        #define __ALIGN__ __attribute__(( aligned (128) ))
33#elif defined( __sparc )
34        #define __ALIGN__ CALIGN
35#else
36        #error unsupported architecture
37#endif
38
39#if defined( __x86_64 )
40        #define __lock_test_and_test_and_set( lock ) (lock) == 0 && __sync_lock_test_and_set_8( &(lock), 1 ) == 0
41        #define __lock_release( lock ) __sync_lock_release_8( &(lock) );
42#elif defined( __i386 )
43        #define __lock_test_and_test_and_set( lock ) (lock) == 0 && __sync_lock_test_and_set_4( &(lock), 1 ) == 0
44        #define __lock_release( lock ) __sync_lock_release_4( &(lock) );
45#else
46        #error unsupported architecture
47#endif
48
49struct __spinlock_t {
50        __ALIGN__ volatile uintptr_t lock;
51        #ifdef __CFA_DEBUG__
52                const char * prev_name;
53                void* prev_thrd;
54        #endif
55} __ALIGN__;
56
57#ifdef __cforall
58        extern void yield( unsigned int );
59        extern thread_local struct thread_desc *    volatile this_thread;
60
61        static inline void ?{}( __spinlock_t & this ) {
62                this.lock = 0;
63        }
64
65        // Lock the spinlock, return false if already acquired
66        static inline _Bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
67                _Bool result = __lock_test_and_test_and_set( this.lock );
68                __cfaabi_dbg_debug_do(
69                        if( result ) {
70                                this.prev_name = caller;
71                                this.prev_thrd = this_thread;
72                        }
73                )
74                return result;
75        }
76
77        // Lock the spinlock, spin if already acquired
78        static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
79                #ifndef NOEXPBACK
80                        enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
81                        unsigned int spin = SPIN_START;
82                #endif
83
84                for ( unsigned int i = 1;; i += 1 ) {
85                        if ( __lock_test_and_test_and_set( this.lock ) ) break;
86                        #ifndef NOEXPBACK
87                                // exponential spin
88                                for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
89
90                                // slowly increase by powers of 2
91                                if ( i % 64 == 0 ) spin += spin;
92
93                                // prevent overflow
94                                if ( spin > SPIN_END ) spin = SPIN_START;
95                        #else
96                                Pause();
97                        #endif
98                }
99                __cfaabi_dbg_debug_do(
100                        this.prev_name = caller;
101                        this.prev_thrd = this_thread;
102                )
103        }
104
105        // Lock the spinlock, spin if already acquired
106        static inline void lock_yield( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
107                for ( unsigned int i = 1;; i += 1 ) {
108                        if ( __lock_test_and_test_and_set( this.lock ) ) break;
109                        yield( i );
110                }
111                __cfaabi_dbg_debug_do(
112                        this.prev_name = caller;
113                        this.prev_thrd = this_thread;
114                )
115        }
116
117        static inline void unlock( __spinlock_t & this ) {
118                __lock_release( this.lock );
119        }
120#endif
Note: See TracBrowser for help on using the repository browser.