Subversion Repositories Kolibri OS

Rev

Rev 5565 | Rev 5596 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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