// -*- Mode: CFA -*- // // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // mutex.c -- // // Author : Thierry Delisle // Created On : Fri May 25 01:37:11 2018 // Last Modified By : Thierry Delisle // Last Modified On : Fri May 25 01:37:51 2018 // Update Count : 0 // #define __cforall_thread__ #include "mutex.hfa" #include "kernel_private.hfa" //----------------------------------------------------------------------------- // Locks // Exclusive lock - non-recursive // --- void ?{}(mutex_lock & this) { this.lock{}; this.blocked_threads{}; } void ^?{}(mutex_lock & this) { // default } void lock(mutex_lock & this) with(this) { lock( lock __cfaabi_dbg_ctx2 ); if( is_locked ) { append( blocked_threads, kernelTLS.this_thread ); BlockInternal( &lock ); } else { is_locked = true; unlock( lock ); } } bool try_lock(mutex_lock & this) with(this) { bool ret = false; lock( lock __cfaabi_dbg_ctx2 ); if( !is_locked ) { ret = true; is_locked = true; } unlock( lock ); return ret; } void unlock(mutex_lock & this) { lock( this.lock __cfaabi_dbg_ctx2 ); this.is_locked = (this.blocked_threads != 0); WakeThread( pop_head( this.blocked_threads ) ); unlock( this.lock ); } // Exclusive lock - non-recursive // --- void ?{}(recursive_mutex_lock & this) { this.lock{}; this.blocked_threads{}; this.owner = NULL; this.recursion_count = 0; } void ^?{}(recursive_mutex_lock & this) { // default } void lock(recursive_mutex_lock & this) with(this) { lock( lock __cfaabi_dbg_ctx2 ); if( owner == NULL ) { owner = kernelTLS.this_thread; recursion_count = 1; unlock( lock ); } else if( owner == kernelTLS.this_thread ) { recursion_count++; unlock( lock ); } else { append( blocked_threads, kernelTLS.this_thread ); BlockInternal( &lock ); } } bool try_lock(recursive_mutex_lock & this) with(this) { bool ret = false; lock( lock __cfaabi_dbg_ctx2 ); if( owner == NULL ) { owner = kernelTLS.this_thread; recursion_count = 1; ret = true; } else if( owner == kernelTLS.this_thread ) { recursion_count++; ret = true; } unlock( lock ); return ret; } void unlock(recursive_mutex_lock & this) with(this) { lock( lock __cfaabi_dbg_ctx2 ); recursion_count--; if( recursion_count == 0 ) { thread_desc * thrd = pop_head( blocked_threads ); owner = thrd; recursion_count = (thrd ? 1 : 0); WakeThread( thrd ); } unlock( lock ); } //----------------------------------------------------------------------------- // Conditions void ?{}(condition_variable & this) { this.blocked_threads{}; } void ^?{}(condition_variable & this) { // default } void notify_one(condition_variable & this) with(this) { lock( lock __cfaabi_dbg_ctx2 ); WakeThread( pop_head( this.blocked_threads ) ); unlock( lock ); } void notify_all(condition_variable & this) with(this) { lock( lock __cfaabi_dbg_ctx2 ); while(this.blocked_threads) { WakeThread( pop_head( this.blocked_threads ) ); } unlock( lock ); } void wait(condition_variable & this) { lock( this.lock __cfaabi_dbg_ctx2 ); append( this.blocked_threads, kernelTLS.this_thread ); BlockInternal( &this.lock ); } forall(dtype L | is_lock(L)) void wait(condition_variable & this, L & l) { lock( this.lock __cfaabi_dbg_ctx2 ); append( this.blocked_threads, kernelTLS.this_thread ); void __unlock(void) { unlock(l); unlock(this.lock); } BlockInternal( __unlock ); lock(l); } //----------------------------------------------------------------------------- // Scopes forall(dtype L | is_lock(L)) void lock_all ( L * locks[], size_t count) { // Sort locks based on addresses __libcfa_small_sort(locks, count); // Lock all for(size_t i = 0; i < count; i++) { L * l = locks[i]; lock( *l ); } } forall(dtype L | is_lock(L)) void unlock_all( L * locks[], size_t count) { // Lock all for(size_t i = 0; i < count; i++) { L * l = locks[i]; unlock( *l ); } }