Subversion Repositories Kolibri OS

Rev

Rev 6089 | Rev 8874 | 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: 6926 $
  11.  
  12.  
  13.  
  14. RWSEM_WAITING_FOR_WRITE equ 0
  15. RWSEM_WAITING_FOR_READ  equ 1
  16.  
  17. ;void  __fastcall mutex_init(struct mutex *lock)
  18.  
  19. align 4
  20. mutex_init:
  21.         mov     [ecx+MUTEX.wait_list.next], ecx
  22.         mov     [ecx+MUTEX.wait_list.prev], ecx
  23.         mov     [ecx+MUTEX.count], 1
  24.         ret
  25.  
  26. ;void  __fastcall mutex_lock(struct mutex *lock)
  27.  
  28. align 4
  29. mutex_lock:
  30.  
  31.         dec     [ecx+MUTEX.count]
  32.         jns     .done
  33.  
  34.         pushfd
  35.         cli
  36.  
  37.         sub     esp, sizeof.MUTEX_WAITER
  38.  
  39.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  40.  
  41.         mov     edx, [TASK_BASE]
  42.         mov     [esp+MUTEX_WAITER.task], edx
  43.  
  44. .forever:
  45.  
  46.         mov     eax, -1
  47.         xchg    eax, [ecx+MUTEX.count]
  48.         dec     eax
  49.         jz      @F
  50.  
  51.         mov     [edx+TASKDATA.state], 1
  52.         call    change_task
  53.         jmp     .forever
  54. @@:
  55.         mov     eax, ecx
  56.         list_del esp
  57.  
  58.         cmp     [eax+MUTEX.wait_list.next], eax
  59.         jne     @F
  60.  
  61.         mov     [eax+MUTEX.count], 0
  62. @@:
  63.         add     esp, sizeof.MUTEX_WAITER
  64.  
  65.         popfd
  66. .done:
  67.         ret
  68.  
  69. ;void  __fastcall mutex_unlock(struct mutex *lock)
  70.  
  71. align 4
  72. mutex_unlock:
  73.  
  74.         pushfd
  75.         cli
  76.  
  77.         mov     eax, [ecx+MUTEX.wait_list.next]
  78.         cmp     eax, ecx
  79.         mov     [ecx+MUTEX.count], 1
  80.         je      @F
  81.  
  82.         mov     eax, [eax+MUTEX_WAITER.task]
  83.         mov     [eax+TASKDATA.state], 0
  84. @@:
  85.         popfd
  86.         ret
  87.  
  88.  
  89. ;void __fastcall init_rwsem(struct rw_semaphore *sem)
  90.  
  91. align 4
  92. init_rwsem:
  93.         mov     [ecx+RWSEM.wait_list.next], ecx
  94.         mov     [ecx+RWSEM.wait_list.prev], ecx
  95.         mov     [ecx+RWSEM.count], 0
  96.         ret
  97.  
  98. ;void __fastcall down_read(struct rw_semaphore *sem)
  99.  
  100. align 4
  101. down_read:
  102.         pushfd
  103.         cli
  104.  
  105.         mov     eax, [ecx+RWSEM.count]
  106.         test    eax, eax
  107.         js      @F
  108.  
  109.         cmp     ecx, [ecx+RWSEM.wait_list.next]
  110.         je      .ok
  111. @@:
  112.         sub     esp, sizeof.MUTEX_WAITER
  113.  
  114.         mov     eax, [TASK_BASE]
  115.         mov     [esp+MUTEX_WAITER.task], eax
  116.         mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_READ
  117.         mov     [eax+TASKDATA.state], 1
  118.  
  119.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  120.  
  121.         call    change_task
  122.  
  123.         add     esp, sizeof.MUTEX_WAITER
  124.         popfd
  125.         ret
  126. .ok:
  127.         inc     eax
  128.         mov     [ecx+RWSEM.count], eax
  129.  
  130.         popfd
  131.         ret
  132.  
  133. ;void __fastcall down_write(struct rw_semaphore *sem)
  134.  
  135. align 4
  136. down_write:
  137.         pushfd
  138.         cli
  139.         sub     esp, sizeof.MUTEX_WAITER
  140.  
  141.         mov     edx, [TASK_BASE]
  142.         mov     [esp+MUTEX_WAITER.task], edx
  143.         mov     [esp+MUTEX_WAITER.type], RWSEM_WAITING_FOR_WRITE
  144.         mov     [edx+TASKDATA.state], 1
  145.  
  146.         list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
  147.  
  148.         xor     eax, eax
  149.         not     eax
  150.  
  151. .forever:
  152.         test    eax, [ecx+RWSEM.count]
  153.         jz      @F
  154.  
  155.         mov     [edx+TASKDATA.state], 1
  156.         call    change_task
  157.         jmp     .forever
  158. @@:
  159.         mov     [ecx+RWSEM.count], eax
  160.         list_del esp
  161.  
  162.         add     esp, sizeof.MUTEX_WAITER
  163.         popfd
  164.         ret
  165.  
  166. ;void __fastcall up_read(struct rw_semaphore *sem)
  167.  
  168. align 4
  169. up_read:
  170.         pushfd
  171.         cli
  172.  
  173.         dec     [ecx+RWSEM.count]
  174.         jnz     @F
  175.  
  176.         mov     eax, [ecx+RWSEM.wait_list.next]
  177.         cmp     eax, ecx
  178.         je      @F
  179.  
  180.         mov     eax, [eax+MUTEX_WAITER.task]
  181.         mov     [eax+TASKDATA.state], 0
  182. @@:
  183.         popfd
  184.         ret
  185.  
  186. ;void __fastcall up_write(struct rw_semaphore *sem)
  187.  
  188. align 4
  189. up_write:
  190.  
  191.         pushfd
  192.         cli
  193.  
  194.         mov     eax, [ecx+RWSEM.wait_list.next]
  195.         mov     [ecx+RWSEM.count], 0
  196.  
  197.         cmp     ecx, eax
  198.         je      .done
  199.  
  200.         mov     edx, [eax+MUTEX_WAITER.type]
  201.         test    edx, edx
  202.         jnz     .wake
  203.  
  204.         mov     eax, [eax+MUTEX_WAITER.task]
  205.         mov     [eax+TASKDATA.state], 0
  206. .done:
  207.         popfd
  208.         ret
  209.  
  210. .wake:
  211.         push    ebx
  212.         push    esi
  213.         push    edi
  214.  
  215.         xor     esi, esi
  216.         mov     edi, ecx
  217.  
  218. .wake_list:
  219.  
  220.         mov     ebx, [eax+MUTEX_WAITER.list.next]
  221.         list_del eax
  222.         mov     edx, [eax+MUTEX_WAITER.task]
  223.         mov     [edx+TASKDATA.state], 0
  224.         inc     esi
  225.         cmp     edi, ebx
  226.         je      .wake_done
  227.  
  228.         mov     ecx, [ebx+MUTEX_WAITER.type]
  229.         test    ecx, ecx
  230.         jz      .wake_done
  231.  
  232.         mov     eax, ebx
  233.         jmp     .wake_list
  234.  
  235. .wake_done:
  236.         add     [edi+RWSEM.count], esi
  237.  
  238.         pop     edi
  239.         pop     esi
  240.         pop     ebx
  241.         popfd
  242.         ret
  243.  
  244.  
  245. purge RWSEM_WAITING_FOR_WRITE
  246. purge RWSEM_WAITING_FOR_READ
  247.  
  248.  
  249. if ~defined sync_inc
  250. sync_inc_fix:
  251. sync_inc fix sync_inc_fix
  252.  
  253. ;simplest mutex.
  254. macro SimpleMutex name
  255. {
  256. ;  iglobal
  257.     name dd 0
  258.     name#.type = 1
  259. ;  endg
  260. }
  261. macro WaitSimpleMutex name
  262. {
  263.   local start_wait,ok
  264. start_wait=$
  265.         cli
  266.         cmp     [name], dword 0
  267.         jz      ok
  268.         sti
  269.         call    change_task
  270.         jmp     start_wait
  271. ok=$
  272.         push    eax
  273.         mov     eax, dword [TASK_BASE+second_base_address]
  274.         mov     eax, [eax+TASKDATA.pid]
  275.         mov     [name], eax
  276.         pop     eax
  277.         sti
  278. }
  279. macro ReleaseSimpleMutex name
  280. {
  281.         mov     [name], dword 0
  282. }
  283. macro TryWaitSimpleMutex name  ;result in eax and in flags
  284. {
  285.   local ok,try_end
  286.         cmp     [name], dword 0
  287.         jz      ok
  288.         xor     eax, eax
  289.         jmp     try_end
  290. ok=$
  291.         xor     eax, eax
  292.         inc     eax
  293. try_end=$
  294. }
  295. macro SimpleCriticalSection name
  296. {
  297. ;  iglobal
  298.     name  dd 0
  299.           dd 0
  300.     name#.type=2
  301. ;  endg
  302. }
  303. macro WaitSimpleCriticalSection name
  304. {
  305.   local start_wait,first_wait,inc_counter,end_wait
  306.         push    eax
  307.         mov     eax, [TASK_BASE+second_base_address]
  308.         mov     eax, [eax+TASKDATA.pid]
  309. start_wait=$
  310.         cli
  311.         cmp     [name], dword 0
  312.         jz      first_wait
  313.         cmp     [name], eax
  314.         jz      inc_counter
  315.         sti
  316.         call    change_task
  317.         jmp     start_wait
  318. first_wait=$
  319.         mov     [name], eax
  320.         mov     [name+4], dword 1
  321.         jmp     end_wait
  322. inc_counter=$
  323.         inc     dword [name+4]
  324. end_wait=$
  325.         sti
  326.         pop     eax
  327. }
  328. macro ReleaseSimpleCriticalSection name
  329. {
  330.   local release_end
  331.         dec     dword [name+4]
  332.         jnz     release_end
  333.         mov     [name], dword 0
  334. release_end=$
  335. }
  336. macro TryWaitSimpleCriticalSection name ;result in eax and in flags
  337. {
  338.   local ok,try_end
  339.         mov     eax, [CURRENT_TASK+second_base_address]
  340.         mov     eax, [eax+TASKDATA.pid]
  341.         cmp     [name], eax
  342.         jz      ok
  343.         cmp     [name], 0
  344.         jz      ok
  345.         xor     eax, eax
  346.         jmp     try_end
  347. ok=$
  348.         xor     eax, eax
  349.         inc     eax
  350. try_end=$
  351. }
  352. _cli equ call MEM_HeapLock
  353. _sti equ call MEM_HeapUnLock
  354. end if
  355.  
  356.