1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2012-09-30     Bernard      first version.
9  * 2017-11-08     JasonJiaJie  fix memory leak issue when close a pipe.
10  * 2023-06-28     shell        return POLLHUP when writer closed its channel on poll()
11  *                             fix flag test on pipe_fops_open()
12  * 2023-12-02     shell        Make read pipe operation interruptable.
13  */
14 #include <rthw.h>
15 #include <rtdevice.h>
16 #include <stdint.h>
17 #include <sys/errno.h>
18 #include <ipc/condvar.h>
19 
20 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <poll.h>
24 #include <sys/ioctl.h>
25 #include <dfs_file.h>
26 #include <resource_id.h>
27 
28 /* check RT_UNAMED_PIPE_NUMBER */
29 
30 #ifndef RT_UNAMED_PIPE_NUMBER
31 #define RT_UNAMED_PIPE_NUMBER 64
32 #endif
33 
34 #define BITS(x) _BITS(x)
35 #define _BITS(x) (sizeof(#x) - 1)
36 
37 struct check_rt_unamed_pipe_number
38 {
39     /* -4 for "pipe" prefix */
40     /* -1 for '\0' postfix */
41     char _check[RT_NAME_MAX - 4 - 1 - BITS(RT_UNAMED_PIPE_NUMBER)];
42 };
43 
44 /* check end */
45 
46 static void *resoure_id[RT_UNAMED_PIPE_NUMBER];
47 static resource_id_t id_mgr = RESOURCE_ID_INIT(RT_UNAMED_PIPE_NUMBER, resoure_id);
48 
49 /**
50  * @brief    This function will open a pipe.
51  *
52  * @param    fd is the file descriptor.
53  *
54  * @return   Return the operation status.
55  *           When the return value is 0, it means the operation is successful.
56  *           When the return value is -1, it means the file descriptor is invalid.
57  *           When the return value is -RT_ENOMEM, it means insufficient memory allocation failed.
58  */
pipe_fops_open(struct dfs_file * fd)59 static int pipe_fops_open(struct dfs_file *fd)
60 {
61     int rc = 0;
62     rt_pipe_t *pipe;
63 
64     pipe = (rt_pipe_t *)fd->vnode->data;
65     if (!pipe)
66     {
67         return -1;
68     }
69 
70     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
71 
72     if ((fd->flags & O_ACCMODE) == O_RDONLY)
73     {
74         pipe->reader += 1;
75     }
76 
77     if ((fd->flags & O_ACCMODE) == O_WRONLY)
78     {
79         pipe->writer += 1;
80     }
81     if (fd->vnode->ref_count == 1)
82     {
83         pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
84         if (pipe->fifo == RT_NULL)
85         {
86             rc = -RT_ENOMEM;
87             goto __exit;
88         }
89     }
90 
91     if ((fd->flags & O_ACCMODE) == O_RDONLY && !pipe->writer)
92     {
93         /* wait for partner */
94         rc = rt_condvar_timedwait(&pipe->waitfor_parter, &pipe->lock,
95                                   RT_INTERRUPTIBLE, RT_WAITING_FOREVER);
96         if (rc != 0)
97         {
98             pipe->reader--;
99         }
100     }
101     else if ((fd->flags & O_ACCMODE) == O_WRONLY)
102     {
103         rt_condvar_broadcast(&pipe->waitfor_parter);
104     }
105 
106 __exit:
107     rt_mutex_release(&pipe->lock);
108 
109     return rc;
110 }
111 
112 /**
113  * @brief    This function will close a pipe.
114  *
115  * @param    fd is the file descriptor.
116  *
117  * @return   Return the operation status.
118  *           When the return value is 0, it means the operation is successful.
119  *           When the return value is -1, it means the file descriptor is invalid.
120  */
pipe_fops_close(struct dfs_file * fd)121 static int pipe_fops_close(struct dfs_file *fd)
122 {
123     rt_device_t device;
124     rt_pipe_t *pipe;
125 
126     pipe = (rt_pipe_t *)fd->vnode->data;
127     if (!pipe)
128     {
129         return -1;
130     }
131 
132     device = &pipe->parent;
133     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
134 
135     if ((fd->flags & O_RDONLY) == O_RDONLY)
136     {
137         pipe->reader -= 1;
138     }
139 
140     if ((fd->flags & O_WRONLY) == O_WRONLY)
141     {
142         pipe->writer -= 1;
143         while (!rt_list_isempty(&pipe->reader_queue.waiting_list))
144         {
145             rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
146         }
147     }
148 
149     if (fd->vnode->ref_count == 1)
150     {
151         if (pipe->fifo != RT_NULL)
152         {
153             rt_ringbuffer_destroy(pipe->fifo);
154         }
155         pipe->fifo = RT_NULL;
156     }
157 
158     rt_mutex_release(&pipe->lock);
159 
160     if (fd->vnode->ref_count == 1 && pipe->is_named == RT_FALSE)
161     {
162         /* delete the unamed pipe */
163         rt_pipe_delete(device->parent.name);
164     }
165 
166     return 0;
167 }
168 
169 /**
170  * @brief    This function will get the pipe space size depends on the command.
171  *
172  * @param    fd is the file descriptor.
173  *
174  * @param    cmd is the command. It determines what data will get.
175  *
176  *               FIONREAD        The command to get the number of bytes in the pipe.
177  *
178  *               FIONWRITE       The command to get the number of bytes can be written to the pipe.
179  *
180  * @param    args is the pointer to the data to store the read data.
181  *
182  * @return   Return the operation status.
183  *           When the return value is 0, it means the operation is successful.
184  *           When the return value is -EINVAL, it means the command is invalid.
185  */
pipe_fops_ioctl(struct dfs_file * fd,int cmd,void * args)186 static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
187 {
188     rt_pipe_t *pipe;
189     int ret = 0;
190 
191     pipe = (rt_pipe_t *)fd->vnode->data;
192 
193     switch (cmd)
194     {
195     case FIONREAD:
196         *((int*)args) = rt_ringbuffer_data_len(pipe->fifo);
197         break;
198     case FIONWRITE:
199         *((int*)args) = rt_ringbuffer_space_len(pipe->fifo);
200         break;
201     default:
202         ret = -EINVAL;
203         break;
204     }
205 
206     return ret;
207 }
208 
209 /**
210  * @brief    This function will read data from pipe.
211  *
212  * @param    fd is the file descriptor.
213  *
214  * @param    buf is the buffer to store the read data.
215  *
216  * @param    count is the length of data to be read.
217  *
218  * @return   Return the length of data read.
219  *           When the return value is 0, it means O_NONBLOCK is enabled and there is no thread that has the pipe open for writing.
220  *           When the return value is -EAGAIN, it means there are no data to be read.
221  */
222 #ifdef RT_USING_DFS_V2
pipe_fops_read(struct dfs_file * fd,void * buf,size_t count,off_t * pos)223 static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
224 #else
225 static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count)
226 #endif
227 {
228     int len = 0;
229     rt_pipe_t *pipe;
230 
231     pipe = (rt_pipe_t *)fd->vnode->data;
232 
233     /* no process has the pipe open for writing, return end-of-file */
234     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
235 
236     while (1)
237     {
238         len = rt_ringbuffer_get(pipe->fifo, buf, count);
239 
240         if (len > 0 || pipe->writer == 0)
241         {
242             break;
243         }
244         else
245         {
246             if (fd->flags & O_NONBLOCK)
247             {
248                 len = -EAGAIN;
249                 goto out;
250             }
251 
252             rt_mutex_release(&pipe->lock);
253             rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
254             if (rt_wqueue_wait_interruptible(&pipe->reader_queue, 0, -1) == -RT_EINTR)
255                 return -EINTR;
256             rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
257         }
258     }
259 
260     /* wakeup writer */
261     rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
262 
263 out:
264     rt_mutex_release(&pipe->lock);
265     return len;
266 }
267 
268 /**
269  * @brief    This function will write data to pipe.
270  *
271  * @param    fd is the file descriptor.
272  *
273  * @param    buf is a pointer to the data buffer to be written.
274  *
275  * @param    count is the length of data to be write.
276  *
277  * @return   Return the length of data written.
278  *           When the return value is -EAGAIN, it means O_NONBLOCK is enabled and there are no space to be written.
279  *           When the return value is -EPIPE, it means there is no thread that has the pipe open for reading.
280  */
281 #ifdef RT_USING_DFS_V2
pipe_fops_write(struct dfs_file * fd,const void * buf,size_t count,off_t * pos)282 static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
283 #else
284 static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count)
285 #endif
286 {
287     int len;
288     rt_pipe_t *pipe;
289     int wakeup = 0;
290     int ret = 0;
291     uint8_t *pbuf;
292 
293     pipe = (rt_pipe_t *)fd->vnode->data;
294 
295     if (count == 0)
296     {
297         return 0;
298     }
299 
300     pbuf = (uint8_t*)buf;
301     rt_mutex_take(&pipe->lock, -1);
302 
303     while (1)
304     {
305         len = rt_ringbuffer_put(pipe->fifo, pbuf, count - ret);
306         ret +=  len;
307         pbuf += len;
308         wakeup = 1;
309 
310         if (ret == count)
311         {
312             break;
313         }
314         else
315         {
316             if (fd->flags & O_NONBLOCK)
317             {
318                 if (ret == 0)
319                 {
320                     ret = -EAGAIN;
321                 }
322 
323                 break;
324             }
325         }
326 
327         rt_mutex_release(&pipe->lock);
328         rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
329         /* pipe full, waiting on suspended write list */
330         if (rt_wqueue_wait_interruptible(&pipe->writer_queue, 0, -1) == -RT_EINTR)
331             return -EINTR;
332         rt_mutex_take(&pipe->lock, -1);
333     }
334     rt_mutex_release(&pipe->lock);
335 
336     if (wakeup)
337     {
338         rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
339     }
340 
341     return ret;
342 }
343 
344 /**
345  * @brief    This function will get the pipe status.
346  *
347  * @param    fd is the file descriptor.
348  *
349  * @param    req is the request type.
350  *
351  * @return   mask of the pipe status.
352  *           POLLIN means there is data to be read.
353  *           POLLHUP means there is no thread that occupied the pipe to open for writing.
354  *           POLLOUT means there is space to be written.
355  *           POLLERR means there is no thread that occupied the pipe to open for reading.
356  */
pipe_fops_poll(struct dfs_file * fd,rt_pollreq_t * req)357 static int pipe_fops_poll(struct dfs_file *fd, rt_pollreq_t *req)
358 {
359     int mask = 0;
360     rt_pipe_t *pipe;
361     int mode = 0;
362     pipe = (rt_pipe_t *)fd->vnode->data;
363 
364     rt_poll_add(&pipe->reader_queue, req);
365     rt_poll_add(&pipe->writer_queue, req);
366 
367     switch (fd->flags & O_ACCMODE)
368     {
369     case O_RDONLY:
370         mode = 1;
371         break;
372     case O_WRONLY:
373         mode = 2;
374         break;
375     case O_RDWR:
376         mode = 3;
377         break;
378     }
379 
380     if (mode & 1)
381     {
382         if (rt_ringbuffer_data_len(pipe->fifo) != 0)
383         {
384             mask |= POLLIN;
385         }
386         else if (pipe->writer == 0)
387         {
388             mask = POLLHUP;
389         }
390     }
391 
392     if (mode & 2)
393     {
394         if (rt_ringbuffer_space_len(pipe->fifo) != 0)
395         {
396             mask |= POLLOUT;
397         }
398     }
399 
400     return mask;
401 }
402 
403 static const struct dfs_file_ops pipe_fops =
404 {
405     .open  = pipe_fops_open,
406     .close = pipe_fops_close,
407     .ioctl = pipe_fops_ioctl,
408     .read  = pipe_fops_read,
409     .write = pipe_fops_write,
410     .poll  = pipe_fops_poll,
411 };
412 #endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */
413 
414 /**
415  * @brief    This function will open the pipe and actually creates the pipe buffer.
416  *
417  * @param    device is a pointer to the pipe device descriptor.
418  *
419  * @param    oflag is the open method, but it is not used yet.
420  *
421  * @return   Return the operation status.
422  *           When the return value is RT_EOK, the operation is successful.
423  *           When the return value is -RT_EINVAL, it means the device handle is empty.
424  *           When the return value is -RT_ENOMEM, it means insufficient memory allocation failed.
425  */
rt_pipe_open(rt_device_t device,rt_uint16_t oflag)426 rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag)
427 {
428     rt_pipe_t *pipe = (rt_pipe_t *)device;
429     rt_err_t ret = RT_EOK;
430 
431     if (device == RT_NULL)
432     {
433         ret = -RT_EINVAL;
434         goto __exit;
435     }
436 
437     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
438 
439     if (pipe->fifo == RT_NULL)
440     {
441         pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
442         if (pipe->fifo == RT_NULL)
443         {
444             ret = -RT_ENOMEM;
445         }
446     }
447 
448     rt_mutex_release(&pipe->lock);
449 
450 __exit:
451     return ret;
452 }
453 
454 /**
455  * @brief    This function will close the pipe and release the pipe buffer.
456  *
457  * @param    device is a pointer to the pipe device descriptor.
458  *
459  * @return   Return the operation status.
460  *           When the return value is RT_EOK, the operation is successful.
461  *           When the return value is -RT_EINVAL, it means the device handle is empty.
462  */
rt_pipe_close(rt_device_t device)463 rt_err_t rt_pipe_close(rt_device_t device)
464 {
465     rt_pipe_t *pipe = (rt_pipe_t *)device;
466 
467     if (device == RT_NULL)
468     {
469         return -RT_EINVAL;
470     }
471     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
472 
473     rt_ringbuffer_destroy(pipe->fifo);
474     pipe->fifo = RT_NULL;
475 
476     rt_mutex_release(&pipe->lock);
477 
478     return RT_EOK;
479 }
480 
481 /**
482  * @brief    This function will read the specified length of data from the pipe.
483  *
484  * @param    device is a pointer to the pipe device descriptor.
485  *
486  * @param    pos is a parameter compatible with POSIX standard interface (currently meaningless, just pass in 0).
487  *
488  * @param    buffer is a pointer to the buffer to store the read data.
489  *
490  * @param    count is the length of data to be read.
491  *
492  * @return   Return the length of data read.
493  *           When the return value is 0, it means the pipe device handle is empty or the count is 0.
494  */
rt_pipe_read(rt_device_t device,rt_off_t pos,void * buffer,rt_size_t count)495 rt_ssize_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
496 {
497     uint8_t *pbuf;
498     rt_size_t read_bytes = 0;
499     rt_pipe_t *pipe = (rt_pipe_t *)device;
500 
501     if (device == RT_NULL)
502     {
503         rt_set_errno(-EINVAL);
504         return 0;
505     }
506     if (count == 0)
507     {
508         return 0;
509     }
510 
511     pbuf = (uint8_t*)buffer;
512     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
513 
514     while (read_bytes < count)
515     {
516         int len = rt_ringbuffer_get(pipe->fifo, &pbuf[read_bytes], count - read_bytes);
517         if (len <= 0)
518         {
519             break;
520         }
521 
522         read_bytes += len;
523     }
524     rt_mutex_release(&pipe->lock);
525 
526     return read_bytes;
527 }
528 
529 /**
530  * @brief    This function will write the specified length of data to the pipe.
531  *
532  * @param    device is a pointer to the pipe device descriptor.
533  *
534  * @param    pos is a parameter compatible with POSIX standard interface (currently meaningless, just pass in 0).
535  *
536  * @param    buffer is a pointer to the data buffer to be written.
537  *
538  * @param    count is the length of data to be written.
539  *
540  * @return   Return the length of data written.
541  *           When the return value is 0, it means the pipe device handle is empty or the count is 0.
542  */
rt_pipe_write(rt_device_t device,rt_off_t pos,const void * buffer,rt_size_t count)543 rt_ssize_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
544 {
545     uint8_t *pbuf;
546     rt_size_t write_bytes = 0;
547     rt_pipe_t *pipe = (rt_pipe_t *)device;
548 
549     if (device == RT_NULL)
550     {
551         rt_set_errno(-EINVAL);
552         return 0;
553     }
554     if (count == 0)
555     {
556         return 0;
557     }
558 
559     pbuf = (uint8_t*)buffer;
560     rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
561 
562     while (write_bytes < count)
563     {
564         int len = rt_ringbuffer_put(pipe->fifo, &pbuf[write_bytes], count - write_bytes);
565         if (len <= 0)
566         {
567             break;
568         }
569 
570         write_bytes += len;
571     }
572     rt_mutex_release(&pipe->lock);
573 
574     return write_bytes;
575 }
576 
577 /**
578  * @brief    This function is not used yet.
579  *
580  * @param    dev is not used yet.
581  *
582  * @param    cmd is not used yet.
583  *
584  * @param    args is not used yet.
585  *
586  * @return   Always return RT_EOK.
587  */
rt_pipe_control(rt_device_t dev,int cmd,void * args)588 rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
589 {
590     return RT_EOK;
591 }
592 
593 #ifdef RT_USING_DEVICE_OPS
594 const static struct rt_device_ops pipe_ops =
595 {
596     RT_NULL,
597     rt_pipe_open,
598     rt_pipe_close,
599     rt_pipe_read,
600     rt_pipe_write,
601     rt_pipe_control,
602 };
603 #endif /* RT_USING_DEVICE_OPS */
604 
605 /**
606  * @brief    This function will initialize a pipe device.
607  *           The system allocates a pipe handle from dynamic heap memory, initializes the pipe handle
608  *           with the specified value, and registers the pipe device with the system.
609  *
610  * @param    name is the name of pipe device.
611  *
612  * @param    bufsz is the size of pipe buffer.
613  *
614  * @return   Return the pointer to the pipe device.
615  *           When the return value is RT_NULL, it means the initialization failed.
616  */
rt_pipe_create(const char * name,int bufsz)617 rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
618 {
619     rt_pipe_t *pipe;
620     rt_device_t dev;
621 
622     RT_ASSERT(name != RT_NULL);
623     RT_ASSERT(bufsz < 0xFFFF);
624 
625     if (rt_device_find(name) != RT_NULL)
626     {
627         /* pipe device has been created */
628         return RT_NULL;
629     }
630     pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t));
631     if (pipe == RT_NULL) return RT_NULL;
632 
633     rt_memset(pipe, 0, sizeof(rt_pipe_t));
634     pipe->is_named = RT_TRUE; /* initialize as a named pipe */
635 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
636     pipe->pipeno = -1;
637 #endif
638     rt_mutex_init(&pipe->lock, name, RT_IPC_FLAG_FIFO);
639     rt_wqueue_init(&pipe->reader_queue);
640     rt_wqueue_init(&pipe->writer_queue);
641     rt_condvar_init(&pipe->waitfor_parter, "piwfp");
642 
643     pipe->writer = 0;
644     pipe->reader = 0;
645 
646     pipe->bufsz = bufsz;
647 
648     dev = &pipe->parent;
649     dev->type = RT_Device_Class_Pipe;
650 #ifdef RT_USING_DEVICE_OPS
651     dev->ops         = &pipe_ops;
652 #else
653     dev->init        = RT_NULL;
654     dev->open        = rt_pipe_open;
655     dev->read        = rt_pipe_read;
656     dev->write       = rt_pipe_write;
657     dev->close       = rt_pipe_close;
658     dev->control     = rt_pipe_control;
659 #endif
660 
661     dev->rx_indicate = RT_NULL;
662     dev->tx_complete = RT_NULL;
663 
664     rt_device_register(&pipe->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
665 
666 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
667     dev->fops = (void *)&pipe_fops;
668 #endif
669 
670     return pipe;
671 }
672 
673 /**
674  * @brief    This function will delete a pipe device.
675  *           The system will release the pipe handle and unregister the pipe device from the system.
676  *
677  * @param    pipe is the pointer to the pipe device.
678  *
679  * @return   Return the operation status.
680  *           When the return value is 0, it means the operation is successful.
681  *           When the return value is -RT_EINVAL, it means the pipe device is not found or the device isn't a pipe.
682  *           When the return value is -RT_EBUSY, it means the pipe device is busy.
683  */
rt_pipe_delete(const char * name)684 int rt_pipe_delete(const char *name)
685 {
686     int result = 0;
687     rt_device_t device;
688 
689     device = rt_device_find(name);
690     if (device)
691     {
692         if (device->type == RT_Device_Class_Pipe)
693         {
694             rt_pipe_t *pipe;
695 
696             pipe = (rt_pipe_t *)device;
697 
698             rt_condvar_detach(&pipe->waitfor_parter);
699             rt_mutex_detach(&pipe->lock);
700 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
701             resource_id_put(&id_mgr, pipe->pipeno);
702 #endif
703             rt_device_unregister(device);
704 
705             /* close fifo ringbuffer */
706             if (pipe->fifo)
707             {
708                 rt_ringbuffer_destroy(pipe->fifo);
709                 pipe->fifo = RT_NULL;
710             }
711             rt_free(pipe);
712         }
713         else
714         {
715             result = -ENODEV;
716         }
717     }
718     else
719     {
720         result = -ENODEV;
721     }
722 
723     return result;
724 }
725 
726 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
727 /**
728  * @brief    This function will creat a anonymous pipe.
729  *
730  * @param    fildes[0] is the read handle.
731  *           fildes[1] is the write handle.
732  *
733  * @return   Return the operation status.
734  *           When the return value is 0, it means the operation is successful.
735  *           When the return value is -1, it means the operation is failed.
736  */
pipe(int fildes[2])737 int pipe(int fildes[2])
738 {
739     rt_pipe_t *pipe;
740     char dname[8];
741     char dev_name[32];
742     int pipeno = 0;
743 
744     pipeno = resource_id_get(&id_mgr);
745     if (pipeno == -1)
746     {
747         return -1;
748     }
749     rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno);
750 
751     pipe = rt_pipe_create(dname, RT_USING_POSIX_PIPE_SIZE);
752     if (pipe == RT_NULL)
753     {
754         resource_id_put(&id_mgr, pipeno);
755         return -1;
756     }
757 
758     pipe->is_named = RT_FALSE; /* unamed pipe */
759     pipe->pipeno = pipeno;
760     rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname);
761 
762     fildes[1] = open(dev_name, O_WRONLY, 0);
763     if (fildes[1] < 0)
764     {
765         rt_pipe_delete(dname);
766         return -1;
767     }
768 
769     fildes[0] = open(dev_name, O_RDONLY, 0);
770     if (fildes[0] < 0)
771     {
772         close(fildes[1]);
773         rt_pipe_delete(dname);
774         return -1;
775     }
776 
777     return 0;
778 }
779 
780 /**
781  * @brief    This function will create a named pipe.
782  *
783  * @param    path is the name of pipe device.
784  *
785  * @param    mode is not used yet.
786  *
787  * @return   Return the operation status.
788  *           When the return value is 0, it means the operation is successful.
789  *           When the return value is -1, it means the operation is failed.
790  */
mkfifo(const char * path,mode_t mode)791 int mkfifo(const char *path, mode_t mode)
792 {
793     rt_pipe_t *pipe;
794 
795     pipe = rt_pipe_create(path, RT_USING_POSIX_PIPE_SIZE);
796     if (pipe == RT_NULL)
797     {
798         return -1;
799     }
800 
801     return 0;
802 }
803 #endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */
804