diff options
Diffstat (limited to 'nuttx/drivers/pipe.c')
-rw-r--r-- | nuttx/drivers/pipe.c | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/nuttx/drivers/pipe.c b/nuttx/drivers/pipe.c index b4479963d..8c06974b1 100644 --- a/nuttx/drivers/pipe.c +++ b/nuttx/drivers/pipe.c @@ -85,8 +85,9 @@ static struct file_operations pipe_fops = 0 /* ioctl */ }; -static sem_t g_pipesem = { 1 }; -static uint32 g_pipeset = 0; +static sem_t g_pipesem = { 1 }; +static uint32 g_pipeset = 0; +static uint32 g_pipecreated = 0; /**************************************************************************** * Private Functions @@ -98,20 +99,16 @@ static uint32 g_pipeset = 0; static inline int pipe_allocate(void) { int pipeno; - int ret = sem_wait(&g_pipesem); - if (ret >= 0) + int ret = -ENFILE; + + for (pipeno = 0; pipeno < MAX_PIPES; pipeno++) { - ret = -ENFILE; - for (pipeno = 0; pipeno < MAX_PIPES; pipeno++) + if ((g_pipeset & (1 << pipeno)) == 0) { - if ((g_pipeset & (1 << pipeno)) == 0) - { - g_pipeset |= (1 << pipeno); - ret = pipeno; - break; - } + g_pipeset |= (1 << pipeno); + ret = pipeno; + break; } - (void)sem_post(&g_pipesem); } return ret; } @@ -146,16 +143,15 @@ static int pipe_close(FAR struct file *filep) return -EBADF; } #endif - pipeno = dev->s.d_pipeno; + pipeno = dev->d_pipeno; /* Perform common close operations */ ret = pipecommon_close(filep); if (ret == 0 && !inode->i_private) { - char devname[16]; - sprintf(devname, "/dev/pipe%d", pipeno); - unlink(devname); + /* Release the pipe */ + pipe_free(pipeno); } return ret; @@ -190,39 +186,61 @@ int pipe(int filedes[2]) int err; int ret; - /* Allocate a minor number for the pipe device */ + /* Get exclusive access to the pipe allocation data */ - pipeno = pipe_allocate(); - if (pipeno < 0) + ret = sem_wait(&g_pipesem); + if (ret < 0) { - err = -pipeno; - goto errout; + /* sem_wait() will have already set errno */ + + return ERROR; } - /* Allocate and initialize a new device structure instance */ + /* Allocate a minor number for the pipe device */ - dev = pipecommon_allocdev(); - if (!dev) + pipeno = pipe_allocate(); + if (pipeno < 0) { - pipe_free(pipeno); - err = ENOMEM; + (void)sem_post(&g_pipesem); + err = -pipeno; goto errout; } - dev->s.d_pipeno = pipeno; /* Create a pathname to the pipe device */ sprintf(devname, "/dev/pipe%d", pipeno); - /* Register the pipe device */ + /* Check if the pipe device has already been created */ - ret = register_driver(devname, &pipe_fops, 0666, (void*)dev); - if (ret != 0) + if ((g_pipecreated & (1 << pipeno)) == 0) { - err = -ret; - goto errout_with_dev; - } + /* No.. Allocate and initialize a new device structure instance */ + + dev = pipecommon_allocdev(); + if (!dev) + { + (void)sem_post(&g_pipesem); + err = ENOMEM; + goto errout_with_pipe; + } + dev->d_pipeno = pipeno; + /* Register the pipe device */ + + ret = register_driver(devname, &pipe_fops, 0666, (void*)dev); + if (ret != 0) + { + (void)sem_post(&g_pipesem); + err = -ret; + goto errout_with_dev; + } + + /* Remember that we created this device */ + + g_pipecreated |= (1 << pipeno); + } + (void)sem_post(&g_pipesem); + /* Get a write file descriptor */ filedes[1] = open(devname, O_WRONLY); @@ -249,6 +267,8 @@ errout_with_driver: unregister_driver(devname); errout_with_dev: pipecommon_freedev(dev); +errout_with_pipe: + pipe_free(pipeno); errout: errno = err; return ERROR; |