Subversion Repositories Kolibri OS

Rev

Rev 5596 | Rev 5599 | 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: 5597 $
  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. align 4
  32. ;int __fastcall destroy_futex(struct futex *futex)
  33. destroy_futex:
  34.         push    esi
  35.         mov     esi, [current_process]
  36.         mov     edx, [ecx+FUTEX.handle]
  37.  
  38.         pushfd
  39.         cli
  40.  
  41.         lea     eax, [ecx+FUTEX.wait_list]
  42.         cmp     eax, [eax+LHEAD.next]
  43.         jne     .fail
  44.  
  45.         mov     eax, [esi+PROC.ht_next]
  46.         mov     [esi+PROC.htab+edx*4], eax
  47.         mov     [esi+PROC.ht_next], edx
  48.         inc     [esi+PROC.ht_free]
  49.  
  50.         popfd
  51.         pop     esi
  52.  
  53.         mov     eax, ecx
  54.         call    free
  55.         xor     eax, eax
  56.         ret
  57.  
  58. .fail:
  59.         popfd
  60.         pop     esi
  61.         mov     eax, -1
  62.         ret
  63.  
  64.  
  65. iglobal
  66. align 4
  67. f77call:
  68.         dd f77.futex_init     ;0
  69.         dd f77.futex_destroy  ;1
  70.         dd f77.futex_wait     ;2
  71.         dd f77.futex_wake     ;3
  72. .end:
  73. endg
  74.  
  75. align 4
  76. sys_synchronization:
  77. f77:
  78.         test    ebx, ebx
  79.         jz      .futex_init
  80.  
  81.         cmp     ebx, (f77call.end-f77call)/4
  82.         jae     .fail
  83.  
  84.         cmp     ecx, STDERR_FILENO
  85.         jbe     .fail
  86.         cmp     ecx, (PROC.pdt_0 - PROC.htab)/4
  87.         jae     .fail
  88.  
  89.         mov     esi, [current_process]
  90.         mov     edi, [esi+PROC.htab+ecx*4]
  91.  
  92.         cmp     [edi+FUTEX.magic], 'FUTX'
  93.         jne     .fail
  94.         cmp     [edi+FUTEX.handle], ecx
  95.         jne     .fail
  96.  
  97.         jmp     dword [f77call+ebx*4]
  98.  
  99. .fail:
  100.         mov     [esp+SYSCALL_STACK._eax], -1
  101.         ret
  102.  
  103. align 4
  104. .futex_init:
  105.         call    create_futex
  106.         test    eax, eax
  107.         jz      @F
  108.         mov     eax, [eax+FUTEX.handle]
  109. @@:
  110.         mov     [esp+SYSCALL_STACK._eax], eax
  111.         ret
  112.  
  113.  
  114. align 4
  115. ;ecx futex handle
  116. ;esi current process
  117. ;edi futex object
  118. .futex_destroy:
  119.         mov     ecx, edi
  120.         call    destroy_futex
  121.         mov     [esp+SYSCALL_STACK._eax], eax
  122.         ret
  123.  
  124. align 4
  125. ;ecx futex handle
  126. ;esi current process
  127. ;edi futex object
  128. ;edx control value
  129. .futex_wait:
  130.         mov     ecx, [edi+FUTEX.pointer]
  131.         mov     eax, edx
  132.         lock cmpxchg [ecx], edx         ;wait until old_value == new_value
  133.         jz .wait_slow
  134.  
  135.         mov     [esp+SYSCALL_STACK._eax], 0
  136.         ret
  137.  
  138. .wait_slow:
  139.         pushfd
  140.         cli
  141.  
  142.         sub     esp, sizeof.MUTEX_WAITER
  143.         mov     ebx, [TASK_BASE]
  144.         mov     [ebx+TASKDATA.state], 1
  145.         mov     [esp+MUTEX_WAITER.task], ebx
  146.         lea     esi, [edi+FUTEX.wait_list]
  147.  
  148.         list_add_tail esp, esi      ;esp= new waiter, esi= list head
  149.  
  150. .again:
  151.         call    change_task
  152.  
  153.         lock cmpxchg [ecx], edx
  154.         jz .again
  155.  
  156.         list_del esp
  157.         add     esp, sizeof.MUTEX_WAITER
  158.  
  159.         popfd
  160.         mov     [esp+SYSCALL_STACK._eax], 0
  161.         ret
  162.  
  163. align 4
  164. ;ecx futex handle
  165. ;esi current process
  166. ;edi futex object
  167. ;edx threads count
  168. .futex_wake:
  169.  
  170.         xor     ecx, ecx
  171.  
  172.         pushfd
  173.         cli
  174.  
  175.         lea     ebx, [edi+FUTEX.wait_list]
  176.         mov     esi, [ebx+LHEAD.next]
  177. @@:
  178.         cmp     esi, ebx
  179.         je      @F
  180.  
  181.         mov     eax, [esi+MUTEX_WAITER.task]
  182.         mov     [eax+TASKDATA.state], 0
  183.  
  184.         mov     esi, [esi+MUTEX_WAITER.list.next]
  185.         inc     ecx
  186.         cmp     ecx, edx
  187.         jb      @B
  188. @@:
  189.         popfd
  190.         mov     [esp+SYSCALL_STACK._eax], ecx
  191.         ret
  192.  
  193. RWSEM_WAITING_FOR_WRITE equ 0
  194. RWSEM_WAITING_FOR_READ  equ 1
  195.  
  196. ;void  __fastcall mutex_init(struct mutex *lock)
  197.  
  198. align 4
  199. mutex_init:
  200.         mov     [ecx+MUTEX.wait_list.next], ecx
  201.         mov     [ecx+MUTEX.wait_list.prev], ecx
  202.         mov     [ecx+MUTEX.count], 1
  203.         ret
  204.  
  205. ;void  __fastcall mutex_lock(struct mutex *lock)
  206.  
  207. align 4
  208. mutex_lock:
  209.  
  210.         dec     [ecx+MUTEX.count]
  211.         jns     .done
  212.  
  213.         pushfd
  214.         cli
  215.  
  216.         sub     esp, sizeof.MUTEX_WAITER
  217.  
  218.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  219.  
  220.         mov     edx, [TASK_BASE]
  221.         mov     [esp+MUTEX_WAITER.task], edx
  222.  
  223. .forever:
  224.  
  225.         mov     eax, -1
  226.         xchg    eax, [ecx+MUTEX.count]
  227.         dec     eax
  228.         jz      @F
  229.  
  230.         mov     [edx+TASKDATA.state], 1
  231.         call    change_task
  232.         jmp     .forever
  233. @@:
  234.         mov     eax, ecx
  235.         list_del esp
  236.  
  237.         cmp     [eax+MUTEX.wait_list.next], eax
  238.         jne     @F
  239.  
  240.         mov     [eax+MUTEX.count], 0
  241. @@:
  242.         add     esp, sizeof.MUTEX_WAITER
  243.  
  244.         popfd
  245. .done:
  246.         ret
  247.  
  248. ;void  __fastcall mutex_unlock(struct mutex *lock)
  249.  
  250. align 4
  251. mutex_unlock:
  252.  
  253.         pushfd
  254.         cli
  255.  
  256.         mov     eax, [ecx+MUTEX.wait_list.next]
  257.         cmp     eax, ecx
  258.         mov     [ecx+MUTEX.count], 1
  259.         je      @F
  260.  
  261.         mov     eax, [eax+MUTEX_WAITER.task]
  262.         mov     [eax+TASKDATA.state], 0
  263. @@:
  264.         popfd
  265.         ret
  266.  
  267.  
  268. ;void __fastcall init_rwsem(struct rw_semaphore *sem)
  269.  
  270. align 4
  271. init_rwsem:
  272.         mov     [ecx+RWSEM.wait_list.next], ecx
  273.         mov     [ecx+RWSEM.wait_list.prev], ecx
  274.         mov     [ecx+RWSEM.count], 0
  275.         ret
  276.  
  277. ;void __fastcall down_read(struct rw_semaphore *sem)
  278.  
  279. align 4
  280. down_read:
  281.         pushfd
  282.         cli
  283.  
  284.         mov     eax, [ecx+RWSEM.count]
  285.         test    eax, eax
  286.         js      @F
  287.  
  288.         cmp     ecx, [ecx+RWSEM.wait_list.next]
  289.         je      .ok
  290. @@:
  291.         sub     esp, sizeof.MUTEX_WAITER
  292.  
  293.         mov     eax, [TASK_BASE]
  294.         mov     [esp+MUTEX_WAITER.task], eax
  295.         mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ
  296.         mov     [eax+TASKDATA.state], 1
  297.  
  298.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  299.  
  300.         call    change_task
  301.  
  302.         add     esp, sizeof.MUTEX_WAITER
  303.         popfd
  304.         ret
  305. .ok:
  306.         inc     eax
  307.         mov     [ecx+RWSEM.count], eax
  308.  
  309.         popfd
  310.         ret
  311.  
  312. ;void __fastcall down_write(struct rw_semaphore *sem)
  313.  
  314. align 4
  315. down_write:
  316.         pushfd
  317.         cli
  318.         sub     esp, sizeof.MUTEX_WAITER
  319.  
  320.         mov     edx, [TASK_BASE]
  321.         mov     [esp+MUTEX_WAITER.task], edx
  322.         mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE
  323.         mov     [edx+TASKDATA.state], 1
  324.  
  325.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  326.  
  327.         xor     eax, eax
  328.         not     eax
  329.  
  330. .forever:
  331.         test    eax, [ecx+RWSEM.count]
  332.         jz      @F
  333.  
  334.         mov     [edx+TASKDATA.state], 1
  335.         call    change_task
  336.         jmp     .forever
  337. @@:
  338.         mov     [ecx+RWSEM.count], eax
  339.         list_del esp
  340.  
  341.         add     esp, sizeof.MUTEX_WAITER
  342.         popfd
  343.         ret
  344.  
  345. ;void __fastcall up_read(struct rw_semaphore *sem)
  346.  
  347. align 4
  348. up_read:
  349.         pushfd
  350.         cli
  351.  
  352.         dec     [ecx+RWSEM.count]
  353.         jnz     @F
  354.  
  355.         mov     eax, [ecx+RWSEM.wait_list.next]
  356.         cmp     eax, ecx
  357.         je      @F
  358.  
  359.         mov     eax, [eax+MUTEX_WAITER.task]
  360.         mov     [eax+TASKDATA.state], 0
  361. @@:
  362.         popfd
  363.         ret
  364.  
  365. ;void __fastcall up_write(struct rw_semaphore *sem)
  366.  
  367. align 4
  368. up_write:
  369.  
  370.         pushfd
  371.         cli
  372.  
  373.         mov     eax, [ecx+RWSEM.wait_list.next]
  374.         mov     [ecx+RWSEM.count], 0
  375.  
  376.         cmp     ecx, eax
  377.         je      .done
  378.  
  379.         mov     edx, [eax+MUTEX_WAITER.type]
  380.         test    edx, edx
  381.         jnz     .wake
  382.  
  383.         mov     eax, [eax+MUTEX_WAITER.task]
  384.         mov     [eax+TASKDATA.state], 0
  385. .done:
  386.         popfd
  387.         ret
  388.  
  389. .wake:
  390.         push    ebx
  391.         push    esi
  392.         push    edi
  393.  
  394.         xor     esi, esi
  395.         mov     edi, ecx
  396.  
  397. .wake_list:
  398.  
  399.         mov     ebx, [eax+MUTEX_WAITER.list.next]
  400.         list_del eax
  401.         mov     edx, [eax+MUTEX_WAITER.task]
  402.         mov     [edx+TASKDATA.state], 0
  403.         inc     esi
  404.         cmp     edi, ebx
  405.         je      .wake_done
  406.  
  407.         mov     ecx, [ebx+MUTEX_WAITER.type]
  408.         test    ecx, ecx
  409.         jz      .wake_done
  410.  
  411.         mov     eax, ebx
  412.         jmp     .wake_list
  413.  
  414. .wake_done:
  415.         add     [edi+RWSEM.count], esi
  416.  
  417.         pop     edi
  418.         pop     esi
  419.         pop     ebx
  420.         popfd
  421.         ret
  422.  
  423.  
  424. purge RWSEM_WAITING_FOR_WRITE
  425. purge RWSEM_WAITING_FOR_READ
  426.  
  427.  
  428. if ~defined sync_inc
  429. sync_inc_fix:
  430. sync_inc fix sync_inc_fix
  431.  
  432. ;simplest mutex.
  433. macro SimpleMutex name
  434. {
  435. ;  iglobal
  436.     name dd 0
  437.     name#.type = 1
  438. ;  endg
  439. }
  440. macro WaitSimpleMutex name
  441. {
  442.   local start_wait,ok
  443. start_wait=$
  444.         cli
  445.         cmp     [name], dword 0
  446.         jz      ok
  447.         sti
  448.         call    change_task
  449.         jmp     start_wait
  450. ok=$
  451.         push    eax
  452.         mov     eax, dword [TASK_BASE+second_base_address]
  453.         mov     eax, [eax+TASKDATA.pid]
  454.         mov     [name], eax
  455.         pop     eax
  456.         sti
  457. }
  458. macro ReleaseSimpleMutex name
  459. {
  460.         mov     [name], dword 0
  461. }
  462. macro TryWaitSimpleMutex name  ;result in eax and in flags
  463. {
  464.   local ok,try_end
  465.         cmp     [name], dword 0
  466.         jz      ok
  467.         xor     eax, eax
  468.         jmp     try_end
  469. ok=$
  470.         xor     eax, eax
  471.         inc     eax
  472. try_end=$
  473. }
  474. macro SimpleCriticalSection name
  475. {
  476. ;  iglobal
  477.     name  dd 0
  478.           dd 0
  479.     name#.type=2
  480. ;  endg
  481. }
  482. macro WaitSimpleCriticalSection name
  483. {
  484.   local start_wait,first_wait,inc_counter,end_wait
  485.         push    eax
  486.         mov     eax, [TASK_BASE+second_base_address]
  487.         mov     eax, [eax+TASKDATA.pid]
  488. start_wait=$
  489.         cli
  490.         cmp     [name], dword 0
  491.         jz      first_wait
  492.         cmp     [name], eax
  493.         jz      inc_counter
  494.         sti
  495.         call    change_task
  496.         jmp     start_wait
  497. first_wait=$
  498.         mov     [name], eax
  499.         mov     [name+4], dword 1
  500.         jmp     end_wait
  501. inc_counter=$
  502.         inc     dword [name+4]
  503. end_wait=$
  504.         sti
  505.         pop     eax
  506. }
  507. macro ReleaseSimpleCriticalSection name
  508. {
  509.   local release_end
  510.         dec     dword [name+4]
  511.         jnz     release_end
  512.         mov     [name], dword 0
  513. release_end=$
  514. }
  515. macro TryWaitSimpleCriticalSection name ;result in eax and in flags
  516. {
  517.   local ok,try_end
  518.         mov     eax, [CURRENT_TASK+second_base_address]
  519.         mov     eax, [eax+TASKDATA.pid]
  520.         cmp     [name], eax
  521.         jz      ok
  522.         cmp     [name], 0
  523.         jz      ok
  524.         xor     eax, eax
  525.         jmp     try_end
  526. ok=$
  527.         xor     eax, eax
  528.         inc     eax
  529. try_end=$
  530. }
  531. _cli equ call MEM_HeapLock
  532. _sti equ call MEM_HeapUnLock
  533. end if
  534.  
  535.