source: src/libcfa/bits/locks.h@ 3ce0d440

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 3ce0d440 was 13073be, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Fix atomic builtins in libcfa and prelude

  • Property mode set to 100644
File size: 3.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"
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" : : : )
[b158d8f]26#elif defined( __ARM_ARCH )
27 #define Pause() __asm__ __volatile__ ( "nop" : : : )
[ea7d2b0]28#else
29 #error unsupported architecture
30#endif
31
[b158d8f]32#if defined( __i386 ) || defined( __x86_64 ) || defined( __ARM_ARCH )
[ea7d2b0]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
41struct __spinlock_t {
[13073be]42 // Wrap in struct to prevent false sharing with debug info
43 struct {
44 // Align lock on 128-bit boundary
45 __ALIGN__ volatile _Bool lock;
46 };
[ea7d2b0]47 #ifdef __CFA_DEBUG__
[13073be]48 // previous function to acquire the lock
[ea7d2b0]49 const char * prev_name;
[13073be]50 // previous thread to acquire the lock
[ea7d2b0]51 void* prev_thrd;
52 #endif
53} __ALIGN__;
54
[0cf5b79]55#ifdef __cforall
[dbe9b08]56 extern "C" {
57 extern void disable_interrupts();
58 extern void enable_interrupts_noPoll();
59 }
60
[ea7d2b0]61 extern void yield( unsigned int );
62
63 static inline void ?{}( __spinlock_t & this ) {
64 this.lock = 0;
65 }
66
[9181f1d]67
68 #ifdef __CFA_DEBUG__
69 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);
70 #else
71 #define __cfaabi_dbg_record(x, y)
72 #endif
73
[ea7d2b0]74 // Lock the spinlock, return false if already acquired
[36982fc]75 static inline _Bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[13073be]76 _Bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
[dbe9b08]77 if( result ) {
78 disable_interrupts();
[9181f1d]79 __cfaabi_dbg_record( this, caller );
[dbe9b08]80 }
[ea7d2b0]81 return result;
82 }
83
84 // Lock the spinlock, spin if already acquired
[36982fc]85 static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[ea7d2b0]86 #ifndef NOEXPBACK
87 enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
88 unsigned int spin = SPIN_START;
89 #endif
90
91 for ( unsigned int i = 1;; i += 1 ) {
[13073be]92 if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
[ea7d2b0]93 #ifndef NOEXPBACK
94 // exponential spin
95 for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
96
97 // slowly increase by powers of 2
98 if ( i % 64 == 0 ) spin += spin;
99
100 // prevent overflow
101 if ( spin > SPIN_END ) spin = SPIN_START;
102 #else
103 Pause();
104 #endif
105 }
[dbe9b08]106 disable_interrupts();
[9181f1d]107 __cfaabi_dbg_record( this, caller );
[ea7d2b0]108 }
109
110 static inline void unlock( __spinlock_t & this ) {
[dbe9b08]111 enable_interrupts_noPoll();
[13073be]112 __atomic_clear( &this.lock, __ATOMIC_RELEASE );
[ea7d2b0]113 }
[b158d8f]114#endif
Note: See TracBrowser for help on using the repository browser.