1 /****************************************************************************
2 * drivers/pipes/pipe_common.c
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership. The
7 * ASF licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * under the License.
18 *
19 ****************************************************************************/
20
21 /****************************************************************************
22 * Included Files
23 ****************************************************************************/
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/ioctl.h>
28 #include <stdint.h>
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sched.h>
33 #include <semaphore.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <poll.h>
37 #include "linux/wait.h"
38 #include <assert.h>
39
40 #ifdef CONFIG_DEBUG_FEATURES
41 # include <nuttx/arch.h>
42 #endif
43 #include <semaphore.h>
44 #include <fs/driver.h>
45 #include "pipe_common.h"
46 #include "los_printf.h"
47 #include "user_copy.h"
48 #ifdef LOSCFG_KERNEL_PIPE
49
50 /****************************************************************************
51 * Pre-processor Definitions
52 ****************************************************************************/
53
54 /* CONFIG_DEV_PIPEDUMP will dump the contents of each transfer into and out
55 * of the pipe.
56 */
57
58 #ifdef CONFIG_DEV_PIPEDUMP
59 # define pipe_dumpbuffer(m,a,n) lib_dumpbuffer(m,a,n)
60 #else
61 # define pipe_dumpbuffer(m,a,n)
62 #endif
63
64 /****************************************************************************
65 * Private Function Prototypes
66 ****************************************************************************/
67
68 static void pipecommon_semtake(sem_t *sem);
69
70 /****************************************************************************
71 * Private Functions
72 ****************************************************************************/
73
74 /****************************************************************************
75 * Name: pipecommon_semtake
76 ****************************************************************************/
77
pipecommon_semtake(sem_t * sem)78 static void pipecommon_semtake(sem_t *sem)
79 {
80 int ret;
81
82 do
83 {
84 /* Take the semaphore (perhaps waiting) */
85
86 ret = sem_wait(sem);
87
88 }
89 while (ret == -EINTR);
90 }
91
92 /****************************************************************************
93 * Name: pipecommon_pollnotify
94 ****************************************************************************/
95
pipecommon_pollnotify(struct pipe_dev_s * dev,pollevent_t eventset)96 static void pipecommon_pollnotify(struct pipe_dev_s *dev,
97 pollevent_t eventset)
98 {
99 if (eventset & POLLERR)
100 {
101 eventset &= ~(POLLOUT | POLLIN);
102 }
103
104 notify_poll_with_key(&dev->wq, eventset);
105 }
106
107 /****************************************************************************
108 * Public Functions
109 ****************************************************************************/
110
111 /****************************************************************************
112 * Name: pipecommon_allocdev
113 ****************************************************************************/
114
pipecommon_allocdev(size_t bufsize,const char * name)115 struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
116 {
117 struct pipe_dev_s *dev = NULL;
118 int ret;
119
120 if (bufsize > CONFIG_DEV_PIPE_MAXSIZE)
121 {
122 return NULL;
123 }
124
125 /* Allocate a private structure to manage the pipe */
126
127 dev = (struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s));
128 if (dev)
129 {
130 /* Initialize the private structure */
131
132 (void)memset_s(dev, sizeof(struct pipe_dev_s), 0, sizeof(struct pipe_dev_s));
133 ret = strcpy_s(dev->name, sizeof(dev->name), name);
134 if (ret < 0)
135 {
136 free(dev);
137 return NULL;
138 }
139 sem_init(&dev->d_bfsem, 0, 1);
140 sem_init(&dev->d_rdsem, 0, 0);
141 sem_init(&dev->d_wrsem, 0, 0);
142 LOS_ListInit(&dev->wq.poll_queue);
143 /* The read/write wait semaphores are used for signaling and, hence,
144 * should not have priority inheritance enabled.
145 */
146
147 dev->d_bufsize = bufsize;
148 }
149
150 return dev;
151 }
152
153 /****************************************************************************
154 * Name: pipecommon_freedev
155 ****************************************************************************/
156
pipecommon_freedev(struct pipe_dev_s * dev)157 void pipecommon_freedev(struct pipe_dev_s *dev)
158 {
159 sem_destroy(&dev->d_bfsem);
160 sem_destroy(&dev->d_rdsem);
161 sem_destroy(&dev->d_wrsem);
162 free(dev);
163 }
164
165 /****************************************************************************
166 * Name: pipecommon_open
167 ****************************************************************************/
168
pipecommon_open(struct file * filep)169 int pipecommon_open(struct file *filep)
170 {
171 struct Vnode *vnode = filep->f_vnode;
172 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
173 int sval;
174 int ret;
175
176 if (dev == NULL)
177 {
178 return -EINVAL;
179 }
180
181 /* Make sure that we have exclusive access to the device structure. The
182 * sem_wait() call should fail only if we are awakened by a signal.
183 */
184
185 ret = sem_wait(&dev->d_bfsem);
186 if (ret < 0)
187 {
188 PRINT_ERR("ERROR: sem_wait failed: %d\n", ret);
189 return ret;
190 }
191
192 /* If this the first reference on the device, then allocate the buffer.
193 * In the case of policy 1, the buffer already be present when the pipe
194 * is first opened.
195 */
196
197 if (vnode->useCount == 1 && dev->d_buffer == NULL)
198 {
199 dev->d_buffer = (uint8_t *)malloc(dev->d_bufsize);
200 if (!dev->d_buffer)
201 {
202 (void)sem_post(&dev->d_bfsem);
203 return -ENOMEM;
204 }
205 }
206
207
208 /* If opened for writing, increment the count of writers on the pipe instance */
209
210 if ((filep->f_oflags & O_WRONLY) != 0)
211 {
212 dev->d_nwriters++;
213
214 /* If this this is the first writer, then the read semaphore indicates the
215 * number of readers waiting for the first writer. Wake them all up.
216 */
217
218 if (dev->d_nwriters == 1)
219 {
220 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
221 {
222 sem_post(&dev->d_rdsem);
223 }
224 }
225 }
226
227 /* If opened for reading, increment the count of reader on on the pipe instance */
228
229 if ((filep->f_oflags & O_WRONLY) == 0)
230 {
231 dev->d_nreaders++;
232 }
233
234 /* If opened for read-only, then wait for either (1) at least one writer
235 * on the pipe (policy == 0), or (2) until there is buffered data to be
236 * read (policy == 1).
237 */
238
239 (void)sem_post(&dev->d_bfsem);
240
241 if ((filep->f_oflags & O_WRONLY) == 0 && /* Read-only */
242 dev->d_nwriters < 1 && /* No writers on the pipe */
243 dev->d_wrndx == dev->d_rdndx) /* Buffer is empty */
244 {
245 /* NOTE: d_rdsem is normally used when the read logic waits for more
246 * data to be written. But until the first writer has opened the
247 * pipe, the meaning is different: it is used prevent O_RDONLY open
248 * calls from returning until there is at least one writer on the pipe.
249 * This is required both by spec and also because it prevents
250 * subsequent read() calls from returning end-of-file because there is
251 * no writer on the pipe.
252 */
253
254 ret = sem_wait(&dev->d_rdsem);
255 if (ret < 0)
256 {
257 /* The sem_wait() call should fail only if we are awakened by
258 * a signal.
259 */
260
261 PRINT_ERR("ERROR: sem_wait failed: %d\n", ret);
262
263 /* Immediately close the pipe that we just opened */
264
265 (void)pipecommon_close(filep);
266 }
267 }
268 VnodeHold();
269 vnode->useCount++;
270 VnodeDrop();
271 return ret;
272 }
273
274 /****************************************************************************
275 * Name: pipecommon_close
276 ****************************************************************************/
277
pipecommon_close(struct file * filep)278 int pipecommon_close(struct file *filep)
279 {
280 struct Vnode *vnode = filep->f_vnode;
281 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
282 int sval;
283
284 if (dev == NULL || filep->f_vnode->useCount <= 1)
285 {
286 return -EINVAL;
287 }
288
289 /* Make sure that we have exclusive access to the device structure.
290 * NOTE: close() is supposed to return EINTR if interrupted, however
291 * I've never seen anyone check that.
292 */
293
294 pipecommon_semtake(&dev->d_bfsem);
295
296 /* Decrement the number of references on the pipe. Check if there are
297 * still outstanding references to the pipe.
298 */
299
300 /* Check if the decremented vnode reference count would go to zero */
301
302 if (vnode->useCount > 1)
303 {
304 /* More references.. If opened for writing, decrement the count of
305 * writers on the pipe instance.
306 */
307
308 if ((filep->f_oflags & O_WRONLY) != 0)
309 {
310 /* If there are no longer any writers on the pipe, then notify all of the
311 * waiting readers that they must return end-of-file.
312 */
313
314 if (--dev->d_nwriters <= 0)
315 {
316 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
317 {
318 sem_post(&dev->d_rdsem);
319 }
320
321 /* Inform poll readers that other end closed. */
322
323 pipecommon_pollnotify(dev, POLLHUP);
324 }
325 }
326
327 /* If opened for reading, decrement the count of readers on the pipe
328 * instance.
329 */
330
331 if ((filep->f_oflags & O_WRONLY) == 0)
332 {
333 if (--dev->d_nreaders <= 0)
334 {
335 if (PIPE_IS_POLICY_0(dev->d_flags))
336 {
337 /* Inform poll writers that other end closed. */
338
339 pipecommon_pollnotify(dev, POLLERR);
340 }
341 }
342 }
343 }
344
345 /* What is the buffer management policy? Do we free the buffer when the
346 * last client closes the pipe policy 0, or when the buffer becomes empty.
347 * In the latter case, the buffer data will remain valid and can be
348 * obtained when the pipe is re-opened.
349 */
350
351 else if (PIPE_IS_POLICY_0(dev->d_flags) || dev->d_wrndx == dev->d_rdndx)
352 {
353 /* Policy 0 or the buffer is empty ... deallocate the buffer now. */
354
355 free(dev->d_buffer);
356 dev->d_buffer = NULL;
357
358 /* And reset all counts and indices */
359
360 dev->d_wrndx = 0;
361 dev->d_rdndx = 0;
362 dev->d_nwriters = 0;
363 dev->d_nreaders = 0;
364 }
365 VnodeHold();
366 vnode->useCount--;
367 VnodeDrop();
368 sem_post(&dev->d_bfsem);
369 return OK;
370 }
371
372 /****************************************************************************
373 * Name: pipecommon_read
374 ****************************************************************************/
375
pipecommon_read(struct file * filep,char * buffer,size_t len)376 ssize_t pipecommon_read(struct file *filep, char *buffer, size_t len)
377 {
378 struct Vnode *vnode = filep->f_vnode;
379 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
380 ssize_t nread;
381 int sval;
382 int ret;
383 volatile int num;
384
385 if (dev == NULL)
386 {
387 return -EINVAL;
388 }
389
390 if (len == 0)
391 {
392 return 0;
393 }
394
395 if (len > MAX_READ_WRITE_LEN)
396 {
397 return -EINVAL;
398 }
399
400 /* Make sure that we have exclusive access to the device structure */
401
402 ret = sem_wait(&dev->d_bfsem);
403 if (ret < 0)
404 {
405 return ret;
406 }
407
408 /* If the pipe is empty, then wait for something to be written to it */
409
410 while (dev->d_wrndx == dev->d_rdndx)
411 {
412 /* If O_NONBLOCK was set, then return EGAIN */
413
414 if (filep->f_oflags & O_NONBLOCK)
415 {
416 sem_post(&dev->d_bfsem);
417 return -EAGAIN;
418 }
419
420 /* If there are no writers on the pipe, then return end of file */
421
422 if (dev->d_nwriters <= 0)
423 {
424 sem_post(&dev->d_bfsem);
425 return 0;
426 }
427
428 /* Otherwise, wait for something to be written to the pipe */
429
430 sem_post(&dev->d_bfsem);
431 ret = sem_wait(&dev->d_rdsem);
432
433 if (ret < 0 || (ret = sem_wait(&dev->d_bfsem)) < 0)
434 {
435 return ret;
436 }
437 }
438
439 /* Then return whatever is available in the pipe (which is at least one byte) */
440
441 nread = 0;
442 for (; ; )
443 {
444 while ((size_t)nread < len && dev->d_wrndx != dev->d_rdndx)
445 {
446 ret = LOS_ArchCopyToUser(buffer, dev->d_buffer + dev->d_rdndx, sizeof(char));
447 if (ret != 0)
448 {
449 sem_post(&dev->d_bfsem);
450 return -EFAULT;
451 }
452 buffer++;
453 if (++dev->d_rdndx >= dev->d_bufsize)
454 {
455 dev->d_rdndx = 0;
456 }
457
458 nread++;
459 }
460
461 /* Is the read complete? */
462 if ((size_t)nread >= len)
463 {
464 break;
465 }
466
467 /* Notify all waiting writers that bytes have been read from the buffer */
468
469 num = 0;
470 while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval == 0)
471 {
472 sem_post(&dev->d_wrsem);
473 num++;
474 }
475
476 /* If there are no writers be awakened, then return */
477
478 if (num == 0 || num == 1)
479 {
480 pipecommon_pollnotify(dev, POLLOUT);
481 sem_post(&dev->d_bfsem);
482 return nread;
483 }
484
485 /* If there are no writers on the pipe, then return the number of read bytes */
486
487 if (dev->d_nwriters <= 0)
488 {
489 sem_post(&dev->d_wrsem);
490 pipecommon_pollnotify(dev, POLLOUT);
491 sem_post(&dev->d_bfsem);
492 return nread;
493 }
494
495 /* wait for something to be written to the pipe */
496 pipecommon_pollnotify(dev, POLLOUT);
497
498 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval != 0)
499 {
500 sem_wait(&dev->d_rdsem);
501 }
502
503 sem_post(&dev->d_bfsem);
504
505 ret = sem_wait(&dev->d_rdsem);
506 if (ret < 0)
507 {
508 return ret;
509 }
510
511 ret = sem_wait(&dev->d_bfsem);
512 if (ret < 0)
513 {
514 return ret;
515 }
516 }
517
518 /* Notify all waiting writers that bytes have been removed from the buffer */
519
520 while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval == 0)
521 {
522 sem_post(&dev->d_wrsem);
523 }
524
525 /* Notify all poll/select waiters that they can write to the FIFO */
526
527 pipecommon_pollnotify(dev, POLLOUT);
528 sem_post(&dev->d_bfsem);
529 return nread;
530 }
531
532 /****************************************************************************
533 * Name: pipecommon_write
534 ****************************************************************************/
535
pipecommon_write(struct file * filep,const char * buffer,size_t len)536 ssize_t pipecommon_write(struct file *filep, const char *buffer,
537 size_t len)
538 {
539 struct Vnode *vnode = filep->f_vnode;
540 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
541 ssize_t nwritten = 0;
542 ssize_t last;
543 int nxtwrndx;
544 int sval;
545 int ret;
546
547
548 if (dev == NULL)
549 {
550 return -EINVAL;
551 }
552
553 /* Handle zero-length writes */
554
555 if (len == 0)
556 {
557 return 0;
558 }
559
560 if (len > MAX_READ_WRITE_LEN)
561 {
562 return -EINVAL;
563 }
564
565 /* REVISIT: "If all file descriptors referring to the read end of a pipe
566 * have been closed, then a write will cause a SIGPIPE signal to be
567 * generated for the calling process. If the calling process is ignoring
568 * this signal, then write(2) fails with the error EPIPE."
569 */
570
571 if (dev->d_nreaders <= 0)
572 {
573 return -EPIPE;
574 }
575
576 /* At present, this method cannot be called from interrupt handlers. That
577 * is because it calls sem_wait (via pipecommon_semtake below) and
578 * sem_wait cannot be called from interrupt level. This actually
579 * happens fairly commonly IF [a-z]err() is called from interrupt handlers
580 * and stdout is being redirected via a pipe. In that case, the debug
581 * output will try to go out the pipe (interrupt handlers should use the
582 * _err() APIs).
583 *
584 * On the other hand, it would be very valuable to be able to feed the pipe
585 * from an interrupt handler! TODO: Consider disabling interrupts instead
586 * of taking semaphores so that pipes can be written from interrupt handlers
587 */
588
589 /* Make sure that we have exclusive access to the device structure */
590
591 ret = sem_wait(&dev->d_bfsem);
592 if (ret < 0)
593 {
594 return ret;
595 }
596
597 /* Loop until all of the bytes have been written */
598
599 last = 0;
600 for (; ; )
601 {
602 /* Calculate the write index AFTER the next byte is written */
603
604 nxtwrndx = dev->d_wrndx + 1;
605 if (nxtwrndx >= dev->d_bufsize)
606 {
607 nxtwrndx = 0;
608 }
609
610 /* Would the next write overflow the circular buffer? */
611
612 if (nxtwrndx != dev->d_rdndx)
613 {
614 /* No... copy the byte */
615
616
617 ret = LOS_ArchCopyFromUser(dev->d_buffer + dev->d_wrndx, buffer, sizeof(char));
618 if (ret != 0)
619 {
620 sem_post(&dev->d_bfsem);
621 return -EFAULT;
622 }
623 buffer++;
624 dev->d_wrndx = nxtwrndx;
625
626 /* Is the write complete? */
627
628 nwritten++;
629 if ((size_t)nwritten >= len)
630 {
631 /* Yes.. Notify all of the waiting readers that more data is available */
632 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
633 {
634 sem_post(&dev->d_rdsem);
635 }
636
637 /* Notify all poll/select waiters that they can read from the FIFO */
638
639 pipecommon_pollnotify(dev, POLLIN);
640
641 /* Return the number of bytes written */
642
643 sem_post(&dev->d_bfsem);
644 return len;
645 }
646 }
647 else
648 {
649 /* There is not enough room for the next byte. Was anything written in this pass? */
650
651 if (last < nwritten)
652 {
653 /* Yes.. Notify all of the waiting readers that more data is available */
654
655 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
656 {
657 sem_post(&dev->d_rdsem);
658 }
659
660 /* Notify all poll/select waiters that they can read from the FIFO */
661
662 pipecommon_pollnotify(dev, POLLIN);
663 }
664
665 last = nwritten;
666
667 /* If O_NONBLOCK was set, then return partial bytes written or EGAIN */
668
669 if (filep->f_oflags & O_NONBLOCK)
670 {
671 if (nwritten == 0)
672 {
673 nwritten = -EAGAIN;
674 }
675
676 sem_post(&dev->d_bfsem);
677 return nwritten;
678 }
679
680 /* There is more to be written.. wait for data to be removed from the pipe */
681
682 while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval != 0)
683 {
684 pipecommon_semtake(&dev->d_wrsem);
685 }
686 sem_post(&dev->d_bfsem);
687
688 pipecommon_semtake(&dev->d_wrsem);
689 pipecommon_semtake(&dev->d_bfsem);
690 }
691 }
692 }
693
694 /****************************************************************************
695 * Name: pipecommon_poll
696 ****************************************************************************/
697
pipecommon_poll(struct file * filep,poll_table * table)698 int pipecommon_poll(struct file *filep, poll_table *table)
699 {
700 struct Vnode *vnode = filep->f_vnode;
701 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
702 pollevent_t eventset;
703 pipe_ndx_t nbytes;
704 int ret;
705
706 if (dev == NULL || table == NULL)
707 {
708 return -EINVAL;
709 }
710
711 /* Are we setting up the poll? Or tearing it down? */
712
713 pipecommon_semtake(&dev->d_bfsem);
714
715 /* Should immediately notify on any of the requested events?
716 * First, determine how many bytes are in the buffer
717 */
718
719 if (dev->d_wrndx >= dev->d_rdndx)
720 {
721 nbytes = dev->d_wrndx - dev->d_rdndx;
722 }
723 else
724 {
725 nbytes = dev->d_bufsize + dev->d_wrndx - dev->d_rdndx;
726 }
727
728 /* Notify the POLLOUT event if the pipe is not full, but only if
729 * there is readers.
730 */
731
732 eventset = 0;
733 if (((filep->f_oflags & O_WRONLY) != 0) && (nbytes < (dev->d_bufsize - 1)))
734 {
735 eventset |= POLLOUT;
736 }
737
738 /* Notify the POLLIN event if the pipe is not empty */
739
740 if (((filep->f_oflags & O_WRONLY) == 0) && (nbytes > 0))
741 {
742 eventset |= POLLIN;
743 }
744
745 /* Notify the POLLHUP event if the pipe is empty and no writers */
746
747 if (nbytes == 0 && dev->d_nwriters <= 0)
748 {
749 eventset |= POLLHUP;
750 }
751
752 /* Change POLLOUT to POLLERR, if no readers and policy 0. */
753
754 if ((eventset | POLLOUT) &&
755 PIPE_IS_POLICY_0(dev->d_flags) &&
756 dev->d_nreaders <= 0)
757 {
758 eventset |= POLLERR;
759 }
760
761 ret = eventset & table->key;
762 if (ret == 0)
763 {
764 poll_wait(NULL, &dev->wq, table);
765 }
766 sem_post(&dev->d_bfsem);
767
768 return ret;
769 }
770
771 /****************************************************************************
772 * Name: pipecommon_ioctl
773 ****************************************************************************/
774
pipecommon_ioctl(struct file * filep,int cmd,unsigned long arg)775 int pipecommon_ioctl(struct file *filep, int cmd, unsigned long arg)
776 {
777 return -ENOSYS;
778 }
779
780 /****************************************************************************
781 * Name: pipecommon_unlink
782 ****************************************************************************/
783
784 #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
pipecommon_unlink(struct Vnode * vnode)785 int pipecommon_unlink(struct Vnode *vnode)
786 {
787 struct pipe_dev_s *dev = NULL;
788
789 if (vnode == NULL || vnode->data == NULL)
790 {
791 return -EINVAL;
792 }
793
794 dev = ((struct drv_data *)vnode->data)->priv;
795 if (dev == NULL)
796 {
797 return -EINVAL;
798 }
799
800 if (dev->d_buffer)
801 {
802 free(dev->d_buffer);
803 }
804
805 /* And free the device structure. */
806 unregister_driver(dev->name);
807 pipecommon_freedev(dev);
808
809 return OK;
810 }
811 #endif
812
813 #endif /* LOSCFG_KERNEL_PIPE */
814