Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2017. All rights reserved. ;;
  4. ;;  Distributed under terms of the GNU General Public License.  ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 8130 $
  9.  
  10. F_READ              = 0x0001  ; file opened for reading
  11. F_WRITE             = 0x0002  ; file opened for writing
  12.  
  13. O_CLOEXEC           = 0x40000
  14. PIPE_BUFFER_SIZE    = 4096
  15.  
  16.  
  17. iglobal
  18. align 4
  19. pipe_file_ops:
  20.         dd pipe_close       ;0
  21.         dd pipe_read        ;1
  22.         dd pipe_write       ;2
  23. endg
  24.  
  25. ;int pipe2(int pipefd[2], int flags);
  26. ;ecx pipefd
  27. ;edx flags
  28.  
  29. align 4
  30. sys_pipe2:
  31. .pipeflags equ  esp+16
  32. .pipefd    equ  esp+12
  33. .fdread    equ  esp+8
  34. .fdwrite   equ  esp+4
  35. .intpipe   equ  esp
  36.  
  37.         push    ebp
  38.         test    ecx, ecx
  39.         mov     ebp, -EFAULT
  40.         js      .fail
  41.  
  42.         test    edx, not O_CLOEXEC
  43.         mov     ebp, -EINVAL
  44.         jnz     .fail
  45.  
  46.         push    edx
  47.         push    ecx
  48.         sub     esp, (5-2)*4
  49.  
  50.         mov     ecx, sizeof.FILED
  51.         call    create_object
  52.         mov     [.fdread], eax
  53.         test    eax, eax
  54.         mov     ebp, -EMFILE
  55.         jz      .err_0
  56.  
  57.         mov     ecx, sizeof.FILED
  58.         call    create_object
  59.         mov     [.fdwrite], eax
  60.         test    eax, eax
  61.         jz      .err_1
  62.  
  63.         mov     eax, sizeof.PIPE
  64.         call    malloc
  65.         test    eax, eax
  66.         mov     ebp, -ENFILE
  67.         jz      .err_2
  68.  
  69.         mov     ebp, eax
  70.  
  71.         stdcall create_ring_buffer, PIPE_BUFFER_SIZE, PG_SWR
  72.         test    eax, eax
  73.         jz      .err_3
  74.  
  75.         mov     [ebp+PIPE.pipe_ops], pipe_file_ops
  76.         mov     [ebp+PIPE.buffer], eax
  77.  
  78.         xor     eax, eax
  79.         mov     [ebp+PIPE.count], eax
  80.         mov     [ebp+PIPE.read_end], eax
  81.         mov     [ebp+PIPE.write_end], eax
  82.  
  83.         inc     eax
  84.         mov     [ebp+PIPE.readers], eax
  85.         mov     [ebp+PIPE.writers], eax
  86.  
  87.         lea     ecx, [ebp+PIPE.pipe_lock]
  88.         call    mutex_init
  89.  
  90.         lea     ecx, [ebp+PIPE.rlist]
  91.         list_init ecx
  92.  
  93.         lea     ecx, [ebp+PIPE.wlist]
  94.         list_init ecx
  95.  
  96.         mov     eax, [.fdread]
  97.         mov     edx, [.fdwrite]
  98.         mov     ecx, [.pipefd]
  99.  
  100.         mov     [eax+FILED.magic], 'PIPE'
  101.         mov     [eax+FILED.destroy], 0
  102.         mov     [eax+FILED.mode], F_READ
  103.         mov     [eax+FILED.file], ebp
  104.  
  105.         mov     [edx+FILED.magic], 'PIPE'
  106.         mov     [edx+FILED.destroy], 0
  107.         mov     [edx+FILED.mode], F_WRITE
  108.         mov     [edx+FILED.file], ebp
  109.  
  110.         mov     eax, [eax+FILED.handle]
  111.         mov     edx, [edx+FILED.handle]
  112.  
  113.         mov     [ecx], eax
  114.         mov     [ecx+4], edx
  115.         add     esp, 5*4
  116.         pop     ebp
  117.         xor     eax, eax
  118.         mov     [esp+SYSCALL_STACK._eax], eax
  119.         ret
  120. .err_3:
  121.         mov     eax, ebp
  122.         call    free
  123.         mov     ebp, -ENFILE
  124. .err_2:
  125.         mov     ecx, [.fdwrite]
  126.         call    destroy_object
  127. .err_1:
  128.         mov     ecx, [.fdread]
  129.         call    destroy_object
  130. .err_0:
  131.         add     esp, 5*4
  132. .fail:
  133.         mov     eax, ebp
  134.         pop     ebp
  135.         mov     [esp+SYSCALL_STACK._eax], eax
  136.         ret
  137.  
  138. purge .pipeflags
  139. purge .filefd
  140. purge .fdread
  141. purge .fdwrite
  142. purge .intpipe
  143.  
  144.  
  145. ; edx dst_buf
  146. ; esi read count
  147. ; ebp pipe
  148.  
  149. align 4
  150. pipe_read:
  151.  
  152.         mov     edi, edx
  153.  
  154.         lea     ecx, [ebp+PIPE.pipe_lock]
  155.         call    mutex_lock
  156. .again:
  157.         xor     eax, eax
  158.         cmp     eax, [ebp+PIPE.writers]
  159.         je      .eof
  160.  
  161.         mov     ecx, [ebp+PIPE.count]
  162.         test    ecx, ecx
  163.         jz      .wait
  164.  
  165. .check_count:
  166.         cmp     ecx, esi
  167.         jb      .read
  168.         mov     ecx, esi
  169. .read:
  170.         mov     esi, [ebp+PIPE.buffer]
  171.         add     esi, [ebp+PIPE.read_end]
  172.         mov     [esp+SYSCALL_STACK._eax], ecx
  173.         sub     [ebp+PIPE.count], ecx
  174.         cld
  175.         rep movsb
  176.         and     esi, 0xFFF
  177.         mov     [ebp+PIPE.read_end], esi
  178.  
  179.         lea     ecx, [ebp+PIPE.wlist]
  180.         cmp     ecx, [ebp+PIPE.wlist.next]
  181.         je      @F
  182.  
  183.         mov     ecx, [ecx+MUTEX_WAITER.task]
  184.         mov     [ecx+TASKDATA.state], 0         ;activate writer task
  185. @@:
  186.         cmp     [ebp+PIPE.count], 0
  187.         je      @F
  188.  
  189.         lea     eax, [ebp+PIPE.rlist]
  190.         cmp     eax, [ebp+PIPE.rlist.next]
  191.         je      @F
  192.  
  193.         mov     eax, [eax+MUTEX_WAITER.task]
  194.         mov     [eax+TASKDATA.state], 0         ;activate reader task
  195. @@:
  196.         lea     ecx, [ebp+PIPE.pipe_lock]
  197.         call    mutex_unlock
  198.         ret
  199.  
  200. .wait:
  201.         pushfd
  202.         cli
  203.  
  204.         sub     esp, sizeof.MUTEX_WAITER
  205.         mov     ebx, [TASK_BASE]
  206.         mov     [esp+MUTEX_WAITER.task], ebx
  207.         lea     edx, [ebp+PIPE.rlist]
  208.  
  209.         list_add_tail esp, edx                  ;esp= new waiter, edx= list head
  210.  
  211.         lea     ecx, [ebp+PIPE.pipe_lock]
  212.         call    mutex_unlock
  213.  
  214.         mov     [ebx+TASKDATA.state], 1
  215.         call    change_task
  216.  
  217.         lea     ecx, [ebp+PIPE.pipe_lock]
  218.         call    mutex_lock
  219.  
  220.         list_del esp
  221.         add     esp, sizeof.MUTEX_WAITER
  222.         popfd
  223.         jmp     .again
  224.  
  225. .eof:
  226.         mov     [esp+SYSCALL_STACK._eax], eax
  227.         lea     ecx, [ebp+PIPE.pipe_lock]
  228.         call    mutex_unlock
  229.         ret
  230.  
  231. ; edx src_buf
  232. ; esi write count
  233. ; ebp pipe
  234.  
  235. align 4
  236. pipe_write:
  237.  
  238. .written    equ esp
  239.  
  240.         push    0                               ;written
  241.         mov     ebx, esi                        ;ebx = write count
  242.         mov     esi, edx                        ;esi = src
  243.  
  244.         lea     ecx, [ebp+PIPE.pipe_lock]
  245.         call    mutex_lock
  246. .again:
  247.         xor     eax, eax
  248.         cmp     eax, [ebp+PIPE.readers]
  249.         je      .epipe
  250.  
  251.         mov     ecx, 4096
  252.         sub     ecx, [ebp+PIPE.count]
  253.         jz      .wait                           ;wait if buffer full
  254.  
  255. .check_count:
  256.         cmp     ecx, ebx
  257.         jb      .write
  258.         mov     ecx, ebx
  259. .write:
  260.         mov     edi, [ebp+PIPE.buffer]
  261.         add     edi, [ebp+PIPE.write_end]
  262.         add     [.written], ecx
  263.         sub     ebx, ecx
  264.         add     [ebp+PIPE.count], ecx
  265.  
  266.         cld
  267.         rep movsb
  268.         and     edi, 0xFFF
  269.         mov     [ebp+PIPE.write_end], edi
  270.  
  271.         pushfd
  272.         cli
  273.  
  274.         lea     eax, [ebp+PIPE.rlist]
  275.         cmp     eax, [ebp+PIPE.rlist.next]
  276.         je      @F
  277.  
  278.         mov     eax, [eax+MUTEX_WAITER.task]
  279.         mov     [eax+TASKDATA.state], 0         ;activate reader task
  280. @@:
  281.         cmp     [ebp+PIPE.count], 4096
  282.         je      @F
  283.  
  284.         lea     ecx, [ebp+PIPE.wlist]
  285.         cmp     ecx, [ebp+PIPE.wlist.next]
  286.         je      @F
  287.  
  288.         mov     ecx, [eax+MUTEX_WAITER.task]
  289.         mov     [ecx+TASKDATA.state], 0         ;activate writer task
  290. @@:
  291.         popfd
  292.  
  293.         lea     ecx, [ebp+PIPE.pipe_lock]
  294.         call    mutex_unlock
  295.  
  296.         test    ebx, ebx
  297.         jnz     .again
  298.  
  299.         pop     eax                             ; written
  300.         mov     [esp+SYSCALL_STACK._eax], eax
  301.         ret
  302.  
  303. .wait:
  304.         pushfd
  305.         cli
  306.  
  307.         sub     esp, sizeof.MUTEX_WAITER
  308.         mov     ecx, [TASK_BASE]
  309.         mov     [esp+MUTEX_WAITER.task], ecx
  310.         lea     edx, [ebp+PIPE.wlist]
  311.  
  312.         list_add_tail esp, edx                  ;esp= new waiter, edx= list head
  313.  
  314.         lea     ecx, [ebp+PIPE.pipe_lock]
  315.         call    mutex_unlock
  316.  
  317.         mov     [ecx+TASKDATA.state], 1
  318.         call    change_task
  319.  
  320.         lea     ecx, [ebp+PIPE.pipe_lock]
  321.         call    mutex_lock
  322.  
  323.         list_del esp
  324.         add     esp, sizeof.MUTEX_WAITER
  325.         popfd
  326.         jmp     .again
  327.  
  328. .epipe:
  329.         lea     ecx, [ebp+PIPE.pipe_lock]
  330.         call    mutex_unlock
  331.  
  332.         add     esp, 4
  333.         mov     [esp+SYSCALL_STACK._eax], -EPIPE
  334.         ret
  335.  
  336. align 4
  337. pipe_close:
  338.         mov     [esp+SYSCALL_STACK._eax], -EBADF
  339.         ret
  340.