source: libcfa/src/bits/locks.hfa@ 7d9bbef

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 7d9bbef was 6ec07e5, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Improved error messaging in locks

  • Property mode set to 100644
File size: 4.2 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//
[73abe95]7// bits/locks.hfa -- Fast internal locks.
[ea7d2b0]8//
9// Author : Thierry Delisle
10// Created On : Tue Oct 31 15:14:38 2017
[b158d8f]11// Last Modified By : Peter A. Buhr
[e3fea42]12// Last Modified On : Tue Feb 4 13:03:19 2020
13// Update Count : 11
[ea7d2b0]14//
15
16#pragma once
17
[73abe95]18#include "bits/debug.hfa"
19#include "bits/defs.hfa"
[ea8b2f7]20#include <assert.h>
21
22#ifdef __cforall
23 extern "C" {
24 #include <pthread.h>
25 }
26#endif
[ea7d2b0]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" : : : )
[b158d8f]33#elif defined( __ARM_ARCH )
34 #define Pause() __asm__ __volatile__ ( "nop" : : : )
[ea7d2b0]35#else
36 #error unsupported architecture
37#endif
38
39struct __spinlock_t {
[13073be]40 // Wrap in struct to prevent false sharing with debug info
[3aeee3c]41 volatile bool lock;
[ea7d2b0]42 #ifdef __CFA_DEBUG__
[13073be]43 // previous function to acquire the lock
[ea7d2b0]44 const char * prev_name;
[13073be]45 // previous thread to acquire the lock
[ea7d2b0]46 void* prev_thrd;
47 #endif
[3aeee3c]48};
[ea7d2b0]49
[0cf5b79]50#ifdef __cforall
[dbe9b08]51 extern "C" {
[2026bb6]52 extern void disable_interrupts() OPTIONAL_THREAD;
53 extern void enable_interrupts_noPoll() OPTIONAL_THREAD;
[1997b4e]54
55 #ifdef __CFA_DEBUG__
[ae66348]56 void __cfaabi_dbg_record_lock(__spinlock_t & this, const char prev_name[]);
[1997b4e]57 #else
[ae66348]58 #define __cfaabi_dbg_record_lock(x, y)
[1997b4e]59 #endif
[dbe9b08]60 }
61
[ea7d2b0]62 static inline void ?{}( __spinlock_t & this ) {
63 this.lock = 0;
64 }
65
66 // Lock the spinlock, return false if already acquired
[93c2e0a]67 static inline bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[3381ed7]68 disable_interrupts();
[93c2e0a]69 bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
[dbe9b08]70 if( result ) {
[ae66348]71 __cfaabi_dbg_record_lock( this, caller );
[3381ed7]72 } else {
73 enable_interrupts_noPoll();
[dbe9b08]74 }
[ea7d2b0]75 return result;
76 }
77
78 // Lock the spinlock, spin if already acquired
[36982fc]79 static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[ea7d2b0]80 #ifndef NOEXPBACK
81 enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
82 unsigned int spin = SPIN_START;
83 #endif
84
[3381ed7]85 disable_interrupts();
[ea7d2b0]86 for ( unsigned int i = 1;; i += 1 ) {
[13073be]87 if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
[ea7d2b0]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 }
[ae66348]101 __cfaabi_dbg_record_lock( this, caller );
[ea7d2b0]102 }
103
104 static inline void unlock( __spinlock_t & this ) {
[13073be]105 __atomic_clear( &this.lock, __ATOMIC_RELEASE );
[3381ed7]106 enable_interrupts_noPoll();
[ea7d2b0]107 }
[ea8b2f7]108
109
110 #ifdef __CFA_WITH_VERIFY__
111 extern bool __cfaabi_dbg_in_kernel();
112 #endif
113
[c66f6cb]114 extern "C" {
115 char * strerror(int);
116 }
[6ec07e5]117 #define CHECKED(x) { int err = x; if( err != 0 ) abort("KERNEL ERROR: Operation \"" #x "\" return error %d - %s\n", err, strerror(err)); }
[c66f6cb]118
[ea8b2f7]119 struct __bin_sem_t {
[85b1deb]120 pthread_mutex_t lock;
121 pthread_cond_t cond;
[4069faad]122 int val;
[ea8b2f7]123 };
124
125 static inline void ?{}(__bin_sem_t & this) with( this ) {
[c66f6cb]126 // Create the mutex with error checking
127 pthread_mutexattr_t mattr;
128 pthread_mutexattr_init( &mattr );
129 pthread_mutexattr_settype( &mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
130 pthread_mutex_init(&lock, &mattr);
131
132 pthread_cond_init (&cond, 0p);
[4069faad]133 val = 0;
[ea8b2f7]134 }
135
136 static inline void ^?{}(__bin_sem_t & this) with( this ) {
[c66f6cb]137 CHECKED( pthread_mutex_destroy(&lock) );
138 CHECKED( pthread_cond_destroy (&cond) );
[ea8b2f7]139 }
140
141 static inline void wait(__bin_sem_t & this) with( this ) {
142 verify(__cfaabi_dbg_in_kernel());
[c66f6cb]143 CHECKED( pthread_mutex_lock(&lock) );
[4069faad]144 while(val < 1) {
[85b1deb]145 pthread_cond_wait(&cond, &lock);
146 }
[4069faad]147 val -= 1;
[c66f6cb]148 CHECKED( pthread_mutex_unlock(&lock) );
[ea8b2f7]149 }
150
[92e7631]151 static inline bool post(__bin_sem_t & this) with( this ) {
[4069faad]152 bool needs_signal = false;
153
[c66f6cb]154 CHECKED( pthread_mutex_lock(&lock) );
[4069faad]155 if(val < 1) {
156 val += 1;
157 pthread_cond_signal(&cond);
158 needs_signal = true;
159 }
[c66f6cb]160 CHECKED( pthread_mutex_unlock(&lock) );
[85b1deb]161
[92e7631]162 return needs_signal;
[85b1deb]163 }
[c66f6cb]164
165 #undef CHECKED
[b158d8f]166#endif
Note: See TracBrowser for help on using the repository browser.