source: libcfa/src/bits/locks.hfa @ 3381ed7

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 3381ed7 was 3381ed7, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Added park/unpark primitives thread and removed BlockInternal?.
Converted monitors to use park unpark.
Intrusive Queue now mark next field when thread is inside queue.
Added several asserts to kernel and monitor.
Added a few tests for park and unpark.

  • Property mode set to 100644
File size: 3.8 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 : Sat Aug 11 15:42:24 2018
13// Update Count     : 10
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
39struct __spinlock_t {
40        // Wrap in struct to prevent false sharing with debug info
41        volatile bool lock;
42        #ifdef __CFA_DEBUG__
43                // previous function to acquire the lock
44                const char * prev_name;
45                // previous thread to acquire the lock
46                void* prev_thrd;
47        #endif
48};
49
50#ifdef __cforall
51        extern "C" {
52                extern void disable_interrupts() OPTIONAL_THREAD;
53                extern void enable_interrupts_noPoll() OPTIONAL_THREAD;
54
55                #ifdef __CFA_DEBUG__
56                        void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);
57                #else
58                        #define __cfaabi_dbg_record(x, y)
59                #endif
60        }
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 __cfaabi_dbg_ctx_param2 ) {
68                disable_interrupts();
69                bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
70                if( result ) {
71                        __cfaabi_dbg_record( this, caller );
72                } else {
73                        enable_interrupts_noPoll();
74                }
75                return result;
76        }
77
78        // Lock the spinlock, spin if already acquired
79        static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
80                #ifndef NOEXPBACK
81                        enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
82                        unsigned int spin = SPIN_START;
83                #endif
84
85                disable_interrupts();
86                for ( unsigned int i = 1;; i += 1 ) {
87                        if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) 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_record( this, caller );
102        }
103
104        static inline void unlock( __spinlock_t & this ) {
105                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
106                enable_interrupts_noPoll();
107        }
108
109
110        #ifdef __CFA_WITH_VERIFY__
111                extern bool __cfaabi_dbg_in_kernel();
112        #endif
113
114        struct __bin_sem_t {
115                bool                    signaled;
116                pthread_mutex_t         lock;
117                pthread_cond_t          cond;
118        };
119
120        static inline void ?{}(__bin_sem_t & this) with( this ) {
121                signaled = false;
122                pthread_mutex_init(&lock, NULL);
123                pthread_cond_init (&cond, NULL);
124        }
125
126        static inline void ^?{}(__bin_sem_t & this) with( this ) {
127                pthread_mutex_destroy(&lock);
128                pthread_cond_destroy (&cond);
129        }
130
131        static inline void wait(__bin_sem_t & this) with( this ) {
132                verify(__cfaabi_dbg_in_kernel());
133                pthread_mutex_lock(&lock);
134                        if(!signaled) {   // this must be a loop, not if!
135                                pthread_cond_wait(&cond, &lock);
136                        }
137                        signaled = false;
138                pthread_mutex_unlock(&lock);
139        }
140
141        static inline void post(__bin_sem_t & this) with( this ) {
142                verify(__cfaabi_dbg_in_kernel());
143
144                pthread_mutex_lock(&lock);
145                        bool needs_signal = !signaled;
146                        signaled = true;
147                pthread_mutex_unlock(&lock);
148
149                if (needs_signal)
150                        pthread_cond_signal(&cond);
151        }
152#endif
Note: See TracBrowser for help on using the repository browser.