source: src/libcfa/bits/locks.h @ 875a72f

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 875a72f was 875a72f, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Moved debug to bits folder

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