source: libcfa/src/bits/locks.hfa @ 9aa9126

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexer
Last change on this file since 9aa9126 was 9aa9126, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

  • Property mode set to 100644
File size: 4.0 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 -- Fast internal locks.
8//
9// Author           : Thierry Delisle
10// Created On       : Tue Oct 31 15:14:38 2017
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Mar 30 18:18:13 2018
13// Update Count     : 9
14//
15
16#pragma once
17
18#include "bits/debug.hfa"
19#include "bits/defs.hfa"
20#include <assert.h>
21
22#ifdef __cforall
23        extern "C" {
24                #include <pthread.h>
25        }
26#endif
27
28// pause to prevent excess processor bus usage
29#if defined( __sparc )
30        #define Pause() __asm__ __volatile__ ( "rd %ccr,%g0" )
31#elif defined( __i386 ) || defined( __x86_64 )
32        #define Pause() __asm__ __volatile__ ( "pause" : : : )
33#elif defined( __ARM_ARCH )
34        #define Pause() __asm__ __volatile__ ( "nop" : : : )
35#else
36        #error unsupported architecture
37#endif
38
39#if defined( __i386 ) || defined( __x86_64 ) || defined( __ARM_ARCH )
40        // Intel recommendation
41        #define __ALIGN__ __attribute__(( aligned (128) ))
42#elif defined( __sparc )
43        #define __ALIGN__ CALIGN
44#else
45        #error unsupported architecture
46#endif
47
48struct __spinlock_t {
49        // Wrap in struct to prevent false sharing with debug info
50        struct {
51                // Align lock on 128-bit boundary
52                __ALIGN__ volatile _Bool lock;
53        };
54        #ifdef __CFA_DEBUG__
55                // previous function to acquire the lock
56                const char * prev_name;
57                // previous thread to acquire the lock
58                void* prev_thrd;
59        #endif
60} __ALIGN__;
61
62#ifdef __cforall
63        extern "C" {
64                extern void disable_interrupts();
65                extern void enable_interrupts_noPoll();
66
67                #ifdef __CFA_DEBUG__
68                        void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);
69                #else
70                        #define __cfaabi_dbg_record(x, y)
71                #endif
72        }
73
74        extern void yield( unsigned int );
75
76        static inline void ?{}( __spinlock_t & this ) {
77                this.lock = 0;
78        }
79
80        // Lock the spinlock, return false if already acquired
81        static inline _Bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
82                _Bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
83                if( result ) {
84                        disable_interrupts();
85                        __cfaabi_dbg_record( this, caller );
86                }
87                return result;
88        }
89
90        // Lock the spinlock, spin if already acquired
91        static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
92                #ifndef NOEXPBACK
93                        enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
94                        unsigned int spin = SPIN_START;
95                #endif
96
97                for ( unsigned int i = 1;; i += 1 ) {
98                        if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
99                        #ifndef NOEXPBACK
100                                // exponential spin
101                                for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
102
103                                // slowly increase by powers of 2
104                                if ( i % 64 == 0 ) spin += spin;
105
106                                // prevent overflow
107                                if ( spin > SPIN_END ) spin = SPIN_START;
108                        #else
109                                Pause();
110                        #endif
111                }
112                disable_interrupts();
113                __cfaabi_dbg_record( this, caller );
114        }
115
116        static inline void unlock( __spinlock_t & this ) {
117                enable_interrupts_noPoll();
118                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
119        }
120
121
122        #ifdef __CFA_WITH_VERIFY__
123                extern bool __cfaabi_dbg_in_kernel();
124        #endif
125
126        struct __bin_sem_t {
127                bool                    signaled;
128                pthread_mutex_t         lock;
129                pthread_cond_t          cond;
130        };
131
132        static inline void ?{}(__bin_sem_t & this) with( this ) {
133                signaled = false;
134                pthread_mutex_init(&lock, NULL);
135                pthread_cond_init (&cond, NULL);
136        }
137
138        static inline void ^?{}(__bin_sem_t & this) with( this ) {
139                pthread_mutex_destroy(&lock);
140                pthread_cond_destroy (&cond);
141        }
142
143        static inline void wait(__bin_sem_t & this) with( this ) {
144                verify(__cfaabi_dbg_in_kernel());
145                pthread_mutex_lock(&lock);
146                        if(!signaled) {   // this must be a loop, not if!
147                                pthread_cond_wait(&cond, &lock);
148                        }
149                        signaled = false;
150                pthread_mutex_unlock(&lock);
151        }
152
153        static inline void post(__bin_sem_t & this) with( this ) {
154                verify(__cfaabi_dbg_in_kernel());
155
156                pthread_mutex_lock(&lock);
157                        bool needs_signal = !signaled;
158                        signaled = true;
159                pthread_mutex_unlock(&lock);
160
161                if (needs_signal)
162                        pthread_cond_signal(&cond);
163        }
164#endif
Note: See TracBrowser for help on using the repository browser.