// -*- 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 -- // // Author : Thierry Delisle // Created On : Fri May 25 01:24:09 2018 // Last Modified By : Thierry Delisle // Last Modified On : Fri May 25 01:24:12 2018 // Update Count : 0 // #pragma once #include #include "bits/algorithm.hfa" #include "bits/locks.hfa" #include "invoke.h" #include "time_t.hfa" //----------------------------------------------------------------------------- // Locks // Exclusive lock - non-recursive // --- struct mutex_lock { // Spin lock used for mutual exclusion __spinlock_t lock; // List of blocked threads __queue_t(struct thread_desc) blocked_threads; // Locked flag bool is_locked; }; void ?{}(mutex_lock & this); void ^?{}(mutex_lock & this); void lock(mutex_lock & this); bool try_lock(mutex_lock & this); void unlock(mutex_lock & this); // Exclusive lock - recursive // --- struct recursive_mutex_lock{ // Spin lock used for mutual exclusion __spinlock_t lock; // List of blocked threads __queue_t(struct thread_desc) blocked_threads; // Current thread owning the lock struct thread_desc * owner; // Number of recursion level size_t recursion_count; }; void ?{}(recursive_mutex_lock & this); void ^?{}(recursive_mutex_lock & this); void lock(recursive_mutex_lock & this); bool try_lock(recursive_mutex_lock & this); void unlock(recursive_mutex_lock & this); trait is_lock(dtype L | sized(L)) { void lock (L &); void unlock(L &); }; //----------------------------------------------------------------------------- // Condition variables struct condition_variable { // Spin lock used for mutual exclusion __spinlock_t lock; // List of blocked threads __queue_t(struct thread_desc) blocked_threads; }; void ?{}(condition_variable & this); void ^?{}(condition_variable & this); void notify_one(condition_variable & this); void notify_all(condition_variable & this); void wait(condition_variable & this); forall(dtype L | is_lock(L)) void wait(condition_variable & this, L & l); //----------------------------------------------------------------------------- // Scopes forall(dtype L | is_lock(L)) { #if !defined( __TUPLE_ARRAYS_EXIST__ ) void lock ( L * locks [], size_t count); void unlock( L * locks [], size_t count); struct lock_scope { L ** locks; size_t count; }; static inline void ?{}(lock_scope(L) & this) { this.locks = NULL; this.count = 0; } static inline void ^?{}(lock_scope(L) & this) { if(this.count > 0) { unlock(this.locks, this.count); } } static inline lock_scope(L) lock( L * locks [], size_t count, lock_scope(L) & scope) { lock(locks, count); scope.locks = locks; scope.count = count; } static inline void unlock( lock_scope(L) & this ) { unlock(this.locks, this.count); this.count = 0; } static inline void release( lock_scope(L) & this ) { this.count = 0; } #else void lock( [L &...] locks ); void unlock( [L &...] locks ); forall(size_t N) struct lock_scope { bool released; [L &... N] locks; }; void ?{}(lock_scope(L) & this) = void; void ?{}(lock_scope(L) & this, lock_scope(L) other) = void; void ?move?(lock_scope(L) & this, lock_scope(L) & other) = default; static inline void ^?{}(lock_scope(L) & this) { if( !this.released ) { unlock(this.locks); } } forall(size_t N) static inline lock_scope(L, N) lock( [L &...] locks ) { lock(locks); return @{false, locks}; } static inline void unlock( lock_scope(L) & this ) { unlock(this.locks); this.released = true } static inline void release( lock_scope(L) & this ) { this.released = true; } #endif }