Rev 5599 | Rev 6078 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5599 | Rev 5605 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; Synhronization for MenuetOS. ;; |
6 | ;; Synhronization for MenuetOS. ;; |
7 | ;; Author: Halyavin Andrey, halyavin@land.ru ;; |
7 | ;; Author: Halyavin Andrey, halyavin@land.ru ;; |
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
9 | 9 | ||
10 | $Revision: 5599 $ |
10 | $Revision: 5605 $ |
11 | 11 | ||
12 | align 4 |
12 | align 4 |
13 | ;struct futex* __fastcall create_futex(int *ptr) |
13 | ;struct futex* __fastcall create_futex(int *ptr) |
14 | create_futex: |
14 | create_futex: |
15 | push ecx |
15 | push ecx |
16 | mov ecx, sizeof.FUTEX |
16 | mov ecx, sizeof.FUTEX |
17 | call create_object |
17 | call create_object |
18 | pop ecx |
18 | pop ecx |
19 | test eax, eax |
19 | test eax, eax |
20 | jz .fail |
20 | jz .fail |
21 | 21 | ||
22 | mov [eax+FUTEX.magic], 'FUTX' |
22 | mov [eax+FUTEX.magic], 'FUTX' |
23 | mov [eax+FUTEX.destroy], 0 |
23 | mov [eax+FUTEX.destroy], 0 |
24 | mov [eax+FUTEX.pointer], ecx |
24 | mov [eax+FUTEX.pointer], ecx |
25 | lea ecx, [eax+FUTEX.wait_list] |
25 | lea ecx, [eax+FUTEX.wait_list] |
26 | list_init ecx |
26 | list_init ecx |
27 | mov [eax+FUTEX.flags], 0 |
27 | mov [eax+FUTEX.flags], 0 |
28 | .fail: |
28 | .fail: |
29 | ret |
29 | ret |
30 | 30 | ||
31 | align 4 |
31 | align 4 |
32 | ;int __fastcall destroy_futex(struct futex *futex) |
32 | ;int __fastcall destroy_futex(struct futex *futex) |
33 | destroy_futex: |
33 | destroy_futex: |
34 | push esi |
34 | push esi |
35 | mov esi, [current_process] |
35 | mov esi, [current_process] |
36 | mov edx, [ecx+FUTEX.handle] |
36 | mov edx, [ecx+FUTEX.handle] |
37 | 37 | ||
38 | pushfd |
38 | pushfd |
39 | cli |
39 | cli |
40 | 40 | ||
41 | lea eax, [ecx+FUTEX.wait_list] |
41 | lea eax, [ecx+FUTEX.wait_list] |
42 | cmp eax, [eax+LHEAD.next] |
42 | cmp eax, [eax+LHEAD.next] |
43 | jne .fail |
43 | jne .fail |
44 | 44 | ||
45 | mov eax, [esi+PROC.ht_next] |
45 | mov eax, [esi+PROC.ht_next] |
46 | mov [esi+PROC.htab+edx*4], eax |
46 | mov [esi+PROC.htab+edx*4], eax |
47 | mov [esi+PROC.ht_next], edx |
47 | mov [esi+PROC.ht_next], edx |
48 | inc [esi+PROC.ht_free] |
48 | inc [esi+PROC.ht_free] |
49 | 49 | ||
50 | popfd |
50 | popfd |
51 | pop esi |
51 | pop esi |
52 | 52 | ||
53 | mov eax, ecx |
53 | mov eax, ecx |
54 | call free |
54 | call free |
55 | xor eax, eax |
55 | xor eax, eax |
56 | ret |
56 | ret |
57 | 57 | ||
58 | .fail: |
58 | .fail: |
59 | popfd |
59 | popfd |
60 | pop esi |
60 | pop esi |
61 | mov eax, -1 |
61 | mov eax, -1 |
62 | ret |
62 | ret |
63 | 63 | ||
64 | 64 | ||
65 | iglobal |
65 | iglobal |
66 | align 4 |
66 | align 4 |
67 | f77call: |
67 | f77call: |
68 | dd f77.futex_init ;0 |
68 | dd f77.futex_init ;0 |
69 | dd f77.futex_destroy ;1 |
69 | dd f77.futex_destroy ;1 |
70 | dd f77.futex_wait ;2 |
70 | dd f77.futex_wait ;2 |
71 | dd f77.futex_wake ;3 |
71 | dd f77.futex_wake ;3 |
72 | .end: |
72 | .end: |
73 | endg |
73 | endg |
74 | 74 | ||
75 | align 4 |
75 | align 4 |
76 | sys_synchronization: |
76 | sys_synchronization: |
77 | f77: |
77 | f77: |
78 | test ebx, ebx |
78 | test ebx, ebx |
79 | jz .futex_init |
79 | jz .futex_init |
80 | 80 | ||
81 | cmp ebx, (f77call.end-f77call)/4 |
81 | cmp ebx, (f77call.end-f77call)/4 |
82 | jae .fail |
82 | jae .fail |
83 | 83 | ||
84 | cmp ecx, STDERR_FILENO |
84 | cmp ecx, STDERR_FILENO |
85 | jbe .fail |
85 | jbe .fail |
86 | cmp ecx, (PROC.pdt_0 - PROC.htab)/4 |
86 | cmp ecx, (PROC.pdt_0 - PROC.htab)/4 |
87 | jae .fail |
87 | jae .fail |
88 | 88 | ||
89 | mov edi, [current_process] |
89 | mov edi, [current_process] |
90 | mov ebp, [edi+PROC.htab+ecx*4] |
90 | mov ebp, [edi+PROC.htab+ecx*4] |
91 | 91 | ||
92 | cmp [ebp+FUTEX.magic], 'FUTX' |
92 | cmp [ebp+FUTEX.magic], 'FUTX' |
93 | jne .fail |
93 | jne .fail |
94 | cmp [ebp+FUTEX.handle], ecx |
94 | cmp [ebp+FUTEX.handle], ecx |
95 | jne .fail |
95 | jne .fail |
96 | 96 | ||
97 | jmp dword [f77call+ebx*4] |
97 | jmp dword [f77call+ebx*4] |
98 | 98 | ||
99 | .fail: |
99 | .fail: |
100 | mov [esp+SYSCALL_STACK._eax], -1 |
100 | mov [esp+SYSCALL_STACK._eax], -1 |
101 | ret |
101 | ret |
102 | 102 | ||
103 | align 4 |
103 | align 4 |
104 | .futex_init: |
104 | .futex_init: |
105 | call create_futex |
105 | call create_futex |
106 | test eax, eax |
106 | test eax, eax |
107 | jz @F |
107 | jz @F |
108 | mov eax, [eax+FUTEX.handle] |
108 | mov eax, [eax+FUTEX.handle] |
109 | @@: |
109 | @@: |
110 | mov [esp+SYSCALL_STACK._eax], eax |
110 | mov [esp+SYSCALL_STACK._eax], eax |
111 | ret |
111 | ret |
112 | 112 | ||
113 | 113 | ||
114 | align 4 |
114 | align 4 |
115 | ;ecx futex handle |
115 | ;ecx futex handle |
116 | ;edi current process |
116 | ;edi current process |
117 | ;ebp futex object |
117 | ;ebp futex object |
118 | .futex_destroy: |
118 | .futex_destroy: |
119 | mov ecx, ebp |
119 | mov ecx, ebp |
120 | call destroy_futex |
120 | call destroy_futex |
121 | mov [esp+SYSCALL_STACK._eax], eax |
121 | mov [esp+SYSCALL_STACK._eax], eax |
122 | ret |
122 | ret |
123 | 123 | ||
124 | align 4 |
124 | align 4 |
125 | ;ecx futex handle |
125 | ;ecx futex handle |
126 | ;edx control value |
126 | ;edx control value |
127 | ;esi timeout |
127 | ;esi timeout |
128 | ;edi current process |
128 | ;edi current process |
129 | ;ebp futex object |
129 | ;ebp futex object |
130 | .futex_wait: |
130 | .futex_wait: |
131 | test esi, esi |
131 | test esi, esi |
132 | jnz .futex_wait_timeout |
132 | jnz .futex_wait_timeout |
133 | mov ecx, [ebp+FUTEX.pointer] |
133 | mov ecx, [ebp+FUTEX.pointer] |
134 | mov eax, edx |
134 | mov eax, edx |
135 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
135 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
136 | jz .wait_slow |
136 | jz .wait_slow |
137 | 137 | ||
138 | mov [esp+SYSCALL_STACK._eax], 0 |
138 | mov [esp+SYSCALL_STACK._eax], 0 |
139 | ret |
139 | ret |
140 | 140 | ||
141 | .wait_slow: |
141 | .wait_slow: |
142 | pushfd |
142 | pushfd |
143 | cli |
143 | cli |
144 | 144 | ||
145 | sub esp, sizeof.MUTEX_WAITER |
145 | sub esp, sizeof.MUTEX_WAITER |
146 | mov ebx, [TASK_BASE] |
146 | mov ebx, [TASK_BASE] |
147 | mov [ebx+TASKDATA.state], 1 |
147 | mov [ebx+TASKDATA.state], 1 |
148 | mov [esp+MUTEX_WAITER.task], ebx |
148 | mov [esp+MUTEX_WAITER.task], ebx |
149 | lea esi, [ebp+FUTEX.wait_list] |
149 | lea esi, [ebp+FUTEX.wait_list] |
150 | 150 | ||
151 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
151 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
152 | 152 | ||
153 | .again: |
153 | .again: |
154 | call change_task |
154 | call change_task |
155 | 155 | ||
156 | lock cmpxchg [ecx], edx |
156 | lock cmpxchg [ecx], edx |
157 | jz .again |
157 | jz .again |
158 | 158 | ||
159 | list_del esp |
159 | list_del esp |
160 | add esp, sizeof.MUTEX_WAITER |
160 | add esp, sizeof.MUTEX_WAITER |
161 | 161 | ||
162 | popfd |
162 | popfd |
163 | mov [esp+SYSCALL_STACK._eax], 0 |
163 | mov [esp+SYSCALL_STACK._eax], 0 |
164 | ret |
164 | ret |
165 | 165 | ||
166 | align 4 |
166 | align 4 |
167 | ;ecx futex handle |
167 | ;ecx futex handle |
168 | ;edx control value |
168 | ;edx control value |
169 | ;esi timeout |
169 | ;esi timeout |
170 | ;edi current process |
170 | ;edi current process |
171 | ;ebp futex object |
171 | ;ebp futex object |
172 | 172 | ||
173 | .futex_wait_timeout: |
173 | .futex_wait_timeout: |
174 | mov ecx, [ebp+FUTEX.pointer] |
174 | mov ecx, [ebp+FUTEX.pointer] |
175 | mov eax, edx |
175 | mov eax, edx |
176 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
176 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
177 | jz .wait_slow_timeout |
177 | jz .wait_slow_timeout |
178 | 178 | ||
179 | mov [esp+SYSCALL_STACK._eax], 0 |
179 | mov [esp+SYSCALL_STACK._eax], 0 |
180 | ret |
180 | ret |
181 | 181 | ||
182 | align 4 |
182 | align 4 |
183 | .wait_test: |
183 | .wait_test: |
184 | xor eax, eax |
184 | xor eax, eax |
185 | ret |
185 | ret |
186 | 186 | ||
187 | .wait_slow_timeout: |
187 | .wait_slow_timeout: |
188 | pushfd |
188 | pushfd |
189 | cli |
189 | cli |
190 | 190 | ||
191 | sub esp, sizeof.MUTEX_WAITER |
191 | sub esp, sizeof.MUTEX_WAITER |
192 | 192 | ||
193 | mov ebx, [current_slot] |
193 | mov ebx, [current_slot] |
194 | mov [ebx+APPDATA.wait_test], f77.wait_test |
194 | mov [ebx+APPDATA.wait_test], f77.wait_test |
195 | mov [ebx+APPDATA.wait_timeout], esi |
195 | mov [ebx+APPDATA.wait_timeout], esi |
196 | mov [ebx+APPDATA.wait_param], ebp |
196 | mov [ebx+APPDATA.wait_param], ebp |
197 | mov eax, [timer_ticks] |
197 | mov eax, [timer_ticks] |
198 | mov [ebx+APPDATA.wait_begin], eax |
198 | mov [ebx+APPDATA.wait_begin], eax |
199 | mov eax, [TASK_BASE] |
199 | mov eax, [TASK_BASE] |
200 | mov [eax+TASKDATA.state], 5 |
200 | mov [eax+TASKDATA.state], 5 |
201 | 201 | ||
202 | mov [esp+MUTEX_WAITER.task], ebx |
202 | mov [esp+MUTEX_WAITER.task], ebx |
203 | lea esi, [ebp+FUTEX.wait_list] |
203 | lea esi, [ebp+FUTEX.wait_list] |
204 | 204 | ||
205 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
205 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
206 | 206 | ||
207 | .again_timeout: |
207 | .again_timeout: |
208 | call change_task |
208 | call change_task |
209 | mov eax, [ebx+APPDATA.wait_param] |
209 | mov eax, [ebx+APPDATA.wait_param] |
210 | test eax, eax |
210 | test eax, eax |
211 | jz .timeout |
211 | jz .timeout |
212 | 212 | ||
213 | lock cmpxchg [ecx], edx |
213 | lock cmpxchg [ecx], edx |
214 | jz .again_timeout |
214 | jz .again_timeout |
215 | @@: |
215 | @@: |
216 | list_del esp |
216 | list_del esp |
217 | add esp, sizeof.MUTEX_WAITER |
217 | add esp, sizeof.MUTEX_WAITER |
218 | 218 | ||
219 | popfd |
219 | popfd |
220 | mov [esp+SYSCALL_STACK._eax], 0 |
220 | mov [esp+SYSCALL_STACK._eax], 0 |
221 | ret |
221 | ret |
222 | 222 | ||
223 | .timeout: |
223 | .timeout: |
224 | list_del esp |
224 | list_del esp |
225 | add esp, sizeof.MUTEX_WAITER |
225 | add esp, sizeof.MUTEX_WAITER |
226 | 226 | ||
227 | popfd |
227 | popfd |
228 | mov [esp+SYSCALL_STACK._eax], -1 |
228 | mov [esp+SYSCALL_STACK._eax], -1 |
229 | ret |
229 | ret |
230 | 230 | ||
231 | 231 | ||
232 | align 4 |
232 | align 4 |
233 | ;ecx futex handle |
233 | ;ecx futex handle |
- | 234 | ;edx numder of threads |
|
234 | ;esi current process |
235 | ;edi current process |
235 | ;edi futex object |
236 | ;ebp futex object |
236 | ;edx threads count |
- | |
237 | .futex_wake: |
237 | .futex_wake: |
238 | 238 | ||
239 | xor ecx, ecx |
239 | xor ecx, ecx |
240 | 240 | ||
241 | pushfd |
241 | pushfd |
242 | cli |
242 | cli |
243 | 243 | ||
244 | lea ebx, [edi+FUTEX.wait_list] |
244 | lea ebx, [ebp+FUTEX.wait_list] |
245 | mov esi, [ebx+LHEAD.next] |
245 | mov esi, [ebx+LHEAD.next] |
246 | @@: |
246 | .wake: |
247 | cmp esi, ebx |
247 | cmp esi, ebx |
248 | je @F |
248 | je .done |
249 | 249 | ||
250 | mov eax, [esi+MUTEX_WAITER.task] |
250 | mov eax, [esi+MUTEX_WAITER.task] |
251 | mov [eax+TASKDATA.state], 0 |
251 | mov [eax+TASKDATA.state], 0 |
252 | 252 | ||
253 | mov esi, [esi+MUTEX_WAITER.list.next] |
253 | mov esi, [esi+MUTEX_WAITER.list.next] |
254 | inc ecx |
254 | inc ecx |
255 | cmp ecx, edx |
255 | cmp ecx, edx |
256 | jb @B |
256 | jb .wake |
257 | @@: |
257 | .done: |
258 | popfd |
258 | popfd |
259 | mov [esp+SYSCALL_STACK._eax], ecx |
259 | mov [esp+SYSCALL_STACK._eax], ecx |
260 | ret |
260 | ret |
261 | 261 | ||
262 | RWSEM_WAITING_FOR_WRITE equ 0 |
262 | RWSEM_WAITING_FOR_WRITE equ 0 |
263 | RWSEM_WAITING_FOR_READ equ 1 |
263 | RWSEM_WAITING_FOR_READ equ 1 |
264 | 264 | ||
265 | ;void __fastcall mutex_init(struct mutex *lock) |
265 | ;void __fastcall mutex_init(struct mutex *lock) |
266 | 266 | ||
267 | align 4 |
267 | align 4 |
268 | mutex_init: |
268 | mutex_init: |
269 | mov [ecx+MUTEX.wait_list.next], ecx |
269 | mov [ecx+MUTEX.wait_list.next], ecx |
270 | mov [ecx+MUTEX.wait_list.prev], ecx |
270 | mov [ecx+MUTEX.wait_list.prev], ecx |
271 | mov [ecx+MUTEX.count], 1 |
271 | mov [ecx+MUTEX.count], 1 |
272 | ret |
272 | ret |
273 | 273 | ||
274 | ;void __fastcall mutex_lock(struct mutex *lock) |
274 | ;void __fastcall mutex_lock(struct mutex *lock) |
275 | 275 | ||
276 | align 4 |
276 | align 4 |
277 | mutex_lock: |
277 | mutex_lock: |
278 | 278 | ||
279 | dec [ecx+MUTEX.count] |
279 | dec [ecx+MUTEX.count] |
280 | jns .done |
280 | jns .done |
281 | 281 | ||
282 | pushfd |
282 | pushfd |
283 | cli |
283 | cli |
284 | 284 | ||
285 | sub esp, sizeof.MUTEX_WAITER |
285 | sub esp, sizeof.MUTEX_WAITER |
286 | 286 | ||
287 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
287 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
288 | 288 | ||
289 | mov edx, [TASK_BASE] |
289 | mov edx, [TASK_BASE] |
290 | mov [esp+MUTEX_WAITER.task], edx |
290 | mov [esp+MUTEX_WAITER.task], edx |
291 | 291 | ||
292 | .forever: |
292 | .forever: |
293 | 293 | ||
294 | mov eax, -1 |
294 | mov eax, -1 |
295 | xchg eax, [ecx+MUTEX.count] |
295 | xchg eax, [ecx+MUTEX.count] |
296 | dec eax |
296 | dec eax |
297 | jz @F |
297 | jz @F |
298 | 298 | ||
299 | mov [edx+TASKDATA.state], 1 |
299 | mov [edx+TASKDATA.state], 1 |
300 | call change_task |
300 | call change_task |
301 | jmp .forever |
301 | jmp .forever |
302 | @@: |
302 | @@: |
303 | mov eax, ecx |
303 | mov eax, ecx |
304 | list_del esp |
304 | list_del esp |
305 | 305 | ||
306 | cmp [eax+MUTEX.wait_list.next], eax |
306 | cmp [eax+MUTEX.wait_list.next], eax |
307 | jne @F |
307 | jne @F |
308 | 308 | ||
309 | mov [eax+MUTEX.count], 0 |
309 | mov [eax+MUTEX.count], 0 |
310 | @@: |
310 | @@: |
311 | add esp, sizeof.MUTEX_WAITER |
311 | add esp, sizeof.MUTEX_WAITER |
312 | 312 | ||
313 | popfd |
313 | popfd |
314 | .done: |
314 | .done: |
315 | ret |
315 | ret |
316 | 316 | ||
317 | ;void __fastcall mutex_unlock(struct mutex *lock) |
317 | ;void __fastcall mutex_unlock(struct mutex *lock) |
318 | 318 | ||
319 | align 4 |
319 | align 4 |
320 | mutex_unlock: |
320 | mutex_unlock: |
321 | 321 | ||
322 | pushfd |
322 | pushfd |
323 | cli |
323 | cli |
324 | 324 | ||
325 | mov eax, [ecx+MUTEX.wait_list.next] |
325 | mov eax, [ecx+MUTEX.wait_list.next] |
326 | cmp eax, ecx |
326 | cmp eax, ecx |
327 | mov [ecx+MUTEX.count], 1 |
327 | mov [ecx+MUTEX.count], 1 |
328 | je @F |
328 | je @F |
329 | 329 | ||
330 | mov eax, [eax+MUTEX_WAITER.task] |
330 | mov eax, [eax+MUTEX_WAITER.task] |
331 | mov [eax+TASKDATA.state], 0 |
331 | mov [eax+TASKDATA.state], 0 |
332 | @@: |
332 | @@: |
333 | popfd |
333 | popfd |
334 | ret |
334 | ret |
335 | 335 | ||
336 | 336 | ||
337 | ;void __fastcall init_rwsem(struct rw_semaphore *sem) |
337 | ;void __fastcall init_rwsem(struct rw_semaphore *sem) |
338 | 338 | ||
339 | align 4 |
339 | align 4 |
340 | init_rwsem: |
340 | init_rwsem: |
341 | mov [ecx+RWSEM.wait_list.next], ecx |
341 | mov [ecx+RWSEM.wait_list.next], ecx |
342 | mov [ecx+RWSEM.wait_list.prev], ecx |
342 | mov [ecx+RWSEM.wait_list.prev], ecx |
343 | mov [ecx+RWSEM.count], 0 |
343 | mov [ecx+RWSEM.count], 0 |
344 | ret |
344 | ret |
345 | 345 | ||
346 | ;void __fastcall down_read(struct rw_semaphore *sem) |
346 | ;void __fastcall down_read(struct rw_semaphore *sem) |
347 | 347 | ||
348 | align 4 |
348 | align 4 |
349 | down_read: |
349 | down_read: |
350 | pushfd |
350 | pushfd |
351 | cli |
351 | cli |
352 | 352 | ||
353 | mov eax, [ecx+RWSEM.count] |
353 | mov eax, [ecx+RWSEM.count] |
354 | test eax, eax |
354 | test eax, eax |
355 | js @F |
355 | js @F |
356 | 356 | ||
357 | cmp ecx, [ecx+RWSEM.wait_list.next] |
357 | cmp ecx, [ecx+RWSEM.wait_list.next] |
358 | je .ok |
358 | je .ok |
359 | @@: |
359 | @@: |
360 | sub esp, sizeof.MUTEX_WAITER |
360 | sub esp, sizeof.MUTEX_WAITER |
361 | 361 | ||
362 | mov eax, [TASK_BASE] |
362 | mov eax, [TASK_BASE] |
363 | mov [esp+MUTEX_WAITER.task], eax |
363 | mov [esp+MUTEX_WAITER.task], eax |
364 | mov [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ |
364 | mov [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ |
365 | mov [eax+TASKDATA.state], 1 |
365 | mov [eax+TASKDATA.state], 1 |
366 | 366 | ||
367 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
367 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
368 | 368 | ||
369 | call change_task |
369 | call change_task |
370 | 370 | ||
371 | add esp, sizeof.MUTEX_WAITER |
371 | add esp, sizeof.MUTEX_WAITER |
372 | popfd |
372 | popfd |
373 | ret |
373 | ret |
374 | .ok: |
374 | .ok: |
375 | inc eax |
375 | inc eax |
376 | mov [ecx+RWSEM.count], eax |
376 | mov [ecx+RWSEM.count], eax |
377 | 377 | ||
378 | popfd |
378 | popfd |
379 | ret |
379 | ret |
380 | 380 | ||
381 | ;void __fastcall down_write(struct rw_semaphore *sem) |
381 | ;void __fastcall down_write(struct rw_semaphore *sem) |
382 | 382 | ||
383 | align 4 |
383 | align 4 |
384 | down_write: |
384 | down_write: |
385 | pushfd |
385 | pushfd |
386 | cli |
386 | cli |
387 | sub esp, sizeof.MUTEX_WAITER |
387 | sub esp, sizeof.MUTEX_WAITER |
388 | 388 | ||
389 | mov edx, [TASK_BASE] |
389 | mov edx, [TASK_BASE] |
390 | mov [esp+MUTEX_WAITER.task], edx |
390 | mov [esp+MUTEX_WAITER.task], edx |
391 | mov [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE |
391 | mov [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE |
392 | mov [edx+TASKDATA.state], 1 |
392 | mov [edx+TASKDATA.state], 1 |
393 | 393 | ||
394 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
394 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
395 | 395 | ||
396 | xor eax, eax |
396 | xor eax, eax |
397 | not eax |
397 | not eax |
398 | 398 | ||
399 | .forever: |
399 | .forever: |
400 | test eax, [ecx+RWSEM.count] |
400 | test eax, [ecx+RWSEM.count] |
401 | jz @F |
401 | jz @F |
402 | 402 | ||
403 | mov [edx+TASKDATA.state], 1 |
403 | mov [edx+TASKDATA.state], 1 |
404 | call change_task |
404 | call change_task |
405 | jmp .forever |
405 | jmp .forever |
406 | @@: |
406 | @@: |
407 | mov [ecx+RWSEM.count], eax |
407 | mov [ecx+RWSEM.count], eax |
408 | list_del esp |
408 | list_del esp |
409 | 409 | ||
410 | add esp, sizeof.MUTEX_WAITER |
410 | add esp, sizeof.MUTEX_WAITER |
411 | popfd |
411 | popfd |
412 | ret |
412 | ret |
413 | 413 | ||
414 | ;void __fastcall up_read(struct rw_semaphore *sem) |
414 | ;void __fastcall up_read(struct rw_semaphore *sem) |
415 | 415 | ||
416 | align 4 |
416 | align 4 |
417 | up_read: |
417 | up_read: |
418 | pushfd |
418 | pushfd |
419 | cli |
419 | cli |
420 | 420 | ||
421 | dec [ecx+RWSEM.count] |
421 | dec [ecx+RWSEM.count] |
422 | jnz @F |
422 | jnz @F |
423 | 423 | ||
424 | mov eax, [ecx+RWSEM.wait_list.next] |
424 | mov eax, [ecx+RWSEM.wait_list.next] |
425 | cmp eax, ecx |
425 | cmp eax, ecx |
426 | je @F |
426 | je @F |
427 | 427 | ||
428 | mov eax, [eax+MUTEX_WAITER.task] |
428 | mov eax, [eax+MUTEX_WAITER.task] |
429 | mov [eax+TASKDATA.state], 0 |
429 | mov [eax+TASKDATA.state], 0 |
430 | @@: |
430 | @@: |
431 | popfd |
431 | popfd |
432 | ret |
432 | ret |
433 | 433 | ||
434 | ;void __fastcall up_write(struct rw_semaphore *sem) |
434 | ;void __fastcall up_write(struct rw_semaphore *sem) |
435 | 435 | ||
436 | align 4 |
436 | align 4 |
437 | up_write: |
437 | up_write: |
438 | 438 | ||
439 | pushfd |
439 | pushfd |
440 | cli |
440 | cli |
441 | 441 | ||
442 | mov eax, [ecx+RWSEM.wait_list.next] |
442 | mov eax, [ecx+RWSEM.wait_list.next] |
443 | mov [ecx+RWSEM.count], 0 |
443 | mov [ecx+RWSEM.count], 0 |
444 | 444 | ||
445 | cmp ecx, eax |
445 | cmp ecx, eax |
446 | je .done |
446 | je .done |
447 | 447 | ||
448 | mov edx, [eax+MUTEX_WAITER.type] |
448 | mov edx, [eax+MUTEX_WAITER.type] |
449 | test edx, edx |
449 | test edx, edx |
450 | jnz .wake |
450 | jnz .wake |
451 | 451 | ||
452 | mov eax, [eax+MUTEX_WAITER.task] |
452 | mov eax, [eax+MUTEX_WAITER.task] |
453 | mov [eax+TASKDATA.state], 0 |
453 | mov [eax+TASKDATA.state], 0 |
454 | .done: |
454 | .done: |
455 | popfd |
455 | popfd |
456 | ret |
456 | ret |
457 | 457 | ||
458 | .wake: |
458 | .wake: |
459 | push ebx |
459 | push ebx |
460 | push esi |
460 | push esi |
461 | push edi |
461 | push edi |
462 | 462 | ||
463 | xor esi, esi |
463 | xor esi, esi |
464 | mov edi, ecx |
464 | mov edi, ecx |
465 | 465 | ||
466 | .wake_list: |
466 | .wake_list: |
467 | 467 | ||
468 | mov ebx, [eax+MUTEX_WAITER.list.next] |
468 | mov ebx, [eax+MUTEX_WAITER.list.next] |
469 | list_del eax |
469 | list_del eax |
470 | mov edx, [eax+MUTEX_WAITER.task] |
470 | mov edx, [eax+MUTEX_WAITER.task] |
471 | mov [edx+TASKDATA.state], 0 |
471 | mov [edx+TASKDATA.state], 0 |
472 | inc esi |
472 | inc esi |
473 | cmp edi, ebx |
473 | cmp edi, ebx |
474 | je .wake_done |
474 | je .wake_done |
475 | 475 | ||
476 | mov ecx, [ebx+MUTEX_WAITER.type] |
476 | mov ecx, [ebx+MUTEX_WAITER.type] |
477 | test ecx, ecx |
477 | test ecx, ecx |
478 | jz .wake_done |
478 | jz .wake_done |
479 | 479 | ||
480 | mov eax, ebx |
480 | mov eax, ebx |
481 | jmp .wake_list |
481 | jmp .wake_list |
482 | 482 | ||
483 | .wake_done: |
483 | .wake_done: |
484 | add [edi+RWSEM.count], esi |
484 | add [edi+RWSEM.count], esi |
485 | 485 | ||
486 | pop edi |
486 | pop edi |
487 | pop esi |
487 | pop esi |
488 | pop ebx |
488 | pop ebx |
489 | popfd |
489 | popfd |
490 | ret |
490 | ret |
491 | 491 | ||
492 | 492 | ||
493 | purge RWSEM_WAITING_FOR_WRITE |
493 | purge RWSEM_WAITING_FOR_WRITE |
494 | purge RWSEM_WAITING_FOR_READ |
494 | purge RWSEM_WAITING_FOR_READ |
495 | 495 | ||
496 | 496 | ||
497 | if ~defined sync_inc |
497 | if ~defined sync_inc |
498 | sync_inc_fix: |
498 | sync_inc_fix: |
499 | sync_inc fix sync_inc_fix |
499 | sync_inc fix sync_inc_fix |
500 | 500 | ||
501 | ;simplest mutex. |
501 | ;simplest mutex. |
502 | macro SimpleMutex name |
502 | macro SimpleMutex name |
503 | { |
503 | { |
504 | ; iglobal |
504 | ; iglobal |
505 | name dd 0 |
505 | name dd 0 |
506 | name#.type = 1 |
506 | name#.type = 1 |
507 | ; endg |
507 | ; endg |
508 | } |
508 | } |
509 | macro WaitSimpleMutex name |
509 | macro WaitSimpleMutex name |
510 | { |
510 | { |
511 | local start_wait,ok |
511 | local start_wait,ok |
512 | start_wait=$ |
512 | start_wait=$ |
513 | cli |
513 | cli |
514 | cmp [name], dword 0 |
514 | cmp [name], dword 0 |
515 | jz ok |
515 | jz ok |
516 | sti |
516 | sti |
517 | call change_task |
517 | call change_task |
518 | jmp start_wait |
518 | jmp start_wait |
519 | ok=$ |
519 | ok=$ |
520 | push eax |
520 | push eax |
521 | mov eax, dword [TASK_BASE+second_base_address] |
521 | mov eax, dword [TASK_BASE+second_base_address] |
522 | mov eax, [eax+TASKDATA.pid] |
522 | mov eax, [eax+TASKDATA.pid] |
523 | mov [name], eax |
523 | mov [name], eax |
524 | pop eax |
524 | pop eax |
525 | sti |
525 | sti |
526 | } |
526 | } |
527 | macro ReleaseSimpleMutex name |
527 | macro ReleaseSimpleMutex name |
528 | { |
528 | { |
529 | mov [name], dword 0 |
529 | mov [name], dword 0 |
530 | } |
530 | } |
531 | macro TryWaitSimpleMutex name ;result in eax and in flags |
531 | macro TryWaitSimpleMutex name ;result in eax and in flags |
532 | { |
532 | { |
533 | local ok,try_end |
533 | local ok,try_end |
534 | cmp [name], dword 0 |
534 | cmp [name], dword 0 |
535 | jz ok |
535 | jz ok |
536 | xor eax, eax |
536 | xor eax, eax |
537 | jmp try_end |
537 | jmp try_end |
538 | ok=$ |
538 | ok=$ |
539 | xor eax, eax |
539 | xor eax, eax |
540 | inc eax |
540 | inc eax |
541 | try_end=$ |
541 | try_end=$ |
542 | } |
542 | } |
543 | macro SimpleCriticalSection name |
543 | macro SimpleCriticalSection name |
544 | { |
544 | { |
545 | ; iglobal |
545 | ; iglobal |
546 | name dd 0 |
546 | name dd 0 |
547 | dd 0 |
547 | dd 0 |
548 | name#.type=2 |
548 | name#.type=2 |
549 | ; endg |
549 | ; endg |
550 | } |
550 | } |
551 | macro WaitSimpleCriticalSection name |
551 | macro WaitSimpleCriticalSection name |
552 | { |
552 | { |
553 | local start_wait,first_wait,inc_counter,end_wait |
553 | local start_wait,first_wait,inc_counter,end_wait |
554 | push eax |
554 | push eax |
555 | mov eax, [TASK_BASE+second_base_address] |
555 | mov eax, [TASK_BASE+second_base_address] |
556 | mov eax, [eax+TASKDATA.pid] |
556 | mov eax, [eax+TASKDATA.pid] |
557 | start_wait=$ |
557 | start_wait=$ |
558 | cli |
558 | cli |
559 | cmp [name], dword 0 |
559 | cmp [name], dword 0 |
560 | jz first_wait |
560 | jz first_wait |
561 | cmp [name], eax |
561 | cmp [name], eax |
562 | jz inc_counter |
562 | jz inc_counter |
563 | sti |
563 | sti |
564 | call change_task |
564 | call change_task |
565 | jmp start_wait |
565 | jmp start_wait |
566 | first_wait=$ |
566 | first_wait=$ |
567 | mov [name], eax |
567 | mov [name], eax |
568 | mov [name+4], dword 1 |
568 | mov [name+4], dword 1 |
569 | jmp end_wait |
569 | jmp end_wait |
570 | inc_counter=$ |
570 | inc_counter=$ |
571 | inc dword [name+4] |
571 | inc dword [name+4] |
572 | end_wait=$ |
572 | end_wait=$ |
573 | sti |
573 | sti |
574 | pop eax |
574 | pop eax |
575 | } |
575 | } |
576 | macro ReleaseSimpleCriticalSection name |
576 | macro ReleaseSimpleCriticalSection name |
577 | { |
577 | { |
578 | local release_end |
578 | local release_end |
579 | dec dword [name+4] |
579 | dec dword [name+4] |
580 | jnz release_end |
580 | jnz release_end |
581 | mov [name], dword 0 |
581 | mov [name], dword 0 |
582 | release_end=$ |
582 | release_end=$ |
583 | } |
583 | } |
584 | macro TryWaitSimpleCriticalSection name ;result in eax and in flags |
584 | macro TryWaitSimpleCriticalSection name ;result in eax and in flags |
585 | { |
585 | { |
586 | local ok,try_end |
586 | local ok,try_end |
587 | mov eax, [CURRENT_TASK+second_base_address] |
587 | mov eax, [CURRENT_TASK+second_base_address] |
588 | mov eax, [eax+TASKDATA.pid] |
588 | mov eax, [eax+TASKDATA.pid] |
589 | cmp [name], eax |
589 | cmp [name], eax |
590 | jz ok |
590 | jz ok |
591 | cmp [name], 0 |
591 | cmp [name], 0 |
592 | jz ok |
592 | jz ok |
593 | xor eax, eax |
593 | xor eax, eax |
594 | jmp try_end |
594 | jmp try_end |
595 | ok=$ |
595 | ok=$ |
596 | xor eax, eax |
596 | xor eax, eax |
597 | inc eax |
597 | inc eax |
598 | try_end=$ |
598 | try_end=$ |
599 | } |
599 | } |
600 | _cli equ call MEM_HeapLock |
600 | _cli equ call MEM_HeapLock |
601 | _sti equ call MEM_HeapUnLock |
601 | _sti equ call MEM_HeapUnLock |
602 | end if |
602 | end if |