Subversion Repositories Kolibri OS

Rev

Rev 5593 | Rev 5597 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;; Synhronization for MenuetOS.                                 ;;
  7. ;; Author: Halyavin Andrey, halyavin@land.ru                    ;;
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9.  
  10. $Revision: 5596 $
  11.  
  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
  21.  
  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.  
  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
  408. start_wait=$
  409.         cli
  410.         cmp     [name], dword 0
  411.         jz      ok
  412.         sti
  413.         call    change_task
  414.         jmp     start_wait
  415. ok=$
  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
  422. }
  423. macro ReleaseSimpleMutex name
  424. {
  425.         mov     [name], dword 0
  426. }
  427. macro TryWaitSimpleMutex name  ;result in eax and in flags
  428. {
  429.   local ok,try_end
  430.         cmp     [name], dword 0
  431.         jz      ok
  432.         xor     eax, eax
  433.         jmp     try_end
  434. ok=$
  435.         xor     eax, eax
  436.         inc     eax
  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
  450.         push    eax
  451.         mov     eax, [TASK_BASE+second_base_address]
  452.         mov     eax, [eax+TASKDATA.pid]
  453. start_wait=$
  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
  462. first_wait=$
  463.         mov     [name], eax
  464.         mov     [name+4], dword 1
  465.         jmp     end_wait
  466. inc_counter=$
  467.         inc     dword [name+4]
  468. end_wait=$
  469.         sti
  470.         pop     eax
  471. }
  472. macro ReleaseSimpleCriticalSection name
  473. {
  474.   local release_end
  475.         dec     dword [name+4]
  476.         jnz     release_end
  477.         mov     [name], dword 0
  478. release_end=$
  479. }
  480. macro TryWaitSimpleCriticalSection name ;result in eax and in flags
  481. {
  482.   local ok,try_end
  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
  491. ok=$
  492.         xor     eax, eax
  493.         inc     eax
  494. try_end=$
  495. }
  496. _cli equ call MEM_HeapLock
  497. _sti equ call MEM_HeapUnLock
  498. end if
  499.  
  500.