Subversion Repositories Kolibri OS

Rev

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