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