Subversion Repositories Kolibri OS

Rev

Rev 5596 | Rev 5599 | 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                    ;;
8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9
 
593 mikedld 10
$Revision: 5597 $
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
 
89
        mov     esi, [current_process]
90
        mov     edi, [esi+PROC.htab+ecx*4]
91
 
92
        cmp     [edi+FUTEX.magic], 'FUTX'
93
        jne     .fail
94
        cmp     [edi+FUTEX.handle], ecx
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
5597 serge 116
;esi current process
117
;edi futex object
118
.futex_destroy:
119
        mov     ecx, edi
120
        call    destroy_futex
121
        mov     [esp+SYSCALL_STACK._eax], eax
122
        ret
123
 
124
align 4
125
;ecx futex handle
126
;esi current process
127
;edi futex object
5593 serge 128
;edx control value
129
.futex_wait:
130
        mov     ecx, [edi+FUTEX.pointer]
131
        mov     eax, edx
132
        lock cmpxchg [ecx], edx         ;wait until old_value == new_value
133
        jz .wait_slow
134
 
135
        mov     [esp+SYSCALL_STACK._eax], 0
136
        ret
137
 
138
.wait_slow:
139
        pushfd
140
        cli
141
 
142
        sub     esp, sizeof.MUTEX_WAITER
143
        mov     ebx, [TASK_BASE]
144
        mov     [ebx+TASKDATA.state], 1
145
        mov     [esp+MUTEX_WAITER.task], ebx
146
        lea     esi, [edi+FUTEX.wait_list]
147
 
148
        list_add_tail esp, esi      ;esp= new waiter, esi= list head
149
 
150
.again:
151
        call    change_task
152
 
153
        lock cmpxchg [ecx], edx
154
        jz .again
155
 
156
        list_del esp
157
        add     esp, sizeof.MUTEX_WAITER
158
 
159
        popfd
160
        mov     [esp+SYSCALL_STACK._eax], 0
161
        ret
162
 
163
align 4
164
;ecx futex handle
5597 serge 165
;esi current process
166
;edi futex object
5593 serge 167
;edx threads count
168
.futex_wake:
169
 
170
        xor     ecx, ecx
171
 
172
        pushfd
173
        cli
174
 
175
        lea     ebx, [edi+FUTEX.wait_list]
5597 serge 176
        mov     esi, [ebx+LHEAD.next]
5593 serge 177
@@:
178
        cmp     esi, ebx
179
        je      @F
180
 
181
        mov     eax, [esi+MUTEX_WAITER.task]
182
        mov     [eax+TASKDATA.state], 0
183
 
184
        mov     esi, [esi+MUTEX_WAITER.list.next]
185
        inc     ecx
186
        cmp     ecx, edx
187
        jb      @B
188
@@:
189
        popfd
190
        mov     [esp+SYSCALL_STACK._eax], ecx
191
        ret
192
 
193
RWSEM_WAITING_FOR_WRITE equ 0
194
RWSEM_WAITING_FOR_READ  equ 1
195
 
196
;void  __fastcall mutex_init(struct mutex *lock)
197
 
198
align 4
199
mutex_init:
200
        mov     [ecx+MUTEX.wait_list.next], ecx
201
        mov     [ecx+MUTEX.wait_list.prev], ecx
202
        mov     [ecx+MUTEX.count], 1
203
        ret
204
 
205
;void  __fastcall mutex_lock(struct mutex *lock)
206
 
207
align 4
208
mutex_lock:
209
 
210
        dec     [ecx+MUTEX.count]
211
        jns     .done
212
 
213
        pushfd
214
        cli
215
 
216
        sub     esp, sizeof.MUTEX_WAITER
217
 
218
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
219
 
220
        mov     edx, [TASK_BASE]
221
        mov     [esp+MUTEX_WAITER.task], edx
222
 
223
.forever:
224
 
225
        mov     eax, -1
226
        xchg    eax, [ecx+MUTEX.count]
227
        dec     eax
228
        jz      @F
229
 
230
        mov     [edx+TASKDATA.state], 1
231
        call    change_task
232
        jmp     .forever
233
@@:
234
        mov     eax, ecx
235
        list_del esp
236
 
237
        cmp     [eax+MUTEX.wait_list.next], eax
238
        jne     @F
239
 
240
        mov     [eax+MUTEX.count], 0
241
@@:
242
        add     esp, sizeof.MUTEX_WAITER
243
 
244
        popfd
245
.done:
246
        ret
247
 
248
;void  __fastcall mutex_unlock(struct mutex *lock)
249
 
250
align 4
251
mutex_unlock:
252
 
253
        pushfd
254
        cli
255
 
256
        mov     eax, [ecx+MUTEX.wait_list.next]
257
        cmp     eax, ecx
258
        mov     [ecx+MUTEX.count], 1
259
        je      @F
260
 
261
        mov     eax, [eax+MUTEX_WAITER.task]
262
        mov     [eax+TASKDATA.state], 0
263
@@:
264
        popfd
265
        ret
266
 
267
 
268
;void __fastcall init_rwsem(struct rw_semaphore *sem)
269
 
270
align 4
271
init_rwsem:
272
        mov     [ecx+RWSEM.wait_list.next], ecx
273
        mov     [ecx+RWSEM.wait_list.prev], ecx
274
        mov     [ecx+RWSEM.count], 0
275
        ret
276
 
277
;void __fastcall down_read(struct rw_semaphore *sem)
278
 
279
align 4
280
down_read:
281
        pushfd
282
        cli
283
 
284
        mov     eax, [ecx+RWSEM.count]
285
        test    eax, eax
286
        js      @F
287
 
288
        cmp     ecx, [ecx+RWSEM.wait_list.next]
289
        je      .ok
290
@@:
291
        sub     esp, sizeof.MUTEX_WAITER
292
 
293
        mov     eax, [TASK_BASE]
294
        mov     [esp+MUTEX_WAITER.task], eax
295
        mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ
296
        mov     [eax+TASKDATA.state], 1
297
 
298
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
299
 
300
        call    change_task
301
 
302
        add     esp, sizeof.MUTEX_WAITER
303
        popfd
304
        ret
305
.ok:
306
        inc     eax
307
        mov     [ecx+RWSEM.count], eax
308
 
309
        popfd
310
        ret
311
 
312
;void __fastcall down_write(struct rw_semaphore *sem)
313
 
314
align 4
315
down_write:
316
        pushfd
317
        cli
318
        sub     esp, sizeof.MUTEX_WAITER
319
 
320
        mov     edx, [TASK_BASE]
321
        mov     [esp+MUTEX_WAITER.task], edx
322
        mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE
323
        mov     [edx+TASKDATA.state], 1
324
 
325
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
326
 
327
        xor     eax, eax
328
        not     eax
329
 
330
.forever:
331
        test    eax, [ecx+RWSEM.count]
332
        jz      @F
333
 
334
        mov     [edx+TASKDATA.state], 1
335
        call    change_task
336
        jmp     .forever
337
@@:
338
        mov     [ecx+RWSEM.count], eax
339
        list_del esp
340
 
341
        add     esp, sizeof.MUTEX_WAITER
342
        popfd
343
        ret
344
 
345
;void __fastcall up_read(struct rw_semaphore *sem)
346
 
347
align 4
348
up_read:
349
        pushfd
350
        cli
351
 
352
        dec     [ecx+RWSEM.count]
353
        jnz     @F
354
 
355
        mov     eax, [ecx+RWSEM.wait_list.next]
356
        cmp     eax, ecx
357
        je      @F
358
 
359
        mov     eax, [eax+MUTEX_WAITER.task]
360
        mov     [eax+TASKDATA.state], 0
361
@@:
362
        popfd
363
        ret
364
 
365
;void __fastcall up_write(struct rw_semaphore *sem)
366
 
367
align 4
368
up_write:
369
 
370
        pushfd
371
        cli
372
 
373
        mov     eax, [ecx+RWSEM.wait_list.next]
374
        mov     [ecx+RWSEM.count], 0
375
 
376
        cmp     ecx, eax
377
        je      .done
378
 
379
        mov     edx, [eax+MUTEX_WAITER.type]
380
        test    edx, edx
381
        jnz     .wake
382
 
383
        mov     eax, [eax+MUTEX_WAITER.task]
384
        mov     [eax+TASKDATA.state], 0
385
.done:
386
        popfd
387
        ret
388
 
389
.wake:
390
        push    ebx
391
        push    esi
392
        push    edi
393
 
394
        xor     esi, esi
395
        mov     edi, ecx
396
 
397
.wake_list:
398
 
399
        mov     ebx, [eax+MUTEX_WAITER.list.next]
400
        list_del eax
401
        mov     edx, [eax+MUTEX_WAITER.task]
402
        mov     [edx+TASKDATA.state], 0
403
        inc     esi
404
        cmp     edi, ebx
405
        je      .wake_done
406
 
407
        mov     ecx, [ebx+MUTEX_WAITER.type]
408
        test    ecx, ecx
409
        jz      .wake_done
410
 
411
        mov     eax, ebx
412
        jmp     .wake_list
413
 
414
.wake_done:
415
        add     [edi+RWSEM.count], esi
416
 
417
        pop     edi
418
        pop     esi
419
        pop     ebx
420
        popfd
421
        ret
422
 
423
 
424
purge RWSEM_WAITING_FOR_WRITE
425
purge RWSEM_WAITING_FOR_READ
426
 
427
 
1 ha 428
if ~defined sync_inc
429
sync_inc_fix:
430
sync_inc fix sync_inc_fix
431
 
432
;simplest mutex.
433
macro SimpleMutex name
434
{
435
;  iglobal
436
    name dd 0
437
    name#.type = 1
438
;  endg
439
}
440
macro WaitSimpleMutex name
441
{
442
  local start_wait,ok
379 serge 443
start_wait=$
2434 Serge 444
        cli
445
        cmp     [name], dword 0
446
        jz      ok
447
        sti
448
        call    change_task
449
        jmp     start_wait
1 ha 450
ok=$
2434 Serge 451
        push    eax
452
        mov     eax, dword [TASK_BASE+second_base_address]
453
        mov     eax, [eax+TASKDATA.pid]
454
        mov     [name], eax
455
        pop     eax
456
        sti
1 ha 457
}
458
macro ReleaseSimpleMutex name
459
{
2434 Serge 460
        mov     [name], dword 0
1 ha 461
}
462
macro TryWaitSimpleMutex name  ;result in eax and in flags
463
{
464
  local ok,try_end
2434 Serge 465
        cmp     [name], dword 0
466
        jz      ok
467
        xor     eax, eax
468
        jmp     try_end
1 ha 469
ok=$
2434 Serge 470
        xor     eax, eax
471
        inc     eax
1 ha 472
try_end=$
473
}
474
macro SimpleCriticalSection name
475
{
476
;  iglobal
477
    name  dd 0
478
          dd 0
479
    name#.type=2
480
;  endg
481
}
482
macro WaitSimpleCriticalSection name
483
{
484
  local start_wait,first_wait,inc_counter,end_wait
2434 Serge 485
        push    eax
486
        mov     eax, [TASK_BASE+second_base_address]
487
        mov     eax, [eax+TASKDATA.pid]
1 ha 488
start_wait=$
2434 Serge 489
        cli
490
        cmp     [name], dword 0
491
        jz      first_wait
492
        cmp     [name], eax
493
        jz      inc_counter
494
        sti
495
        call    change_task
496
        jmp     start_wait
1 ha 497
first_wait=$
2434 Serge 498
        mov     [name], eax
499
        mov     [name+4], dword 1
500
        jmp     end_wait
1 ha 501
inc_counter=$
2434 Serge 502
        inc     dword [name+4]
1 ha 503
end_wait=$
2434 Serge 504
        sti
505
        pop     eax
1 ha 506
}
507
macro ReleaseSimpleCriticalSection name
508
{
509
  local release_end
2434 Serge 510
        dec     dword [name+4]
511
        jnz     release_end
512
        mov     [name], dword 0
1 ha 513
release_end=$
514
}
515
macro TryWaitSimpleCriticalSection name ;result in eax and in flags
516
{
517
  local ok,try_end
2434 Serge 518
        mov     eax, [CURRENT_TASK+second_base_address]
519
        mov     eax, [eax+TASKDATA.pid]
520
        cmp     [name], eax
521
        jz      ok
522
        cmp     [name], 0
523
        jz      ok
524
        xor     eax, eax
525
        jmp     try_end
1 ha 526
ok=$
2434 Serge 527
        xor     eax, eax
528
        inc     eax
1 ha 529
try_end=$
530
}
531
_cli equ call MEM_HeapLock
532
_sti equ call MEM_HeapUnLock
533
end if
534