Subversion Repositories Kolibri OS

Rev

Rev 6926 | Rev 9709 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6926 Rev 7136
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: 6926 $
10
$Revision: 7136 $
11
 
11
 
12
 
12
 
13
 
13
 
14
RWSEM_WAITING_FOR_WRITE equ 0
14
RWSEM_WAITING_FOR_WRITE = 0
15
RWSEM_WAITING_FOR_READ  equ 1
15
RWSEM_WAITING_FOR_READ  = 1
16
 
16
 
17
;void  __fastcall mutex_init(struct mutex *lock)
17
;void  __fastcall mutex_init(struct mutex *lock)
18
 
18
 
19
align 4
19
align 4
20
mutex_init:
20
mutex_init:
21
        mov     [ecx+MUTEX.wait_list.next], ecx
21
        mov     [ecx+MUTEX.wait_list.next], ecx
22
        mov     [ecx+MUTEX.wait_list.prev], ecx
22
        mov     [ecx+MUTEX.wait_list.prev], ecx
23
        mov     [ecx+MUTEX.count], 1
23
        mov     [ecx+MUTEX.count], 1
24
        ret
24
        ret
25
 
25
 
26
;void  __fastcall mutex_lock(struct mutex *lock)
26
;void  __fastcall mutex_lock(struct mutex *lock)
27
 
27
 
28
align 4
28
align 4
29
mutex_lock:
29
mutex_lock:
30
 
30
 
31
        dec     [ecx+MUTEX.count]
31
        dec     [ecx+MUTEX.count]
32
        jns     .done
32
        jns     .done
33
 
33
 
34
        pushfd
34
        pushfd
35
        cli
35
        cli
36
 
36
 
37
        sub     esp, sizeof.MUTEX_WAITER
37
        sub     esp, sizeof.MUTEX_WAITER
38
 
38
 
39
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
39
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
40
 
40
 
41
        mov     edx, [TASK_BASE]
41
        mov     edx, [TASK_BASE]
42
        mov     [esp+MUTEX_WAITER.task], edx
42
        mov     [esp+MUTEX_WAITER.task], edx
43
 
43
 
44
.forever:
44
.forever:
45
 
45
 
46
        mov     eax, -1
46
        mov     eax, -1
47
        xchg    eax, [ecx+MUTEX.count]
47
        xchg    eax, [ecx+MUTEX.count]
48
        dec     eax
48
        dec     eax
49
        jz      @F
49
        jz      @F
50
 
50
 
51
        mov     [edx+TASKDATA.state], 1
51
        mov     [edx+TASKDATA.state], 1
52
        call    change_task
52
        call    change_task
53
        jmp     .forever
53
        jmp     .forever
54
@@:
54
@@:
55
        mov     eax, ecx
55
        mov     eax, ecx
56
        list_del esp
56
        list_del esp
57
 
57
 
58
        cmp     [eax+MUTEX.wait_list.next], eax
58
        cmp     [eax+MUTEX.wait_list.next], eax
59
        jne     @F
59
        jne     @F
60
 
60
 
61
        mov     [eax+MUTEX.count], 0
61
        mov     [eax+MUTEX.count], 0
62
@@:
62
@@:
63
        add     esp, sizeof.MUTEX_WAITER
63
        add     esp, sizeof.MUTEX_WAITER
64
 
64
 
65
        popfd
65
        popfd
66
.done:
66
.done:
67
        ret
67
        ret
68
 
68
 
69
;void  __fastcall mutex_unlock(struct mutex *lock)
69
;void  __fastcall mutex_unlock(struct mutex *lock)
70
 
70
 
71
align 4
71
align 4
72
mutex_unlock:
72
mutex_unlock:
73
 
73
 
74
        pushfd
74
        pushfd
75
        cli
75
        cli
76
 
76
 
77
        mov     eax, [ecx+MUTEX.wait_list.next]
77
        mov     eax, [ecx+MUTEX.wait_list.next]
78
        cmp     eax, ecx
78
        cmp     eax, ecx
79
        mov     [ecx+MUTEX.count], 1
79
        mov     [ecx+MUTEX.count], 1
80
        je      @F
80
        je      @F
81
 
81
 
82
        mov     eax, [eax+MUTEX_WAITER.task]
82
        mov     eax, [eax+MUTEX_WAITER.task]
83
        mov     [eax+TASKDATA.state], 0
83
        mov     [eax+TASKDATA.state], 0
84
@@:
84
@@:
85
        popfd
85
        popfd
86
        ret
86
        ret
87
 
87
 
88
 
88
 
89
;void __fastcall init_rwsem(struct rw_semaphore *sem)
89
;void __fastcall init_rwsem(struct rw_semaphore *sem)
90
 
90
 
91
align 4
91
align 4
92
init_rwsem:
92
init_rwsem:
93
        mov     [ecx+RWSEM.wait_list.next], ecx
93
        mov     [ecx+RWSEM.wait_list.next], ecx
94
        mov     [ecx+RWSEM.wait_list.prev], ecx
94
        mov     [ecx+RWSEM.wait_list.prev], ecx
95
        mov     [ecx+RWSEM.count], 0
95
        mov     [ecx+RWSEM.count], 0
96
        ret
96
        ret
97
 
97
 
98
;void __fastcall down_read(struct rw_semaphore *sem)
98
;void __fastcall down_read(struct rw_semaphore *sem)
99
 
99
 
100
align 4
100
align 4
101
down_read:
101
down_read:
102
        pushfd
102
        pushfd
103
        cli
103
        cli
104
 
104
 
105
        mov     eax, [ecx+RWSEM.count]
105
        mov     eax, [ecx+RWSEM.count]
106
        test    eax, eax
106
        test    eax, eax
107
        js      @F
107
        js      @F
108
 
108
 
109
        cmp     ecx, [ecx+RWSEM.wait_list.next]
109
        cmp     ecx, [ecx+RWSEM.wait_list.next]
110
        je      .ok
110
        je      .ok
111
@@:
111
@@:
112
        sub     esp, sizeof.MUTEX_WAITER
112
        sub     esp, sizeof.MUTEX_WAITER
113
 
113
 
114
        mov     eax, [TASK_BASE]
114
        mov     eax, [TASK_BASE]
115
        mov     [esp+MUTEX_WAITER.task], eax
115
        mov     [esp+MUTEX_WAITER.task], eax
116
        mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ
116
        mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ
117
        mov     [eax+TASKDATA.state], 1
117
        mov     [eax+TASKDATA.state], 1
118
 
118
 
119
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
119
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
120
 
120
 
121
        call    change_task
121
        call    change_task
122
 
122
 
123
        add     esp, sizeof.MUTEX_WAITER
123
        add     esp, sizeof.MUTEX_WAITER
124
        popfd
124
        popfd
125
        ret
125
        ret
126
.ok:
126
.ok:
127
        inc     eax
127
        inc     eax
128
        mov     [ecx+RWSEM.count], eax
128
        mov     [ecx+RWSEM.count], eax
129
 
129
 
130
        popfd
130
        popfd
131
        ret
131
        ret
132
 
132
 
133
;void __fastcall down_write(struct rw_semaphore *sem)
133
;void __fastcall down_write(struct rw_semaphore *sem)
134
 
134
 
135
align 4
135
align 4
136
down_write:
136
down_write:
137
        pushfd
137
        pushfd
138
        cli
138
        cli
139
        sub     esp, sizeof.MUTEX_WAITER
139
        sub     esp, sizeof.MUTEX_WAITER
140
 
140
 
141
        mov     edx, [TASK_BASE]
141
        mov     edx, [TASK_BASE]
142
        mov     [esp+MUTEX_WAITER.task], edx
142
        mov     [esp+MUTEX_WAITER.task], edx
143
        mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE
143
        mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE
144
        mov     [edx+TASKDATA.state], 1
144
        mov     [edx+TASKDATA.state], 1
145
 
145
 
146
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
146
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
147
 
147
 
148
        xor     eax, eax
148
        xor     eax, eax
149
        not     eax
149
        not     eax
150
 
150
 
151
.forever:
151
.forever:
152
        test    eax, [ecx+RWSEM.count]
152
        test    eax, [ecx+RWSEM.count]
153
        jz      @F
153
        jz      @F
154
 
154
 
155
        mov     [edx+TASKDATA.state], 1
155
        mov     [edx+TASKDATA.state], 1
156
        call    change_task
156
        call    change_task
157
        jmp     .forever
157
        jmp     .forever
158
@@:
158
@@:
159
        mov     [ecx+RWSEM.count], eax
159
        mov     [ecx+RWSEM.count], eax
160
        list_del esp
160
        list_del esp
161
 
161
 
162
        add     esp, sizeof.MUTEX_WAITER
162
        add     esp, sizeof.MUTEX_WAITER
163
        popfd
163
        popfd
164
        ret
164
        ret
165
 
165
 
166
;void __fastcall up_read(struct rw_semaphore *sem)
166
;void __fastcall up_read(struct rw_semaphore *sem)
167
 
167
 
168
align 4
168
align 4
169
up_read:
169
up_read:
170
        pushfd
170
        pushfd
171
        cli
171
        cli
172
 
172
 
173
        dec     [ecx+RWSEM.count]
173
        dec     [ecx+RWSEM.count]
174
        jnz     @F
174
        jnz     @F
175
 
175
 
176
        mov     eax, [ecx+RWSEM.wait_list.next]
176
        mov     eax, [ecx+RWSEM.wait_list.next]
177
        cmp     eax, ecx
177
        cmp     eax, ecx
178
        je      @F
178
        je      @F
179
 
179
 
180
        mov     eax, [eax+MUTEX_WAITER.task]
180
        mov     eax, [eax+MUTEX_WAITER.task]
181
        mov     [eax+TASKDATA.state], 0
181
        mov     [eax+TASKDATA.state], 0
182
@@:
182
@@:
183
        popfd
183
        popfd
184
        ret
184
        ret
185
 
185
 
186
;void __fastcall up_write(struct rw_semaphore *sem)
186
;void __fastcall up_write(struct rw_semaphore *sem)
187
 
187
 
188
align 4
188
align 4
189
up_write:
189
up_write:
190
 
190
 
191
        pushfd
191
        pushfd
192
        cli
192
        cli
193
 
193
 
194
        mov     eax, [ecx+RWSEM.wait_list.next]
194
        mov     eax, [ecx+RWSEM.wait_list.next]
195
        mov     [ecx+RWSEM.count], 0
195
        mov     [ecx+RWSEM.count], 0
196
 
196
 
197
        cmp     ecx, eax
197
        cmp     ecx, eax
198
        je      .done
198
        je      .done
199
 
199
 
200
        mov     edx, [eax+MUTEX_WAITER.type]
200
        mov     edx, [eax+MUTEX_WAITER.type]
201
        test    edx, edx
201
        test    edx, edx
202
        jnz     .wake
202
        jnz     .wake
203
 
203
 
204
        mov     eax, [eax+MUTEX_WAITER.task]
204
        mov     eax, [eax+MUTEX_WAITER.task]
205
        mov     [eax+TASKDATA.state], 0
205
        mov     [eax+TASKDATA.state], 0
206
.done:
206
.done:
207
        popfd
207
        popfd
208
        ret
208
        ret
209
 
209
 
210
.wake:
210
.wake:
211
        push    ebx
211
        push    ebx
212
        push    esi
212
        push    esi
213
        push    edi
213
        push    edi
214
 
214
 
215
        xor     esi, esi
215
        xor     esi, esi
216
        mov     edi, ecx
216
        mov     edi, ecx
217
 
217
 
218
.wake_list:
218
.wake_list:
219
 
219
 
220
        mov     ebx, [eax+MUTEX_WAITER.list.next]
220
        mov     ebx, [eax+MUTEX_WAITER.list.next]
221
        list_del eax
221
        list_del eax
222
        mov     edx, [eax+MUTEX_WAITER.task]
222
        mov     edx, [eax+MUTEX_WAITER.task]
223
        mov     [edx+TASKDATA.state], 0
223
        mov     [edx+TASKDATA.state], 0
224
        inc     esi
224
        inc     esi
225
        cmp     edi, ebx
225
        cmp     edi, ebx
226
        je      .wake_done
226
        je      .wake_done
227
 
227
 
228
        mov     ecx, [ebx+MUTEX_WAITER.type]
228
        mov     ecx, [ebx+MUTEX_WAITER.type]
229
        test    ecx, ecx
229
        test    ecx, ecx
230
        jz      .wake_done
230
        jz      .wake_done
231
 
231
 
232
        mov     eax, ebx
232
        mov     eax, ebx
233
        jmp     .wake_list
233
        jmp     .wake_list
234
 
234
 
235
.wake_done:
235
.wake_done:
236
        add     [edi+RWSEM.count], esi
236
        add     [edi+RWSEM.count], esi
237
 
237
 
238
        pop     edi
238
        pop     edi
239
        pop     esi
239
        pop     esi
240
        pop     ebx
240
        pop     ebx
241
        popfd
241
        popfd
242
        ret
242
        ret
243
 
243
 
244
 
244
 
245
purge RWSEM_WAITING_FOR_WRITE
245
purge RWSEM_WAITING_FOR_WRITE
246
purge RWSEM_WAITING_FOR_READ
246
purge RWSEM_WAITING_FOR_READ
247
 
247
 
248
 
248
 
249
if ~defined sync_inc
249
if ~defined sync_inc
250
sync_inc_fix:
250
sync_inc_fix:
251
sync_inc fix sync_inc_fix
251
sync_inc fix sync_inc_fix
252
 
252
 
253
;simplest mutex.
253
;simplest mutex.
254
macro SimpleMutex name
254
macro SimpleMutex name
255
{
255
{
256
;  iglobal
256
;  iglobal
257
    name dd 0
257
    name dd 0
258
    name#.type = 1
258
    name#.type = 1
259
;  endg
259
;  endg
260
}
260
}
261
macro WaitSimpleMutex name
261
macro WaitSimpleMutex name
262
{
262
{
263
  local start_wait,ok
263
  local start_wait,ok
264
start_wait=$
264
start_wait=$
265
        cli
265
        cli
266
        cmp     [name], dword 0
266
        cmp     [name], dword 0
267
        jz      ok
267
        jz      ok
268
        sti
268
        sti
269
        call    change_task
269
        call    change_task
270
        jmp     start_wait
270
        jmp     start_wait
271
ok=$
271
ok=$
272
        push    eax
272
        push    eax
273
        mov     eax, dword [TASK_BASE+second_base_address]
273
        mov     eax, dword [TASK_BASE+second_base_address]
274
        mov     eax, [eax+TASKDATA.pid]
274
        mov     eax, [eax+TASKDATA.pid]
275
        mov     [name], eax
275
        mov     [name], eax
276
        pop     eax
276
        pop     eax
277
        sti
277
        sti
278
}
278
}
279
macro ReleaseSimpleMutex name
279
macro ReleaseSimpleMutex name
280
{
280
{
281
        mov     [name], dword 0
281
        mov     [name], dword 0
282
}
282
}
283
macro TryWaitSimpleMutex name  ;result in eax and in flags
283
macro TryWaitSimpleMutex name  ;result in eax and in flags
284
{
284
{
285
  local ok,try_end
285
  local ok,try_end
286
        cmp     [name], dword 0
286
        cmp     [name], dword 0
287
        jz      ok
287
        jz      ok
288
        xor     eax, eax
288
        xor     eax, eax
289
        jmp     try_end
289
        jmp     try_end
290
ok=$
290
ok=$
291
        xor     eax, eax
291
        xor     eax, eax
292
        inc     eax
292
        inc     eax
293
try_end=$
293
try_end=$
294
}
294
}
295
macro SimpleCriticalSection name
295
macro SimpleCriticalSection name
296
{
296
{
297
;  iglobal
297
;  iglobal
298
    name  dd 0
298
    name  dd 0
299
          dd 0
299
          dd 0
300
    name#.type=2
300
    name#.type=2
301
;  endg
301
;  endg
302
}
302
}
303
macro WaitSimpleCriticalSection name
303
macro WaitSimpleCriticalSection name
304
{
304
{
305
  local start_wait,first_wait,inc_counter,end_wait
305
  local start_wait,first_wait,inc_counter,end_wait
306
        push    eax
306
        push    eax
307
        mov     eax, [TASK_BASE+second_base_address]
307
        mov     eax, [TASK_BASE+second_base_address]
308
        mov     eax, [eax+TASKDATA.pid]
308
        mov     eax, [eax+TASKDATA.pid]
309
start_wait=$
309
start_wait=$
310
        cli
310
        cli
311
        cmp     [name], dword 0
311
        cmp     [name], dword 0
312
        jz      first_wait
312
        jz      first_wait
313
        cmp     [name], eax
313
        cmp     [name], eax
314
        jz      inc_counter
314
        jz      inc_counter
315
        sti
315
        sti
316
        call    change_task
316
        call    change_task
317
        jmp     start_wait
317
        jmp     start_wait
318
first_wait=$
318
first_wait=$
319
        mov     [name], eax
319
        mov     [name], eax
320
        mov     [name+4], dword 1
320
        mov     [name+4], dword 1
321
        jmp     end_wait
321
        jmp     end_wait
322
inc_counter=$
322
inc_counter=$
323
        inc     dword [name+4]
323
        inc     dword [name+4]
324
end_wait=$
324
end_wait=$
325
        sti
325
        sti
326
        pop     eax
326
        pop     eax
327
}
327
}
328
macro ReleaseSimpleCriticalSection name
328
macro ReleaseSimpleCriticalSection name
329
{
329
{
330
  local release_end
330
  local release_end
331
        dec     dword [name+4]
331
        dec     dword [name+4]
332
        jnz     release_end
332
        jnz     release_end
333
        mov     [name], dword 0
333
        mov     [name], dword 0
334
release_end=$
334
release_end=$
335
}
335
}
336
macro TryWaitSimpleCriticalSection name ;result in eax and in flags
336
macro TryWaitSimpleCriticalSection name ;result in eax and in flags
337
{
337
{
338
  local ok,try_end
338
  local ok,try_end
339
        mov     eax, [CURRENT_TASK+second_base_address]
339
        mov     eax, [CURRENT_TASK+second_base_address]
340
        mov     eax, [eax+TASKDATA.pid]
340
        mov     eax, [eax+TASKDATA.pid]
341
        cmp     [name], eax
341
        cmp     [name], eax
342
        jz      ok
342
        jz      ok
343
        cmp     [name], 0
343
        cmp     [name], 0
344
        jz      ok
344
        jz      ok
345
        xor     eax, eax
345
        xor     eax, eax
346
        jmp     try_end
346
        jmp     try_end
347
ok=$
347
ok=$
348
        xor     eax, eax
348
        xor     eax, eax
349
        inc     eax
349
        inc     eax
350
try_end=$
350
try_end=$
351
}
351
}
352
_cli equ call MEM_HeapLock
352
_cli equ call MEM_HeapLock
353
_sti equ call MEM_HeapUnLock
353
_sti equ call MEM_HeapUnLock
354
end if
354
end if