source: libcfa/src/bits/locks.hfa@ b0c7419

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since b0c7419 was 3381ed7, checked in by Thierry Delisle <tdelisle@…>, 6 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.