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

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since b200492 was 418d31ac, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Added spin count to spin locks as a debugging tool

  • Property mode set to 100644
File size: 2.8 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//
[454f478]7// bits/locks.hfa -- Basic spinlocks that are reused in the system.
8// Used for locks that aren't specific to cforall threads and can be used anywhere
9//
10// *** Must not contain code specific to libcfathread ***
[ea7d2b0]11//
12// Author : Thierry Delisle
13// Created On : Tue Oct 31 15:14:38 2017
[b158d8f]14// Last Modified By : Peter A. Buhr
[fd9b524]15// Last Modified On : Wed Aug 12 14:18:07 2020
16// Update Count : 13
[ea7d2b0]17//
18
19#pragma once
20
[73abe95]21#include "bits/debug.hfa"
22#include "bits/defs.hfa"
[ea8b2f7]23#include <assert.h>
24
[ea7d2b0]25struct __spinlock_t {
[13073be]26 // Wrap in struct to prevent false sharing with debug info
[3aeee3c]27 volatile bool lock;
[ea7d2b0]28 #ifdef __CFA_DEBUG__
[13073be]29 // previous function to acquire the lock
[ea7d2b0]30 const char * prev_name;
[13073be]31 // previous thread to acquire the lock
[ea7d2b0]32 void* prev_thrd;
[418d31ac]33 // keep track of number of times we had to spin, just in case the number is unexpectedly huge
34 size_t spin_count;
[ea7d2b0]35 #endif
[3aeee3c]36};
[ea7d2b0]37
[0cf5b79]38#ifdef __cforall
[dbe9b08]39 extern "C" {
[2026bb6]40 extern void disable_interrupts() OPTIONAL_THREAD;
[a3821fa]41 extern void enable_interrupts( bool poll = true ) OPTIONAL_THREAD;
[1997b4e]42
43 #ifdef __CFA_DEBUG__
[ae66348]44 void __cfaabi_dbg_record_lock(__spinlock_t & this, const char prev_name[]);
[1997b4e]45 #else
[ae66348]46 #define __cfaabi_dbg_record_lock(x, y)
[1997b4e]47 #endif
[dbe9b08]48 }
49
[ea7d2b0]50 static inline void ?{}( __spinlock_t & this ) {
51 this.lock = 0;
[418d31ac]52 #ifdef __CFA_DEBUG__
53 this.spin_count = 0;
54 #endif
[ea7d2b0]55 }
56
57 // Lock the spinlock, return false if already acquired
[93c2e0a]58 static inline bool try_lock ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[3381ed7]59 disable_interrupts();
[93c2e0a]60 bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
[dbe9b08]61 if( result ) {
[ae66348]62 __cfaabi_dbg_record_lock( this, caller );
[3381ed7]63 } else {
[a3821fa]64 enable_interrupts( false );
[dbe9b08]65 }
[ea7d2b0]66 return result;
67 }
68
69 // Lock the spinlock, spin if already acquired
[36982fc]70 static inline void lock( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
[ea7d2b0]71 #ifndef NOEXPBACK
72 enum { SPIN_START = 4, SPIN_END = 64 * 1024, };
73 unsigned int spin = SPIN_START;
74 #endif
75
[3381ed7]76 disable_interrupts();
[ea7d2b0]77 for ( unsigned int i = 1;; i += 1 ) {
[13073be]78 if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
[418d31ac]79 #ifdef __CFA_DEBUG__
80 this.spin_count++;
81 #endif
[ea7d2b0]82 #ifndef NOEXPBACK
83 // exponential spin
84 for ( volatile unsigned int s = 0; s < spin; s += 1 ) Pause();
85
86 // slowly increase by powers of 2
87 if ( i % 64 == 0 ) spin += spin;
88
89 // prevent overflow
90 if ( spin > SPIN_END ) spin = SPIN_START;
91 #else
92 Pause();
93 #endif
94 }
[ae66348]95 __cfaabi_dbg_record_lock( this, caller );
[ea7d2b0]96 }
97
98 static inline void unlock( __spinlock_t & this ) {
[13073be]99 __atomic_clear( &this.lock, __ATOMIC_RELEASE );
[a3821fa]100 enable_interrupts( false );
[ea7d2b0]101 }
[b158d8f]102#endif
Note: See TracBrowser for help on using the repository browser.