Rev 5565 | Rev 5596 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5565 | Rev 5593 | ||
---|---|---|---|
Line 3... | Line 3... | ||
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 | ;; ;; |
|
- | 9 | ;; ;; |
|
- | 10 | ;; ;; |
|
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
11 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Line 9... | Line 12... | ||
9 | 12 | ||
- | 13 | $Revision: 5593 $ |
|
- | 14 | ||
- | 15 | align 4 |
|
- | 16 | ;struct futex* __fastcall create_futex(int *ptr) |
|
- | 17 | create_futex: |
|
- | 18 | push ecx |
|
- | 19 | mov ecx, sizeof.FUTEX |
|
- | 20 | call create_object |
|
- | 21 | pop ecx |
|
- | 22 | test eax, eax |
|
- | 23 | jz .fail |
|
- | 24 | ||
- | 25 | mov [eax+FUTEX.magic], 'FUTX' |
|
- | 26 | mov [eax+FUTEX.destroy], 0 |
|
- | 27 | mov [eax+FUTEX.pointer], ecx |
|
- | 28 | lea ecx, [eax+FUTEX.wait_list] |
|
- | 29 | list_init ecx |
|
- | 30 | mov [eax+FUTEX.flags], 0 |
|
- | 31 | .fail: |
|
- | 32 | ret |
|
- | 33 | ||
- | 34 | iglobal |
|
- | 35 | align 4 |
|
- | 36 | f77call: |
|
- | 37 | dd f77.futex_init ;0 |
|
- | 38 | dd f77.futex_wait ;1 |
|
- | 39 | dd f77.futex_wake ;2 |
|
- | 40 | .end: |
|
- | 41 | endg |
|
- | 42 | ||
- | 43 | align 4 |
|
- | 44 | sys_synchronization: |
|
- | 45 | f77: |
|
- | 46 | cmp ebx, (f77call.end-f77call)/4 |
|
- | 47 | jae .fail |
|
- | 48 | ||
- | 49 | jmp dword [f77call+ebx*4] |
|
- | 50 | ||
- | 51 | .fail: |
|
- | 52 | mov [esp+SYSCALL_STACK._eax], -1 |
|
- | 53 | ret |
|
- | 54 | ||
- | 55 | ||
- | 56 | align 4 |
|
- | 57 | .futex_init: |
|
- | 58 | call create_futex |
|
- | 59 | test eax, eax |
|
- | 60 | jz @F |
|
- | 61 | mov eax, [eax+FUTEX.handle] |
|
- | 62 | @@: |
|
- | 63 | mov [esp+SYSCALL_STACK._eax], eax |
|
- | 64 | ret |
|
- | 65 | ||
- | 66 | align 4 |
|
- | 67 | ;ecx futex handle |
|
- | 68 | ;edx control value |
|
- | 69 | .futex_wait: |
|
- | 70 | cmp ecx, 3 |
|
- | 71 | jb .epicfail |
|
- | 72 | cmp ecx, (PROC.pdt_0 - PROC.htab)/4 |
|
- | 73 | jae .epicfail |
|
- | 74 | ||
- | 75 | mov esi, [current_process] |
|
- | 76 | mov edi, [esi+PROC.htab+ecx*4] |
|
- | 77 | ||
- | 78 | cmp [edi+FUTEX.magic], 'FUTX' |
|
- | 79 | jne .epicfail |
|
- | 80 | cmp [edi+FUTEX.handle], ecx |
|
- | 81 | jne .epicfail |
|
- | 82 | ||
- | 83 | mov ecx, [edi+FUTEX.pointer] |
|
- | 84 | ||
- | 85 | mov eax, edx |
|
- | 86 | lock cmpxchg [ecx], edx ;wait until old_value == new_value |
|
- | 87 | jz .wait_slow |
|
- | 88 | ||
- | 89 | mov [esp+SYSCALL_STACK._eax], 0 |
|
- | 90 | ret |
|
- | 91 | ||
- | 92 | .wait_slow: |
|
- | 93 | pushfd |
|
- | 94 | cli |
|
- | 95 | ||
- | 96 | sub esp, sizeof.MUTEX_WAITER |
|
- | 97 | mov ebx, [TASK_BASE] |
|
- | 98 | mov [ebx+TASKDATA.state], 1 |
|
- | 99 | mov [esp+MUTEX_WAITER.task], ebx |
|
- | 100 | lea esi, [edi+FUTEX.wait_list] |
|
- | 101 | ||
- | 102 | list_add_tail esp, esi ;esp= new waiter, esi= list head |
|
- | 103 | ||
- | 104 | .again: |
|
- | 105 | call change_task |
|
- | 106 | ||
- | 107 | lock cmpxchg [ecx], edx |
|
- | 108 | jz .again |
|
- | 109 | ||
- | 110 | list_del esp |
|
- | 111 | add esp, sizeof.MUTEX_WAITER |
|
- | 112 | ||
- | 113 | popfd |
|
- | 114 | mov [esp+SYSCALL_STACK._eax], 0 |
|
- | 115 | ret |
|
- | 116 | ||
- | 117 | .epicfail: |
|
- | 118 | mov [esp+SYSCALL_STACK._eax], -1 |
|
- | 119 | ret |
|
- | 120 | ||
- | 121 | align 4 |
|
- | 122 | ;ecx futex handle |
|
- | 123 | ;edx threads count |
|
- | 124 | .futex_wake: |
|
- | 125 | cmp ecx, 3 |
|
- | 126 | jb .epicfail |
|
- | 127 | cmp ecx, (PROC.pdt_0 - PROC.htab)/4 |
|
- | 128 | jae .epicfail |
|
- | 129 | ||
- | 130 | mov esi, [current_process] |
|
- | 131 | mov edi, [esi+PROC.htab+ecx*4] |
|
- | 132 | ||
- | 133 | cmp [edi+FUTEX.magic], 'FUTX' |
|
- | 134 | jne .epicfail |
|
- | 135 | cmp [edi+FUTEX.handle], ecx |
|
- | 136 | jne .epicfail |
|
- | 137 | ||
- | 138 | xor ecx, ecx |
|
- | 139 | ||
- | 140 | pushfd |
|
- | 141 | cli |
|
- | 142 | ||
- | 143 | lea ebx, [edi+FUTEX.wait_list] |
|
- | 144 | mov esi, [edi+FUTEX.wait_list.next] |
|
- | 145 | @@: |
|
- | 146 | cmp esi, ebx |
|
- | 147 | je @F |
|
- | 148 | ||
- | 149 | mov eax, [esi+MUTEX_WAITER.task] |
|
- | 150 | mov [eax+TASKDATA.state], 0 |
|
- | 151 | ||
- | 152 | mov esi, [esi+MUTEX_WAITER.list.next] |
|
- | 153 | inc ecx |
|
- | 154 | cmp ecx, edx |
|
- | 155 | jb @B |
|
- | 156 | @@: |
|
- | 157 | popfd |
|
- | 158 | mov [esp+SYSCALL_STACK._eax], ecx |
|
- | 159 | ret |
|
- | 160 | ||
- | 161 | RWSEM_WAITING_FOR_WRITE equ 0 |
|
- | 162 | RWSEM_WAITING_FOR_READ equ 1 |
|
- | 163 | ||
- | 164 | ;void __fastcall mutex_init(struct mutex *lock) |
|
- | 165 | ||
- | 166 | align 4 |
|
- | 167 | mutex_init: |
|
- | 168 | mov [ecx+MUTEX.wait_list.next], ecx |
|
- | 169 | mov [ecx+MUTEX.wait_list.prev], ecx |
|
- | 170 | mov [ecx+MUTEX.count], 1 |
|
- | 171 | ret |
|
- | 172 | ||
- | 173 | ;void __fastcall mutex_lock(struct mutex *lock) |
|
- | 174 | ||
- | 175 | align 4 |
|
- | 176 | mutex_lock: |
|
- | 177 | ||
- | 178 | dec [ecx+MUTEX.count] |
|
- | 179 | jns .done |
|
- | 180 | ||
- | 181 | pushfd |
|
- | 182 | cli |
|
- | 183 | ||
- | 184 | sub esp, sizeof.MUTEX_WAITER |
|
- | 185 | ||
- | 186 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
|
- | 187 | ||
- | 188 | mov edx, [TASK_BASE] |
|
- | 189 | mov [esp+MUTEX_WAITER.task], edx |
|
- | 190 | ||
- | 191 | .forever: |
|
- | 192 | ||
- | 193 | mov eax, -1 |
|
- | 194 | xchg eax, [ecx+MUTEX.count] |
|
- | 195 | dec eax |
|
- | 196 | jz @F |
|
- | 197 | ||
- | 198 | mov [edx+TASKDATA.state], 1 |
|
- | 199 | call change_task |
|
- | 200 | jmp .forever |
|
- | 201 | @@: |
|
- | 202 | mov eax, ecx |
|
- | 203 | list_del esp |
|
- | 204 | ||
- | 205 | cmp [eax+MUTEX.wait_list.next], eax |
|
- | 206 | jne @F |
|
- | 207 | ||
- | 208 | mov [eax+MUTEX.count], 0 |
|
- | 209 | @@: |
|
- | 210 | add esp, sizeof.MUTEX_WAITER |
|
- | 211 | ||
- | 212 | popfd |
|
- | 213 | .done: |
|
- | 214 | ret |
|
- | 215 | ||
- | 216 | ;void __fastcall mutex_unlock(struct mutex *lock) |
|
- | 217 | ||
- | 218 | align 4 |
|
- | 219 | mutex_unlock: |
|
- | 220 | ||
- | 221 | pushfd |
|
- | 222 | cli |
|
- | 223 | ||
- | 224 | mov eax, [ecx+MUTEX.wait_list.next] |
|
- | 225 | cmp eax, ecx |
|
- | 226 | mov [ecx+MUTEX.count], 1 |
|
- | 227 | je @F |
|
- | 228 | ||
- | 229 | mov eax, [eax+MUTEX_WAITER.task] |
|
- | 230 | mov [eax+TASKDATA.state], 0 |
|
- | 231 | @@: |
|
- | 232 | popfd |
|
- | 233 | ret |
|
- | 234 | ||
- | 235 | ||
- | 236 | ;void __fastcall init_rwsem(struct rw_semaphore *sem) |
|
- | 237 | ||
- | 238 | align 4 |
|
- | 239 | init_rwsem: |
|
- | 240 | mov [ecx+RWSEM.wait_list.next], ecx |
|
- | 241 | mov [ecx+RWSEM.wait_list.prev], ecx |
|
- | 242 | mov [ecx+RWSEM.count], 0 |
|
- | 243 | ret |
|
- | 244 | ||
- | 245 | ;void __fastcall down_read(struct rw_semaphore *sem) |
|
- | 246 | ||
- | 247 | align 4 |
|
- | 248 | down_read: |
|
- | 249 | pushfd |
|
- | 250 | cli |
|
- | 251 | ||
- | 252 | mov eax, [ecx+RWSEM.count] |
|
- | 253 | test eax, eax |
|
- | 254 | js @F |
|
- | 255 | ||
- | 256 | cmp ecx, [ecx+RWSEM.wait_list.next] |
|
- | 257 | je .ok |
|
- | 258 | @@: |
|
- | 259 | sub esp, sizeof.MUTEX_WAITER |
|
- | 260 | ||
- | 261 | mov eax, [TASK_BASE] |
|
- | 262 | mov [esp+MUTEX_WAITER.task], eax |
|
- | 263 | mov [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ |
|
- | 264 | mov [eax+TASKDATA.state], 1 |
|
- | 265 | ||
- | 266 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
|
- | 267 | ||
- | 268 | call change_task |
|
- | 269 | ||
- | 270 | add esp, sizeof.MUTEX_WAITER |
|
- | 271 | popfd |
|
- | 272 | ret |
|
- | 273 | .ok: |
|
- | 274 | inc eax |
|
- | 275 | mov [ecx+RWSEM.count], eax |
|
- | 276 | ||
- | 277 | popfd |
|
- | 278 | ret |
|
- | 279 | ||
- | 280 | ;void __fastcall down_write(struct rw_semaphore *sem) |
|
- | 281 | ||
- | 282 | align 4 |
|
- | 283 | down_write: |
|
- | 284 | pushfd |
|
- | 285 | cli |
|
- | 286 | sub esp, sizeof.MUTEX_WAITER |
|
- | 287 | ||
- | 288 | mov edx, [TASK_BASE] |
|
- | 289 | mov [esp+MUTEX_WAITER.task], edx |
|
- | 290 | mov [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE |
|
- | 291 | mov [edx+TASKDATA.state], 1 |
|
- | 292 | ||
- | 293 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
|
- | 294 | ||
- | 295 | xor eax, eax |
|
- | 296 | not eax |
|
- | 297 | ||
- | 298 | .forever: |
|
- | 299 | test eax, [ecx+RWSEM.count] |
|
- | 300 | jz @F |
|
- | 301 | ||
- | 302 | mov [edx+TASKDATA.state], 1 |
|
- | 303 | call change_task |
|
- | 304 | jmp .forever |
|
- | 305 | @@: |
|
- | 306 | mov [ecx+RWSEM.count], eax |
|
- | 307 | list_del esp |
|
- | 308 | ||
- | 309 | add esp, sizeof.MUTEX_WAITER |
|
- | 310 | popfd |
|
- | 311 | ret |
|
- | 312 | ||
- | 313 | ;void __fastcall up_read(struct rw_semaphore *sem) |
|
- | 314 | ||
- | 315 | align 4 |
|
- | 316 | up_read: |
|
- | 317 | pushfd |
|
- | 318 | cli |
|
- | 319 | ||
- | 320 | dec [ecx+RWSEM.count] |
|
- | 321 | jnz @F |
|
- | 322 | ||
- | 323 | mov eax, [ecx+RWSEM.wait_list.next] |
|
- | 324 | cmp eax, ecx |
|
- | 325 | je @F |
|
- | 326 | ||
- | 327 | mov eax, [eax+MUTEX_WAITER.task] |
|
- | 328 | mov [eax+TASKDATA.state], 0 |
|
- | 329 | @@: |
|
- | 330 | popfd |
|
- | 331 | ret |
|
- | 332 | ||
- | 333 | ;void __fastcall up_write(struct rw_semaphore *sem) |
|
- | 334 | ||
- | 335 | align 4 |
|
- | 336 | up_write: |
|
- | 337 | ||
- | 338 | pushfd |
|
- | 339 | cli |
|
- | 340 | ||
- | 341 | mov eax, [ecx+RWSEM.wait_list.next] |
|
- | 342 | mov [ecx+RWSEM.count], 0 |
|
- | 343 | ||
- | 344 | cmp ecx, eax |
|
- | 345 | je .done |
|
- | 346 | ||
- | 347 | mov edx, [eax+MUTEX_WAITER.type] |
|
- | 348 | test edx, edx |
|
- | 349 | jnz .wake |
|
- | 350 | ||
- | 351 | mov eax, [eax+MUTEX_WAITER.task] |
|
- | 352 | mov [eax+TASKDATA.state], 0 |
|
- | 353 | .done: |
|
- | 354 | popfd |
|
- | 355 | ret |
|
- | 356 | ||
- | 357 | .wake: |
|
- | 358 | push ebx |
|
- | 359 | push esi |
|
- | 360 | push edi |
|
- | 361 | ||
- | 362 | xor esi, esi |
|
- | 363 | mov edi, ecx |
|
- | 364 | ||
- | 365 | .wake_list: |
|
- | 366 | ||
- | 367 | mov ebx, [eax+MUTEX_WAITER.list.next] |
|
- | 368 | list_del eax |
|
- | 369 | mov edx, [eax+MUTEX_WAITER.task] |
|
- | 370 | mov [edx+TASKDATA.state], 0 |
|
- | 371 | inc esi |
|
- | 372 | cmp edi, ebx |
|
- | 373 | je .wake_done |
|
- | 374 | ||
- | 375 | mov ecx, [ebx+MUTEX_WAITER.type] |
|
- | 376 | test ecx, ecx |
|
- | 377 | jz .wake_done |
|
- | 378 | ||
- | 379 | mov eax, ebx |
|
- | 380 | jmp .wake_list |
|
- | 381 | ||
- | 382 | .wake_done: |
|
- | 383 | add [edi+RWSEM.count], esi |
|
- | 384 | ||
- | 385 | pop edi |
|
- | 386 | pop esi |
|
- | 387 | pop ebx |
|
- | 388 | popfd |
|
- | 389 | ret |
|
- | 390 | ||
- | 391 | ||
- | 392 | purge MUTEX_WAITER |
|
- | 393 | purge RWSEM_WAITING_FOR_WRITE |
|
Line 10... | Line 394... | ||
10 | $Revision: 5565 $ |
394 | purge RWSEM_WAITING_FOR_READ |
11 | 395 | ||
12 | 396 |