source: src/libcfa/concurrency/mutex.c@ eaa6430

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 no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since eaa6430 was 8cc7dd1, checked in by Thierry Delisle <tdelisle@…>, 7 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.