source: src/libcfa/concurrency/mutex.c @ 460bd3a

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since 460bd3a was 8cc7dd1, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Condition variables now properly reacquire locks on wake-up

  • Property mode set to 100644
File size: 4.0 KB
Line 
1
2//                              -*- Mode: CFA -*-
3//
4// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
5//
6// The contents of this file are covered under the licence agreement in the
7// file "LICENCE" distributed with Cforall.
8//
9// mutex.c --
10//
11// Author           : Thierry Delisle
12// Created On       : Fri May 25 01:37:11 2018
13// Last Modified By : Thierry Delisle
14// Last Modified On : Fri May 25 01:37:51 2018
15// Update Count     : 0
16//
17
18#include "mutex"
19
20#include "kernel_private.h"
21
22//-----------------------------------------------------------------------------
23// Locks
24
25// Exclusive lock - non-recursive
26// ---
27void ?{}(mutex_lock & this) {
28        this.lock{};
29        this.blocked_threads{};
30}
31
32void ^?{}(mutex_lock & this) {
33        // default
34}
35
36void lock(mutex_lock & this) with(this) {
37        lock( lock __cfaabi_dbg_ctx2 );
38        if( is_locked ) {
39                append( blocked_threads, kernelTLS.this_thread );
40                BlockInternal( &lock );
41        }
42        else {
43                is_locked = true;
44                unlock( lock );
45        }
46}
47
48bool try_lock(mutex_lock & this) with(this) {
49        bool ret = false;
50        lock( lock __cfaabi_dbg_ctx2 );
51        if( !is_locked ) {
52                ret = true;
53                is_locked = true;
54        }
55        unlock( lock );
56        return ret;
57}
58
59void unlock(mutex_lock & this) {
60        lock( this.lock __cfaabi_dbg_ctx2 );
61        this.is_locked = (this.blocked_threads != 0);
62        WakeThread(
63                pop_head( this.blocked_threads )
64        );
65        unlock( this.lock );
66}
67
68// Exclusive lock - non-recursive
69// ---
70void ?{}(recursive_mutex_lock & this) {
71        this.lock{};
72        this.blocked_threads{};
73        this.owner = NULL;
74        this.recursion_count = 0;
75}
76
77void ^?{}(recursive_mutex_lock & this) {
78        // default
79}
80
81void lock(recursive_mutex_lock & this) with(this) {
82        lock( lock __cfaabi_dbg_ctx2 );
83        if( owner == NULL ) {
84                owner = kernelTLS.this_thread;
85                recursion_count = 1;
86                unlock( lock );
87        }
88        else if( owner == kernelTLS.this_thread ) {
89                recursion_count++;
90                unlock( lock );
91        }
92        else {
93                append( blocked_threads, kernelTLS.this_thread );
94                BlockInternal( &lock );
95        }
96}
97
98bool try_lock(recursive_mutex_lock & this) with(this) {
99        bool ret = false;
100        lock( lock __cfaabi_dbg_ctx2 );
101        if( owner == NULL ) {
102                owner = kernelTLS.this_thread;
103                recursion_count = 1;
104                ret = true;
105        }
106        else if( owner == kernelTLS.this_thread ) {
107                recursion_count++;
108                ret = true;
109        }
110        unlock( lock );
111        return ret;
112}
113
114void unlock(recursive_mutex_lock & this) with(this) {
115        lock( lock __cfaabi_dbg_ctx2 );
116        recursion_count--;
117        if( recursion_count == 0 ) {
118                thread_desc * thrd = pop_head( blocked_threads );
119                owner = thrd;
120                recursion_count = (thrd ? 1 : 0);
121                WakeThread( thrd );
122        }
123        unlock( lock );
124}
125
126//-----------------------------------------------------------------------------
127// Conditions
128void ?{}(condition_variable & this) {
129        this.blocked_threads{};
130}
131
132void ^?{}(condition_variable & this) {
133        // default
134}
135
136void notify_one(condition_variable & this) with(this) {
137        lock( lock __cfaabi_dbg_ctx2 );
138        WakeThread(
139                pop_head( this.blocked_threads )
140        );
141        unlock( lock );
142}
143
144void notify_all(condition_variable & this) with(this) {
145        lock( lock __cfaabi_dbg_ctx2 );
146        while(this.blocked_threads) {
147                WakeThread(
148                        pop_head( this.blocked_threads )
149                );
150        }
151        unlock( lock );
152}
153
154void wait(condition_variable & this) {
155        lock( this.lock __cfaabi_dbg_ctx2 );
156        append( this.blocked_threads, kernelTLS.this_thread );
157        BlockInternal( &this.lock );
158}
159
160forall(dtype L | is_lock(L))
161void wait(condition_variable & this, L & l) {
162        lock( this.lock __cfaabi_dbg_ctx2 );
163        append( this.blocked_threads, kernelTLS.this_thread );
164        void __unlock(void) {
165                unlock(l);
166                unlock(this.lock);
167        }
168        BlockInternal( __unlock );
169        lock(l);
170}
171
172//-----------------------------------------------------------------------------
173// Scopes
174forall(dtype L | is_lock(L))
175void lock_all  ( L * locks[], size_t count) {
176        // Sort locks based on addresses
177        __libcfa_small_sort(locks, count);
178
179        // Lock all
180        for(size_t i = 0; i < count; i++) {
181                L * l = locks[i];
182                lock( *l );
183        }
184}
185
186forall(dtype L | is_lock(L))
187void unlock_all( L * locks[], size_t count) {
188        // Lock all
189        for(size_t i = 0; i < count; i++) {
190                L * l = locks[i];
191                unlock( *l );
192        }
193}
Note: See TracBrowser for help on using the repository browser.