Subversion Repositories Kolibri OS

Rev

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