Adds OS internal function nx_write() which is functionally equivalent to write() except that it does not set the errno variable and do not cause cancellation points.

This commit is contained in:
Gregory Nutt 2017-10-11 10:18:30 -06:00
parent af072d52bc
commit a00d8e16a1
14 changed files with 212 additions and 128 deletions

View File

@ -299,18 +299,19 @@ static ssize_t loop_write(FAR struct inode *inode,
ret = lseek(dev->fd, offset, SEEK_SET);
if (ret == (off_t)-1)
{
_err("ERROR: Seek failed for offset=%d: %d\n", (int)offset, get_errno());
_err("ERROR: Seek failed for offset=%d: %d\n",
(int)offset, get_errno());
}
/* Then write the requested number of sectors to that position */
do
{
nbyteswritten = write(dev->fd, buffer, nsectors * dev->sectsize);
if (nbyteswritten < 0 && get_errno() != EINTR)
nbyteswritten = nx_write(dev->fd, buffer, nsectors * dev->sectsize);
if (nbyteswritten < 0 && nbyteswritten != -EINTR)
{
_err("ERROR: Write failed: %d\n", get_errno());
return -get_errno();
_err("ERROR: nx_write failed: %d\n", nbyteswritten);
return nbyteswritten;
}
}
while (nbyteswritten < 0);

View File

@ -49,6 +49,7 @@
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/mtd/mtd.h>
@ -204,7 +205,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset,
if (buflen == 0)
{
lseek(priv->fd, seekpos, SEEK_SET);
write(priv->fd, buf, sizeof(buf));
(void)nx_write(priv->fd, buf, sizeof(buf));
seekpos += sizeof(buf);
}
}
@ -214,7 +215,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset,
if (buflen != 0)
{
lseek(priv->fd, seekpos, SEEK_SET);
write(priv->fd, buf, sizeof(buf));
(void)nx_write(priv->fd, buf, sizeof(buf));
}
return len;
@ -281,7 +282,7 @@ static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
memset(buffer, CONFIG_FILEMTD_ERASESTATE, sizeof(buffer));
while (nbytes)
{
write(priv->fd, buffer, sizeof(buffer));
(void)nx_write(priv->fd, buffer, sizeof(buffer));
nbytes -= sizeof(buffer);
}
@ -333,7 +334,7 @@ static ssize_t filemtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
****************************************************************************/
static ssize_t filemtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, FAR const uint8_t *buf)
size_t nblocks, FAR const uint8_t *buf)
{
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
off_t offset;
@ -396,7 +397,7 @@ static ssize_t filemtd_byteread(FAR struct mtd_dev_s *dev, off_t offset,
#ifdef CONFIG_MTD_BYTE_WRITE
static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
size_t nbytes, FAR const uint8_t *buf)
size_t nbytes, FAR const uint8_t *buf)
{
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
off_t maxoffset;

View File

@ -118,8 +118,12 @@ void cc3000_resume(void)
long cc3000_write(uint8_t *pUserBuffer, uint16_t usLength)
{
ssize_t ret;
DEBUGASSERT(spiconf.cc3000fd >= 0);
return write(spiconf.cc3000fd, pUserBuffer, usLength) == usLength ? 0 : -errno;
ret = nx_write(spiconf.cc3000fd, pUserBuffer, usLength);
return ret >= 0 ? 0 : ret;
}
/****************************************************************************

View File

@ -65,8 +65,24 @@
*
* Description:
* Equivalent to the standard write() function except that is accepts a
* struct file instance instead of a file descriptor. Currently used
* only by aio_write();
* struct file instance instead of a file descriptor. It is functionally
* equivalent to write() except that in addition to the differences in
* input paramters:
*
* - It does not modify the errno variable,
* - It is not a cancellation point, and
* - It does not handle socket descriptors.
*
* Input Parameters:
* filep - Instance of struct file to use with the write
* buf - Data to write
* nbytes - Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On any failure, a negated errno value is returned
* (see comments withwrite() for a description of the appropriate errno
* values).
*
****************************************************************************/
@ -94,6 +110,81 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
return inode->u.i_ops->write(filep, buf, nbytes);
}
/****************************************************************************
* Name: nx_write
*
* Description:
* nx_write() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf. nx_write() is an
* internal OS function. It is functionally equivalent to write() except
* that:
*
* - It does not modify the errno variable, and
* - It is not a cancellation point.
*
* Input Parameters:
* fd - file descriptor (or socket descriptor) to write to
* buf - Data to write
* nbytes - Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On any failure, a negated errno value is returned
* (see comments withwrite() for a description of the appropriate errno
* values).
*
****************************************************************************/
ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep;
#endif
ssize_t ret;
if (buf == NULL)
{
return -EINVAL;
}
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
/* Write to a socket descriptor is equivalent to send with flags == 0. */
ret = nx_send(fd, buf, nbytes, 0);
#else
ret = -EBADF;
#endif
}
#if CONFIG_NFILE_DESCRIPTORS > 0
else
{
/* The descriptor is in the right range to be a file descriptor..
* write to the file. Note that fs_getfilep() will set the errno on
* failure.
*/
ret = (ssize_t)fs_getfilep(fd, &filep);
if (ret >= 0)
{
/* Perform the write operation using the file descriptor as an
* index. Note that file_write() will set the errno on failure.
*/
ret = file_write(filep, buf, nbytes);
}
}
#endif
return ret;
}
/****************************************************************************
* Name: write
*
@ -101,13 +192,13 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
* write() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf.
*
* Parameters:
* fd file descriptor (or socket descriptor) to write to
* buf Data to write
* nbytes Length of data to write
* Input Parameters:
* fd - file descriptor (or socket descriptor) to write to
* buf - Data to write
* nbytes - Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On error, -1 is returned, and errno is set appro-
* priately:
*
@ -140,78 +231,25 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes)
* signal. (Thus, the write return value is seen only if the program
* catches, blocks or ignores this signal.)
*
* Assumptions:
*
********************************************************************************************/
****************************************************************************/
ssize_t write(int fd, FAR const void *buf, size_t nbytes)
{
#if CONFIG_NFILE_DESCRIPTORS > 0
FAR struct file *filep;
#endif
ssize_t ret;
/* write() is a cancellation point */
(void)enter_cancellation_point();
if (buf == NULL)
/* Let nx_write() do all of the work */
ret = nx_write(fd, buf, nbytes);
if (ret < 0)
{
ret = -EINVAL;
goto errout;
set_errno(ret);
ret = ERROR;
}
/* Did we get a valid file descriptor? */
#if CONFIG_NFILE_DESCRIPTORS > 0
if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS)
#endif
{
#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
/* Write to a socket descriptor is equivalent to send with flags == 0. */
ret = nx_send(fd, buf, nbytes, 0);
if (ret < 0)
{
goto errout;
}
#else
ret = -EBADF;
goto errout;
#endif
}
#if CONFIG_NFILE_DESCRIPTORS > 0
else
{
/* The descriptor is in the right range to be a file descriptor..
* write to the file. Note that fs_getfilep() will set the errno on
* failure.
*/
ret = (ssize_t)fs_getfilep(fd, &filep);
if (ret < 0)
{
goto errout;
}
/* Perform the write operation using the file descriptor as an
* index. Note that file_write() will set the errno on failure.
*/
ret = file_write(filep, buf, nbytes);
if (ret < 0)
{
goto errout;
}
}
#endif
leave_cancellation_point();
return ret;
errout:
set_errno(-ret);
leave_cancellation_point();
return ERROR;
}

View File

@ -84,12 +84,14 @@
#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
# define _NX_WRITE(f,b,s) nx_write(s,b,s)
# define _NX_ERRNO(r) (-(r))
# define _NX_ERRVAL(r) (r)
# define _NX_GETERRNO(r) (-(r))
# define _NX_SETERRNO(r) set_errno(-(r))
# define _NX_GETERRVAL(r) (r)
#else
# define _NX_WRITE(f,b,s) rite(s,b,s)
# define _NX_ERRNO(r) errno
# define _NX_ERRVAL(r) (-errno)
# define _NX_WRITE(f,b,s) write(s,b,s)
# define _NX_GETERRNO(r) errno
# define _NX_SETERRNO(r)
# define _NX_GETERRVAL(r) (-errno)
#endif
/* Stream flags for the fs_flags field of in struct file_struct */
@ -935,6 +937,33 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes);
ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes);
#endif
/****************************************************************************
* Name: nx_write
*
* Description:
* nx_write() writes up to nytes bytes to the file referenced by the file
* descriptor fd from the buffer starting at buf. nx_write() is an
* internal OS function. It is functionally equivalent to write() except
* that:
*
* - It does not modify the errno variable, and
* - It is not a cancellation point.
*
* Input Parameters:
* fd - file descriptor (or socket descriptor) to write to
* buf - Data to write
* nbytes - Length of data to write
*
* Returned Value:
* On success, the number of bytes written are returned (zero indicates
* nothing was written). On any failure, a negated errno value is returned
* (see comments withwrite() for a description of the appropriate errno
* values).
*
****************************************************************************/
ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes);
/****************************************************************************
* Name: file_pread
*

View File

@ -76,14 +76,14 @@
# define _NX_SEND(s,b,l,f) nx_send(s,b,l,f)
# define _NX_RECV(s,b,l,f) nx_recv(s,b,l,f)
# define _NX_RECVFROM(s,b,l,f,a,n) nx_recvfrom(s,b,l,f,a,n)
# define _NX_ERRNO(r) (-(r))
# define _NX_ERRVAL(r) (r)
# define _NX_GETERRNO(r) (-(r))
# define _NX_GETERRVAL(r) (r)
#else
# define _NX_SEND(s,b,l,f) send(s,b,l,f)
# define _NX_RECV(s,b,l,f) recv(s,b,l,f)
# define _NX_RECVFROM(s,b,l,f,a,n) recvfrom(s,b,l,f,a,n)
# define _NX_ERRNO(r) errno
# define _NX_ERRVAL(r) (-errno)
# define _NX_GETERRNO(r) errno
# define _NX_GETERRVAL(r) (-errno)
#endif
/* Socket descriptors are the index into the TCB sockets list, offset by the

View File

@ -45,26 +45,12 @@
#include <unistd.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "libc.h"
#if CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0
/****************************************************************************
* Private types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
@ -217,7 +203,7 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
{
/* Write the buffer of data to the outfd */
nbyteswritten = write(outfd, wrbuffer, nbytesread);
nbyteswritten = _NX_WRITE(outfd, wrbuffer, nbytesread);
/* Check for a complete (or parial) write. write() should not
* return zero.
@ -242,6 +228,8 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
else
{
int errcode = _NX_GETERRNO(nbyteswritten);
/* Check for a read ERROR. EINTR is a special case. This
* function should break out and return an error if EINTR
* is returned and no data has been transferred. But what
@ -250,11 +238,12 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count)
*/
#ifndef CONFIG_DISABLE_SIGNALS
if (errno != EINTR || ntransferred == 0)
if (errcode != EINTR || ntransferred == 0)
#endif
{
/* Write error. Break out and return the error condition */
_NX_SETERRNO(nbyteswritten);
ntransferred = ERROR;
endxfr = true;
break;

View File

@ -255,9 +255,9 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr,
ret = _NX_RECV(sd, buffer, RECV_BUFFER_SIZE, 0);
if (ret < 0)
{
errcode = _NX_ERRNO(ret);
errcode = -_NX_GETERRNO(ret);
nerr("ERROR: recv failed: %d\n", errcode);
return -errcode;
return errcode;
}
hdr = (FAR struct dns_header_s *)buffer;

View File

@ -52,7 +52,8 @@
* Name: fwrite
****************************************************************************/
size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream)
size_t fwrite(FAR const void *ptr, size_t size, size_t n_items,
FAR FILE *stream)
{
size_t full_size = n_items * (size_t)size;
ssize_t bytes_written;

View File

@ -129,7 +129,7 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
{
/* Perform the write */
bytes_written = write(stream->fs_fd, src, nbuffer);
bytes_written = _NX_WRITE(stream->fs_fd, src, nbuffer);
if (bytes_written < 0)
{
/* Write failed. The cause of the failure is in 'errno'.
@ -137,7 +137,7 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
*/
stream->fs_flags |= __FS_FLAG_ERROR;
ret = -get_errno();
ret = _NX_GETERRVAL(bytes_written);
goto errout_with_sem;
}

View File

@ -46,6 +46,8 @@
#include <fcntl.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "libc.h"
/****************************************************************************
@ -84,7 +86,15 @@ ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream)
if (stream->fs_bufstart == NULL)
{
ret = write(stream->fs_fd, ptr, count);
ret = _NX_WRITE(stream->fs_fd, ptr, count);
#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__)
if (ret < 0)
{
_NX_SETERRNO((int)-ret);
ret = ERROR;
}
#endif
goto errout;
}
@ -167,10 +177,11 @@ errout:
}
#else
{
ssize_t ret = write(stream->fs_fd, ptr, count);
ssize_t ret = _NX_WRITE(stream->fs_fd, ptr, count);
if (ret < 0)
{
stream->fs_flags |= __FS_FLAG_ERROR;
_NX_SETERRNO(ret);
}
return ret;

View File

@ -37,10 +37,14 @@
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "libc.h"
/****************************************************************************
@ -54,8 +58,9 @@
static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch)
{
FAR struct lib_rawsostream_s *rthis = (FAR struct lib_rawsostream_s *)this;
int nwritten;
char buffer = ch;
int nwritten;
int errcode;
DEBUGASSERT(this && rthis->fd >= 0);
@ -65,7 +70,7 @@ static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch)
do
{
nwritten = write(rthis->fd, &buffer, 1);
nwritten = _NX_WRITE(rthis->fd, &buffer, 1);
if (nwritten == 1)
{
this->nput++;
@ -74,12 +79,13 @@ static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch)
/* The only expected error is EINTR, meaning that the write operation
* was awakened by a signal. Zero would not be a valid return value
* from write().
* from _NX_WRITE().
*/
errcode = _NX_GETERRNO(nwritten);
DEBUGASSERT(nwritten < 0);
}
while (get_errno() == EINTR);
while (errcode == EINTR);
}
/****************************************************************************

View File

@ -1,5 +1,5 @@
/****************************************************************************
* libc/stdio/lib_rawoutstream.c
* libc/stdio/lib_rawsostream.c
*
* Copyright (C) 2007-2009, 2011-2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -37,10 +37,14 @@
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "libc.h"
/****************************************************************************
@ -66,7 +70,7 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch)
do
{
nwritten = write(rthis->fd, &buffer, 1);
nwritten = _NX_WRITE(rthis->fd, &buffer, 1);
if (nwritten == 1)
{
this->nput++;
@ -75,10 +79,10 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch)
/* The only expected error is EINTR, meaning that the write operation
* was awakened by a signal. Zero or values > 1 would not be valid
* return values from write().
* return values from _NX_WRITE().
*/
errcode = get_errno();
errcode = _NX_GETERRNO(nwritten);
DEBUGASSERT(nwritten < 0);
}
while (errcode == EINTR);

View File

@ -38,7 +38,6 @@
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
#include <sys/types.h>
#include <stdint.h>
@ -47,8 +46,12 @@
#include <assert.h>
#include <debug.h>
#include <nuttx/fs/fs.h>
#include "local/local.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -92,16 +95,13 @@ static int local_fifo_write(int fd, FAR const uint8_t *buf, size_t len)
while (len > 0)
{
nwritten = write(fd, buf, len);
nwritten = nx_write(fd, buf, len);
if (nwritten < 0)
{
int errcode = get_errno();
DEBUGASSERT(errcode > 0);
if (errcode != EINTR)
if (nwritten != -EINTR)
{
nerr("ERROR: Write failed: %d\n", errcode);
return -errcode;
nerr("ERROR: nx_write failed: %d\n", nwritten);
return (int)nwritten;
}
ninfo("Ignoring signal\n");