Subversion Repositories Kolibri OS

Rev

Rev 6928 | Rev 7136 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6926 serge 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: 6917 $
9
 
6929 serge 10
F_READ              equ 0x0001  ; file opened for reading
11
F_WRITE             equ 0x0002  ; file opened for writing
12
 
6926 serge 13
O_CLOEXEC           equ 0x40000
14
PIPE_BUFFER_SIZE    equ 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
 
6928 serge 46
        push    edx
6926 serge 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
6929 serge 102
        mov     [eax+FILED.mode], F_READ
6926 serge 103
        mov     [eax+FILED.file], ebp
104
 
105
        mov     [edx+FILED.magic], 'PIPE'
106
        mov     [edx+FILED.destroy], 0
6929 serge 107
        mov     [edx+FILED.mode], F_WRITE
6926 serge 108
        mov     [edx+FILED.file], ebp
109
 
6928 serge 110
        mov     eax, [eax+FILED.handle]
111
        mov     edx, [edx+FILED.handle]
112
 
6926 serge 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:
6929 serge 133
        mov     eax, ebp
6926 serge 134
        pop     ebp
6929 serge 135
        mov     [esp+SYSCALL_STACK._eax], eax
6926 serge 136
        ret
137
 
138
purge .pipeflags
139
purge .filefd
140
purge .fdread
141
purge .fdwrite
142
purge .intpipe
143
 
144
 
6929 serge 145
; edx dst_buf
146
; esi read count
6926 serge 147
; ebp pipe
148
 
149
align 4
150
pipe_read:
6929 serge 151
 
6926 serge 152
        mov     edi, edx
6927 serge 153
 
6926 serge 154
        lea     ecx, [ebp+PIPE.pipe_lock]
155
        call    mutex_lock
6929 serge 156
.again:
6926 serge 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
6927 serge 175
        rep movsb
6926 serge 176
        and     esi, 0xFFF
6927 serge 177
        mov     [ebp+PIPE.read_end], esi
6926 serge 178
 
6929 serge 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
@@:
6926 serge 196
        lea     ecx, [ebp+PIPE.pipe_lock]
197
        call    mutex_unlock
198
        ret
199
 
200
.wait:
6929 serge 201
        pushfd
202
        cli
203
 
6926 serge 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
 
6929 serge 209
        list_add_tail esp, edx                  ;esp= new waiter, edx= list head
6926 serge 210
 
211
        lea     ecx, [ebp+PIPE.pipe_lock]
212
        call    mutex_unlock
213
 
214
        mov     [ebx+TASKDATA.state], 1
215
        call    change_task
216
 
6929 serge 217
        lea     ecx, [ebp+PIPE.pipe_lock]
218
        call    mutex_lock
219
 
6927 serge 220
        list_del esp
221
        add     esp, sizeof.MUTEX_WAITER
6929 serge 222
        popfd
6927 serge 223
        jmp     .again
224
 
225
.eof:
226
        mov     [esp+SYSCALL_STACK._eax], eax
6926 serge 227
        lea     ecx, [ebp+PIPE.pipe_lock]
6927 serge 228
        call    mutex_unlock
229
        ret
230
 
6929 serge 231
; edx src_buf
232
; esi write count
6927 serge 233
; ebp pipe
234
 
235
align 4
236
pipe_write:
237
 
6929 serge 238
.written    equ esp
239
 
240
        push    0                               ;written
241
        mov     ebx, esi                        ;ebx = write count
242
        mov     esi, edx                        ;esi = src
243
 
6927 serge 244
        lea     ecx, [ebp+PIPE.pipe_lock]
6926 serge 245
        call    mutex_lock
6929 serge 246
.again:
6927 serge 247
        xor     eax, eax
248
        cmp     eax, [ebp+PIPE.readers]
249
        je      .epipe
250
 
6929 serge 251
        mov     ecx, 4096
252
        sub     ecx, [ebp+PIPE.count]
253
        jz      .wait                           ;wait if buffer full
6926 serge 254
 
6927 serge 255
.check_count:
6929 serge 256
        cmp     ecx, ebx
6927 serge 257
        jb      .write
6929 serge 258
        mov     ecx, ebx
6927 serge 259
.write:
6928 serge 260
        mov     edi, [ebp+PIPE.buffer]
261
        add     edi, [ebp+PIPE.write_end]
6929 serge 262
        add     [.written], ecx
263
        sub     ebx, ecx
6927 serge 264
        add     [ebp+PIPE.count], ecx
6929 serge 265
 
6927 serge 266
        cld
267
        rep movsb
6928 serge 268
        and     edi, 0xFFF
269
        mov     [ebp+PIPE.write_end], edi
6927 serge 270
 
6929 serge 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
 
6927 serge 293
        lea     ecx, [ebp+PIPE.pipe_lock]
294
        call    mutex_unlock
6929 serge 295
 
296
        test    ebx, ebx
297
        jnz     .again
298
 
299
        pop     eax                             ; written
300
        mov     [esp+SYSCALL_STACK._eax], eax
6927 serge 301
        ret
302
 
303
.wait:
6929 serge 304
        pushfd
305
        cli
306
 
6927 serge 307
        sub     esp, sizeof.MUTEX_WAITER
6929 serge 308
        mov     ecx, [TASK_BASE]
309
        mov     [esp+MUTEX_WAITER.task], ecx
6927 serge 310
        lea     edx, [ebp+PIPE.wlist]
311
 
6929 serge 312
        list_add_tail esp, edx                  ;esp= new waiter, edx= list head
6927 serge 313
 
314
        lea     ecx, [ebp+PIPE.pipe_lock]
315
        call    mutex_unlock
316
 
6929 serge 317
        mov     [ecx+TASKDATA.state], 1
6927 serge 318
        call    change_task
319
 
6929 serge 320
        lea     ecx, [ebp+PIPE.pipe_lock]
321
        call    mutex_lock
322
 
6926 serge 323
        list_del esp
324
        add     esp, sizeof.MUTEX_WAITER
6929 serge 325
        popfd
6927 serge 326
        jmp     .again
6926 serge 327
 
6927 serge 328
.epipe:
6926 serge 329
        lea     ecx, [ebp+PIPE.pipe_lock]
330
        call    mutex_unlock
6929 serge 331
 
332
        add     esp, 4
333
        mov     [esp+SYSCALL_STACK._eax], -EPIPE
6926 serge 334
        ret
335
 
336
align 4
337
pipe_close:
338
        mov     [esp+SYSCALL_STACK._eax], -EBADF
339
        ret