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 |