source: src/libcfa/bits/locks.h@ 4c3ee8d

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since 4c3ee8d was 85b1deb, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Fix processor halting

  • Property mode set to 100644
File size: 4.0 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
[b10affd]12// Last Modified On : Fri Mar 30 18:18:13 2018
13// Update Count : 9
[ea7d2b0]14//
15
16#pragma once
17
[875a72f]18#include "bits/debug.h"
[ea7d2b0]19#include "bits/defs.h"
[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
[b158d8f]39#if defined( __i386 ) || defined( __x86_64 ) || defined( __ARM_ARCH )
[ea7d2b0]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 {
[13073be]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 };
[ea7d2b0]54 #ifdef __CFA_DEBUG__
[13073be]55 // previous function to acquire the lock
[ea7d2b0]56 const char * prev_name;
[13073be]57 // previous thread to acquire the lock
[ea7d2b0]58 void* prev_thrd;
59 #endif
60} __ALIGN__;
61
[0cf5b79]62#ifdef __cforall
[dbe9b08]63 extern "C" {
64 extern void disable_interrupts();
65 extern void enable_interrupts_noPoll();
66 }
67
[ea7d2b0]68 extern void yield( unsigned int );
69
70 static inline void ?{}( __spinlock_t & this ) {
71 this.lock = 0;
72 }
73
[9181f1d]74
75 #ifdef __CFA_DEBUG__
76 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);
77 #else
78 #define __cfaabi_dbg_record(x, y)
79 #endif
80
[ea7d2b0]81 // Lock the spinlock, return false if already acquired
[36982fc]82 static inline _Bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[13073be]83 _Bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
[dbe9b08]84 if( result ) {
85 disable_interrupts();
[9181f1d]86 __cfaabi_dbg_record( this, caller );
[dbe9b08]87 }
[ea7d2b0]88 return result;
89 }
90
91 // Lock the spinlock, spin if already acquired
[36982fc]92 static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[ea7d2b0]93 #ifndef NOEXPBACK
94 enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
95 unsigned int spin = SPIN_START;
96 #endif
97
98 for ( unsigned int i = 1;; i += 1 ) {
[13073be]99 if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
[ea7d2b0]100 #ifndef NOEXPBACK
101 // exponential spin
102 for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
103
104 // slowly increase by powers of 2
105 if ( i % 64 == 0 ) spin += spin;
106
107 // prevent overflow
108 if ( spin > SPIN_END ) spin = SPIN_START;
109 #else
110 Pause();
111 #endif
112 }
[dbe9b08]113 disable_interrupts();
[9181f1d]114 __cfaabi_dbg_record( this, caller );
[ea7d2b0]115 }
116
117 static inline void unlock( __spinlock_t & this ) {
[dbe9b08]118 enable_interrupts_noPoll();
[13073be]119 __atomic_clear( &this.lock, __ATOMIC_RELEASE );
[ea7d2b0]120 }
[ea8b2f7]121
122
123 #ifdef __CFA_WITH_VERIFY__
124 extern bool __cfaabi_dbg_in_kernel();
125 #endif
126
127 struct __bin_sem_t {
[85b1deb]128 bool signaled;
129 pthread_mutex_t lock;
130 pthread_cond_t cond;
[ea8b2f7]131 };
132
133 static inline void ?{}(__bin_sem_t & this) with( this ) {
[85b1deb]134 signaled = false;
[ea8b2f7]135 pthread_mutex_init(&lock, NULL);
136 pthread_cond_init (&cond, NULL);
137 }
138
139 static inline void ^?{}(__bin_sem_t & this) with( this ) {
140 pthread_mutex_destroy(&lock);
141 pthread_cond_destroy (&cond);
142 }
143
144 static inline void wait(__bin_sem_t & this) with( this ) {
145 verify(__cfaabi_dbg_in_kernel());
146 pthread_mutex_lock(&lock);
[85b1deb]147 if(!signaled) { // this must be a loop, not if!
148 pthread_cond_wait(&cond, &lock);
149 }
150 signaled = false;
[ea8b2f7]151 pthread_mutex_unlock(&lock);
152 }
153
154 static inline void post(__bin_sem_t & this) with( this ) {
155 verify(__cfaabi_dbg_in_kernel());
[85b1deb]156
[ea8b2f7]157 pthread_mutex_lock(&lock);
[85b1deb]158 bool needs_signal = !signaled;
159 signaled = true;
[ea8b2f7]160 pthread_mutex_unlock(&lock);
[85b1deb]161
162 if (needs_signal)
[ea8b2f7]163 pthread_cond_signal(&cond);
[85b1deb]164 }
[b158d8f]165#endif
Note: See TracBrowser for help on using the repository browser.