source: src/libcfa/bits/locks.h @ 92fea32

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumwith_gc
Last change on this file since 92fea32 was 2e9aed4, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Fixed non-preemptive locks

  • Property mode set to 100644
File size: 3.6 KB
RevLine 
[ea7d2b0]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
[b158d8f]11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Dec  8 16:02:22 2017
13// Update Count     : 1
[ea7d2b0]14//
15
16#pragma once
17
[875a72f]18#include "bits/debug.h"
[ea7d2b0]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" : : : )
[b158d8f]26#elif defined( __ARM_ARCH )
27        #define Pause() __asm__ __volatile__ ( "nop" : : : )
[ea7d2b0]28#else
29        #error unsupported architecture
30#endif
31
[b158d8f]32#if defined( __i386 ) || defined( __x86_64 ) || defined( __ARM_ARCH )
[ea7d2b0]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
[b158d8f]41#if __SIZEOF_SIZE_T__ == 8
[ea7d2b0]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) );
[b158d8f]44#elif __SIZEOF_SIZE_T__ == 4
[ea7d2b0]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 {
[b158d8f]52        __ALIGN__ volatile size_t lock;
[ea7d2b0]53        #ifdef __CFA_DEBUG__
54                const char * prev_name;
55                void* prev_thrd;
56        #endif
57} __ALIGN__;
58
[0cf5b79]59#ifdef __cforall
[dbe9b08]60        extern "C" {
61                extern void disable_interrupts();
62                extern void enable_interrupts_noPoll();
63        }
64
[ea7d2b0]65        extern void yield( unsigned int );
66        extern thread_local struct thread_desc *    volatile this_thread;
[2e9aed4]67        extern thread_local struct processor *      volatile this_processor;
[ea7d2b0]68
69        static inline void ?{}( __spinlock_t & this ) {
70                this.lock = 0;
71        }
72
73        // Lock the spinlock, return false if already acquired
[36982fc]74        static inline _Bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[ea7d2b0]75                _Bool result = __lock_test_and_test_and_set( this.lock );
[dbe9b08]76                if( result ) {
77                        disable_interrupts();
78                        __cfaabi_dbg_debug_do(
[ea7d2b0]79                                this.prev_name = caller;
80                                this.prev_thrd = this_thread;
[dbe9b08]81                        )
82                }
[ea7d2b0]83                return result;
84        }
85
86        // Lock the spinlock, spin if already acquired
[36982fc]87        static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[ea7d2b0]88                #ifndef NOEXPBACK
89                        enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
90                        unsigned int spin = SPIN_START;
91                #endif
92
93                for ( unsigned int i = 1;; i += 1 ) {
94                        if ( __lock_test_and_test_and_set( this.lock ) ) break;
95                        #ifndef NOEXPBACK
96                                // exponential spin
97                                for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
98
99                                // slowly increase by powers of 2
100                                if ( i % 64 == 0 ) spin += spin;
101
102                                // prevent overflow
103                                if ( spin > SPIN_END ) spin = SPIN_START;
104                        #else
105                                Pause();
106                        #endif
107                }
[dbe9b08]108                disable_interrupts();
[36982fc]109                __cfaabi_dbg_debug_do(
[ea7d2b0]110                        this.prev_name = caller;
111                        this.prev_thrd = this_thread;
112                )
113        }
114
[2e9aed4]115        // // Lock the spinlock, yield if already acquired
116        // static inline void lock_yield( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
117        //      for ( unsigned int i = 1;; i += 1 ) {
118        //              if ( __lock_test_and_test_and_set( this.lock ) ) break;
119        //              yield( i );
120        //      }
121        //      disable_interrupts();
122        //      __cfaabi_dbg_debug_do(
123        //              this.prev_name = caller;
124        //              this.prev_thrd = this_thread;
125        //      )
126        // }
[ea7d2b0]127
128        static inline void unlock( __spinlock_t & this ) {
[dbe9b08]129                enable_interrupts_noPoll();
[2e9aed4]130                __lock_release( this.lock );
[ea7d2b0]131        }
[b158d8f]132#endif
Note: See TracBrowser for help on using the repository browser.