Rev 6926 | Rev 8876 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6926 | Rev 8130 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2017. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2017. 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 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7 | 7 | ||
8 | $Revision: 6917 $ |
8 | $Revision: 8130 $ |
9 | 9 | ||
10 | align 4 |
10 | align 4 |
11 | ;struct futex* __fastcall create_futex(int *ptr) |
11 | ;struct futex* __fastcall create_futex(int *ptr) |
12 | create_futex: |
12 | create_futex: |
13 | push ecx |
13 | push ecx |
14 | mov ecx, sizeof.FUTEX |
14 | mov ecx, sizeof.FUTEX |
15 | call create_object |
15 | call create_object |
16 | pop ecx |
16 | pop ecx |
17 | test eax, eax |
17 | test eax, eax |
18 | jz .fail |
18 | jz .fail |
19 | 19 | ||
20 | mov [eax+FUTEX.magic], 'FUTX' |
20 | mov [eax+FUTEX.magic], 'FUTX' |
21 | mov [eax+FUTEX.destroy], 0 |
21 | mov [eax+FUTEX.destroy], 0 |
22 | mov [eax+FUTEX.pointer], ecx |
22 | mov [eax+FUTEX.pointer], ecx |
23 | lea ecx, [eax+FUTEX.wait_list] |
23 | lea ecx, [eax+FUTEX.wait_list] |
24 | list_init ecx |
24 | list_init ecx |
25 | mov [eax+FUTEX.flags], 0 |
25 | mov [eax+FUTEX.flags], 0 |
26 | .fail: |
26 | .fail: |
27 | ret |
27 | ret |
28 | 28 | ||
29 | align 4 |
29 | align 4 |
30 | ;int __fastcall destroy_futex(struct futex *futex) |
30 | ;int __fastcall destroy_futex(struct futex *futex) |
31 | destroy_futex: |
31 | destroy_futex: |
32 | push esi |
32 | push esi |
33 | mov esi, [current_process] |
33 | mov esi, [current_process] |
34 | mov edx, [ecx+FUTEX.handle] |
34 | mov edx, [ecx+FUTEX.handle] |
35 | 35 | ||
36 | pushfd |
36 | pushfd |
37 | cli |
37 | cli |
38 | 38 | ||
39 | lea eax, [ecx+FUTEX.wait_list] |
39 | lea eax, [ecx+FUTEX.wait_list] |
40 | cmp eax, [eax+LHEAD.next] |
40 | cmp eax, [eax+LHEAD.next] |
41 | jne .fail |
41 | jne .fail |
42 | 42 | ||
43 | mov eax, [esi+PROC.ht_next] |
43 | mov eax, [esi+PROC.ht_next] |
44 | mov [esi+PROC.htab+edx*4], eax |
44 | mov [esi+PROC.htab+edx*4], eax |
45 | mov [esi+PROC.ht_next], edx |
45 | mov [esi+PROC.ht_next], edx |
46 | inc [esi+PROC.ht_free] |
46 | inc [esi+PROC.ht_free] |
47 | 47 | ||
48 | popfd |
48 | popfd |
49 | pop esi |
49 | pop esi |
50 | 50 | ||
51 | mov eax, ecx |
51 | mov eax, ecx |
52 | call free |
52 | call free |
53 | xor eax, eax |
53 | xor eax, eax |
54 | ret |
54 | ret |
55 | 55 | ||
56 | .fail: |
56 | .fail: |
57 | popfd |
57 | popfd |
58 | pop esi |
58 | pop esi |
59 | mov eax, -1 |
59 | mov eax, -1 |
60 | ret |
60 | ret |
61 | 61 | ||
62 | align 4 |
62 | align 4 |
63 | sys_futex: |
63 | sys_futex: |
64 | cmp ecx, STDERR_FILENO |
64 | cmp ecx, STDERR_FILENO |
65 | jbe .fail |
65 | jbe .fail |
66 | cmp ecx, (PROC.pdt_0 - PROC.htab)/4 |
66 | cmp ecx, (PROC.pdt_0 - PROC.htab)/4 |
67 | jae .fail |
67 | jae .fail |
68 | 68 | ||
69 | mov edi, [current_process] |
69 | mov edi, [current_process] |
70 | mov ebp, [edi+PROC.htab+ecx*4] |
70 | mov ebp, [edi+PROC.htab+ecx*4] |
71 | 71 | ||
72 | cmp [ebp+FUTEX.magic], 'FUTX' |
72 | cmp [ebp+FUTEX.magic], 'FUTX' |
73 | jne .fail |
73 | jne .fail |
74 | cmp [ebp+FUTEX.handle], ecx |
74 | cmp [ebp+FUTEX.handle], ecx |
75 | jne .fail |
75 | jne .fail |
76 | 76 | ||
77 | jmp dword [sys_futex_call+ebx*4-4] |
77 | jmp dword [sys_futex_call+ebx*4-4] |
78 | 78 | ||
79 | .fail: |
79 | .fail: |
80 | .requeue: |
80 | .requeue: |
81 | .cmp_requeue: |
81 | .cmp_requeue: |
82 | .wait_bitset: |
82 | .wait_bitset: |
83 | .wake_bitset: |
83 | .wake_bitset: |
84 | mov [esp+SYSCALL_STACK._eax], -1 |
84 | mov [esp+SYSCALL_STACK._eax], -1 |
85 | ret |
85 | ret |
86 | 86 | ||
87 | align 4 |
87 | align 4 |
88 | .init: |
88 | .init: |
89 | call create_futex |
89 | call create_futex |
90 | test eax, eax |
90 | test eax, eax |
91 | jz @F |
91 | jz @F |
92 | mov eax, [eax+FUTEX.handle] |
92 | mov eax, [eax+FUTEX.handle] |
93 | @@: |
93 | @@: |
94 | mov [esp+SYSCALL_STACK._eax], eax |
94 | mov [esp+SYSCALL_STACK._eax], eax |
95 | ret |
95 | ret |
96 | 96 | ||
97 | align 4 |
97 | align 4 |
98 | ;ecx futex handle |
98 | ;ecx futex handle |
99 | ;edi current process |
99 | ;edi current process |
100 | ;ebp futex object |
100 | ;ebp futex object |
101 | .destroy: |
101 | .destroy: |
102 | mov ecx, ebp |
102 | mov ecx, ebp |
103 | call destroy_futex |
103 | call destroy_futex |
104 | mov [esp+SYSCALL_STACK._eax], eax |
104 | mov [esp+SYSCALL_STACK._eax], eax |
105 | ret |
105 | ret |
106 | 106 | ||
107 | align 4 |
107 | align 4 |
108 | ;ecx futex handle |
108 | ;ecx futex handle |
109 | ;edx control value |
109 | ;edx control value |
110 | ;esi timeout |
110 | ;esi timeout |
111 | ;edi current process |
111 | ;edi current process |
112 | ;ebp futex object |
112 | ;ebp futex object |
113 | .wait: |
113 | .wait: |
114 | test esi, esi |
114 | test esi, esi |
115 | jnz .wait_timeout |
115 | jnz .wait_timeout |
116 | mov ecx, [ebp+FUTEX.pointer] |
116 | mov ecx, [ebp+FUTEX.pointer] |
117 | mov eax, edx |
117 | mov eax, edx |
118 | lock cmpxchg [ecx], edx |
118 | lock cmpxchg [ecx], edx |
119 | je .wait_slow |
119 | je .wait_slow |
120 | 120 | ||
121 | mov [esp+SYSCALL_STACK._eax], -2 |
121 | mov [esp+SYSCALL_STACK._eax], -2 |
122 | ret |
122 | ret |
123 | 123 | ||
124 | .wait_slow: |
124 | .wait_slow: |
125 | pushfd |
125 | pushfd |
126 | cli |
126 | cli |
127 | 127 | ||
128 | sub esp, sizeof.MUTEX_WAITER |
128 | sub esp, sizeof.MUTEX_WAITER |
129 | mov ebx, [TASK_BASE] |
129 | mov ebx, [TASK_BASE] |
130 | mov [esp+MUTEX_WAITER.task], ebx |
130 | mov [esp+MUTEX_WAITER.task], ebx |
131 | lea esi, [ebp+FUTEX.wait_list] |
131 | lea esi, [ebp+FUTEX.wait_list] |
132 | 132 | ||
133 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
133 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
134 | mov eax, edx |
134 | mov eax, edx |
135 | .again: |
135 | .again: |
136 | mov [ebx+TASKDATA.state], 1 |
136 | mov [ebx+TASKDATA.state], 1 |
137 | call change_task |
137 | call change_task |
138 | 138 | ||
139 | lock cmpxchg [ecx], edx |
139 | lock cmpxchg [ecx], edx |
140 | je .again |
140 | je .again |
141 | 141 | ||
142 | list_del esp |
142 | list_del esp |
143 | add esp, sizeof.MUTEX_WAITER |
143 | add esp, sizeof.MUTEX_WAITER |
144 | 144 | ||
145 | popfd |
145 | popfd |
146 | mov [esp+SYSCALL_STACK._eax], 0 |
146 | mov [esp+SYSCALL_STACK._eax], 0 |
147 | ret |
147 | ret |
148 | 148 | ||
149 | align 4 |
149 | align 4 |
150 | ;ecx futex handle |
150 | ;ecx futex handle |
151 | ;edx control value |
151 | ;edx control value |
152 | ;esi timeout |
152 | ;esi timeout |
153 | ;edi current process |
153 | ;edi current process |
154 | ;ebp futex object |
154 | ;ebp futex object |
155 | 155 | ||
156 | .wait_timeout: |
156 | .wait_timeout: |
157 | mov ecx, [ebp+FUTEX.pointer] |
157 | mov ecx, [ebp+FUTEX.pointer] |
158 | mov eax, edx |
158 | mov eax, edx |
159 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
159 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
160 | je .wait_slow_timeout |
160 | je .wait_slow_timeout |
161 | 161 | ||
162 | mov [esp+SYSCALL_STACK._eax], -2 |
162 | mov [esp+SYSCALL_STACK._eax], -2 |
163 | ret |
163 | ret |
164 | 164 | ||
165 | align 4 |
165 | align 4 |
166 | .wait_test: |
166 | .wait_test: |
167 | xor eax, eax |
167 | xor eax, eax |
168 | ret |
168 | ret |
169 | 169 | ||
170 | .wait_slow_timeout: |
170 | .wait_slow_timeout: |
171 | pushfd |
171 | pushfd |
172 | cli |
172 | cli |
173 | 173 | ||
174 | sub esp, sizeof.MUTEX_WAITER |
174 | sub esp, sizeof.MUTEX_WAITER |
175 | 175 | ||
176 | mov ebx, [current_slot] |
176 | mov ebx, [current_slot] |
177 | mov [ebx+APPDATA.wait_test], sys_futex.wait_test |
177 | mov [ebx+APPDATA.wait_test], sys_futex.wait_test |
178 | mov [ebx+APPDATA.wait_timeout], esi |
178 | mov [ebx+APPDATA.wait_timeout], esi |
179 | mov [ebx+APPDATA.wait_param], ebp |
179 | mov [ebx+APPDATA.wait_param], ebp |
180 | mov eax, [timer_ticks] |
180 | mov eax, [timer_ticks] |
181 | mov [ebx+APPDATA.wait_begin], eax |
181 | mov [ebx+APPDATA.wait_begin], eax |
182 | mov eax, [TASK_BASE] |
182 | mov eax, [TASK_BASE] |
183 | mov [eax+TASKDATA.state], 5 |
183 | mov [eax+TASKDATA.state], 5 |
184 | 184 | ||
185 | mov [esp+MUTEX_WAITER.task], eax |
185 | mov [esp+MUTEX_WAITER.task], eax |
186 | lea esi, [ebp+FUTEX.wait_list] |
186 | lea esi, [ebp+FUTEX.wait_list] |
187 | 187 | ||
188 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
188 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
189 | 189 | ||
190 | .again_timeout: |
190 | .again_timeout: |
191 | call change_task |
191 | call change_task |
192 | mov eax, [ebx+APPDATA.wait_param] |
192 | mov eax, [ebx+APPDATA.wait_param] |
193 | test eax, eax |
193 | test eax, eax |
194 | jz .timeout |
194 | jz .timeout |
195 | 195 | ||
196 | mov eax, edx |
196 | mov eax, edx |
197 | lock cmpxchg [ecx], edx |
197 | lock cmpxchg [ecx], edx |
198 | jz .again_timeout |
198 | jz .again_timeout |
199 | @@: |
199 | @@: |
200 | list_del esp |
200 | list_del esp |
201 | add esp, sizeof.MUTEX_WAITER |
201 | add esp, sizeof.MUTEX_WAITER |
202 | 202 | ||
203 | popfd |
203 | popfd |
204 | mov [esp+SYSCALL_STACK._eax], 0 |
204 | mov [esp+SYSCALL_STACK._eax], 0 |
205 | ret |
205 | ret |
206 | 206 | ||
207 | .timeout: |
207 | .timeout: |
208 | list_del esp |
208 | list_del esp |
209 | add esp, sizeof.MUTEX_WAITER |
209 | add esp, sizeof.MUTEX_WAITER |
210 | 210 | ||
211 | popfd |
211 | popfd |
212 | mov [esp+SYSCALL_STACK._eax], -1 |
212 | mov [esp+SYSCALL_STACK._eax], -1 |
213 | ret |
213 | ret |
214 | 214 | ||
215 | 215 | ||
216 | align 4 |
216 | align 4 |
217 | ;ecx futex handle |
217 | ;ecx futex handle |
218 | ;edx number of threads |
218 | ;edx number of threads |
219 | ;edi current process |
219 | ;edi current process |
220 | ;ebp futex object |
220 | ;ebp futex object |
221 | .wake: |
221 | .wake: |
222 | 222 | ||
223 | xor ecx, ecx |
223 | xor ecx, ecx |
224 | 224 | ||
225 | pushfd |
225 | pushfd |
226 | cli |
226 | cli |
227 | 227 | ||
228 | lea ebx, [ebp+FUTEX.wait_list] |
228 | lea ebx, [ebp+FUTEX.wait_list] |
229 | mov esi, [ebx+LHEAD.next] |
229 | mov esi, [ebx+LHEAD.next] |
230 | .again_wake: |
230 | .again_wake: |
231 | cmp esi, ebx |
231 | cmp esi, ebx |
232 | je .done |
232 | je .done |
233 | 233 | ||
234 | mov eax, [esi+MUTEX_WAITER.task] |
234 | mov eax, [esi+MUTEX_WAITER.task] |
235 | mov [eax+TASKDATA.state], 0 |
235 | mov [eax+TASKDATA.state], 0 |
236 | 236 | ||
237 | mov esi, [esi+MUTEX_WAITER.list.next] |
237 | mov esi, [esi+MUTEX_WAITER.list.next] |
238 | inc ecx |
238 | inc ecx |
239 | cmp ecx, edx |
239 | cmp ecx, edx |
240 | jb .again_wake |
240 | jb .again_wake |
241 | .done: |
241 | .done: |
242 | popfd |
242 | popfd |
243 | mov [esp+SYSCALL_STACK._eax], ecx |
243 | mov [esp+SYSCALL_STACK._eax], ecx |
244 | ret |
244 | ret |