mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #5466 from kjbracey-arm/write_all
Make POSIX-like writes write everything when blockingpull/5574/head^2
commit
b9c3003419
|
@ -138,16 +138,26 @@ ssize_t UARTSerial::write(const void* buffer, size_t length)
|
|||
size_t data_written = 0;
|
||||
const char *buf_ptr = static_cast<const char *>(buffer);
|
||||
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
api_lock();
|
||||
|
||||
while (_txbuf.full()) {
|
||||
// Unlike read, we should write the whole thing if blocking. POSIX only
|
||||
// allows partial as a side-effect of signal handling; it normally tries to
|
||||
// write everything if blocking. Without signals we can always write all.
|
||||
while (data_written < length) {
|
||||
|
||||
if (_txbuf.full()) {
|
||||
if (!_blocking) {
|
||||
api_unlock();
|
||||
return -EAGAIN;
|
||||
break;
|
||||
}
|
||||
do {
|
||||
api_unlock();
|
||||
wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
|
||||
api_lock();
|
||||
} while (_txbuf.full());
|
||||
}
|
||||
|
||||
while (data_written < length && !_txbuf.full()) {
|
||||
|
@ -164,10 +174,11 @@ ssize_t UARTSerial::write(const void* buffer, size_t length)
|
|||
}
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
api_unlock();
|
||||
|
||||
return data_written;
|
||||
return data_written != 0 ? (ssize_t) data_written : (ssize_t) -EAGAIN;
|
||||
}
|
||||
|
||||
ssize_t UARTSerial::read(void* buffer, size_t length)
|
||||
|
@ -176,6 +187,10 @@ ssize_t UARTSerial::read(void* buffer, size_t length)
|
|||
|
||||
char *ptr = static_cast<char *>(buffer);
|
||||
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
api_lock();
|
||||
|
||||
while (_rxbuf.empty()) {
|
||||
|
|
|
@ -70,6 +70,12 @@ public:
|
|||
using FileHandle::writable;
|
||||
|
||||
/** Write the contents of a buffer to a file
|
||||
*
|
||||
* Follows POSIX semantics:
|
||||
*
|
||||
* * if blocking, block until all data is written
|
||||
* * if no data can be written, and non-blocking set, return -EAGAIN
|
||||
* * if some data can be written, and non-blocking set, write partial
|
||||
*
|
||||
* @param buffer The buffer to write from
|
||||
* @param length The number of bytes to write
|
||||
|
|
|
@ -105,7 +105,9 @@ nsapi_error_t TCPSocket::connect(const char *host, uint16_t port)
|
|||
nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
|
||||
{
|
||||
_lock.lock();
|
||||
const uint8_t *data_ptr = static_cast<const uint8_t *>(data);
|
||||
nsapi_size_or_error_t ret;
|
||||
nsapi_size_t written = 0;
|
||||
|
||||
// If this assert is hit then there are two threads
|
||||
// performing a send at the same time which is undefined
|
||||
|
@ -113,6 +115,9 @@ nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
|
|||
MBED_ASSERT(!_write_in_progress);
|
||||
_write_in_progress = true;
|
||||
|
||||
// Unlike recv, we should write the whole thing if blocking. POSIX only
|
||||
// allows partial as a side-effect of signal handling; it normally tries to
|
||||
// write everything if blocking. Without signals we can always write all.
|
||||
while (true) {
|
||||
if (!_socket) {
|
||||
ret = NSAPI_ERROR_NO_SOCKET;
|
||||
|
@ -120,10 +125,16 @@ nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
|
|||
}
|
||||
|
||||
_pending = 0;
|
||||
ret = _stack->socket_send(_socket, data, size);
|
||||
if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
|
||||
ret = _stack->socket_send(_socket, data_ptr + written, size - written);
|
||||
if (ret >= 0) {
|
||||
written += ret;
|
||||
if (written >= size) {
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
if (_timeout == 0) {
|
||||
break;
|
||||
} else if (ret == NSAPI_ERROR_WOULD_BLOCK) {
|
||||
uint32_t flag;
|
||||
|
||||
// Release lock before blocking so other threads
|
||||
|
@ -134,15 +145,22 @@ nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
|
|||
|
||||
if (flag & osFlagsError) {
|
||||
// Timeout break
|
||||
ret = NSAPI_ERROR_WOULD_BLOCK;
|
||||
break;
|
||||
}
|
||||
} else if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_write_in_progress = false;
|
||||
_lock.unlock();
|
||||
if (ret <= 0 && ret != NSAPI_ERROR_WOULD_BLOCK) {
|
||||
return ret;
|
||||
} else if (written == 0) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
} else {
|
||||
return written;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size)
|
||||
|
|
|
@ -88,9 +88,9 @@ public:
|
|||
* The socket must be connected to a remote host. Returns the number of
|
||||
* bytes sent from the buffer.
|
||||
*
|
||||
* By default, send blocks until data is sent. If socket is set to
|
||||
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
|
||||
* immediately.
|
||||
* By default, send blocks until all data is sent. If socket is set to
|
||||
* non-blocking or times out, a partial amount can be written.
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned if no data was written.
|
||||
*
|
||||
* @param data Buffer of data to send to the host
|
||||
* @param size Size of the buffer in bytes
|
||||
|
@ -104,9 +104,9 @@ public:
|
|||
* The socket must be connected to a remote host. Returns the number of
|
||||
* bytes received into the buffer.
|
||||
*
|
||||
* By default, recv blocks until data is sent. If socket is set to
|
||||
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
|
||||
* immediately.
|
||||
* By default, recv blocks until some data is received. If socket is set to
|
||||
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK can be returned to
|
||||
* indicate no data.
|
||||
*
|
||||
* @param data Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
* Devices acting as FileHandles should follow POSIX semantics:
|
||||
*
|
||||
* * if no data is available, and non-blocking set return -EAGAIN
|
||||
* * if no data is available, and blocking set, wait until data is available
|
||||
* * if no data is available, and blocking set, wait until some data is available
|
||||
* * If any data is available, call returns immediately
|
||||
*
|
||||
* @param buffer The buffer to read in to
|
||||
|
@ -61,6 +61,12 @@ public:
|
|||
virtual ssize_t read(void *buffer, size_t size) = 0;
|
||||
|
||||
/** Write the contents of a buffer to a file
|
||||
*
|
||||
* Devices acting as FileHandles should follow POSIX semantics:
|
||||
*
|
||||
* * if blocking, block until all data is written
|
||||
* * if no data can be written, and non-blocking set, return -EAGAIN
|
||||
* * if some data can be written, and non-blocking set, write partial
|
||||
*
|
||||
* @param buffer The buffer to write from
|
||||
* @param size The number of bytes to write
|
||||
|
|
Loading…
Reference in New Issue