source: src/libcfa/bits/locks.h@ 6ecc079

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 new-env no_list persistent-indexer pthread-emulation qualifiedEnum with_gc
Last change on this file since 6ecc079 was 2e9aed4, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Fixed non-preemptive locks

  • Property mode set to 100644
File size: 3.6 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.h -- 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 Dec 8 16:02:22 2017
13// Update Count : 1
14//
15
16#pragma once
17
18#include "bits/debug.h"
19#include "bits/defs.h"
20
21// pause to prevent excess processor bus usage
22#if defined( __sparc )
23 #define Pause() __asm__ __volatile__ ( "rd %ccr,%g0" )
24#elif defined( __i386 ) || defined( __x86_64 )
25 #define Pause() __asm__ __volatile__ ( "pause" : : : )
26#elif defined( __ARM_ARCH )
27 #define Pause() __asm__ __volatile__ ( "nop" : : : )
28#else
29 #error unsupported architecture
30#endif
31
32#if defined( __i386 ) || defined( __x86_64 ) || defined( __ARM_ARCH )
33 // Intel recommendation
34 #define __ALIGN__ __attribute__(( aligned (128) ))
35#elif defined( __sparc )
36 #define __ALIGN__ CALIGN
37#else
38 #error unsupported architecture
39#endif
40
41#if __SIZEOF_SIZE_T__ == 8
42 #define __lock_test_and_test_and_set( lock ) (lock) == 0 && __sync_lock_test_and_set_8( &(lock), 1 ) == 0
43 #define __lock_release( lock ) __sync_lock_release_8( &(lock) );
44#elif __SIZEOF_SIZE_T__ == 4
45 #define __lock_test_and_test_and_set( lock ) (lock) == 0 && __sync_lock_test_and_set_4( &(lock), 1 ) == 0
46 #define __lock_release( lock ) __sync_lock_release_4( &(lock) );
47#else
48 #error unsupported architecture
49#endif
50
51struct __spinlock_t {
52 __ALIGN__ volatile size_t lock;
53 #ifdef __CFA_DEBUG__
54 const char * prev_name;
55 void* prev_thrd;
56 #endif
57} __ALIGN__;
58
59#ifdef __cforall
60 extern "C" {
61 extern void disable_interrupts();
62 extern void enable_interrupts_noPoll();
63 }
64
65 extern void yield( unsigned int );
66 extern thread_local struct thread_desc * volatile this_thread;
67 extern thread_local struct processor * volatile this_processor;
68
69 static inline void ?{}( __spinlock_t & this ) {
70 this.lock = 0;
71 }
72
73 // Lock the spinlock, return false if already acquired
74 static inline _Bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
75 _Bool result = __lock_test_and_test_and_set( this.lock );
76 if( result ) {
77 disable_interrupts();
78 __cfaabi_dbg_debug_do(
79 this.prev_name = caller;
80 this.prev_thrd = this_thread;
81 )
82 }
83 return result;
84 }
85
86 // Lock the spinlock, spin if already acquired
87 static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
88 #ifndef NOEXPBACK
89 enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
90 unsigned int spin = SPIN_START;
91 #endif
92
93 for ( unsigned int i = 1;; i += 1 ) {
94 if ( __lock_test_and_test_and_set( this.lock ) ) break;
95 #ifndef NOEXPBACK
96 // exponential spin
97 for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
98
99 // slowly increase by powers of 2
100 if ( i % 64 == 0 ) spin += spin;
101
102 // prevent overflow
103 if ( spin > SPIN_END ) spin = SPIN_START;
104 #else
105 Pause();
106 #endif
107 }
108 disable_interrupts();
109 __cfaabi_dbg_debug_do(
110 this.prev_name = caller;
111 this.prev_thrd = this_thread;
112 )
113 }
114
115 // // Lock the spinlock, yield if already acquired
116 // static inline void lock_yield( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
117 // for ( unsigned int i = 1;; i += 1 ) {
118 // if ( __lock_test_and_test_and_set( this.lock ) ) break;
119 // yield( i );
120 // }
121 // disable_interrupts();
122 // __cfaabi_dbg_debug_do(
123 // this.prev_name = caller;
124 // this.prev_thrd = this_thread;
125 // )
126 // }
127
128 static inline void unlock( __spinlock_t & this ) {
129 enable_interrupts_noPoll();
130 __lock_release( this.lock );
131 }
132#endif
Note: See TracBrowser for help on using the repository browser.