source: src/libcfa/bits/locks.h @ 34c6c767

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 34c6c767 was ea7d2b0, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Moved spinlocks to bits/locks.h

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