mlyszczek commented on code in PR #6537: URL: https://github.com/apache/incubator-nuttx/pull/6537#discussion_r928636589
########## drivers/ipcc/ipcc_write.c: ########## @@ -0,0 +1,241 @@ +/**************************************************************************** + * drivers/ipcc/ipcc_write.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/ipcc.h> +#include <nuttx/kmalloc.h> +#include <nuttx/semaphore.h> + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <sys/types.h> + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipcc_txfree_notify + * + * Description: + * Notifies all blocked threads or those waiting in poll/select that + * there is place on buffer to perform writing. + * + * Input Parameters: + * ipcc - pointer to driver instance + * + * Returned Value: + * None + * + * Assumptions/Limitations: + * This function can be called from interrupt handler from lower half. + * + ****************************************************************************/ + +void ipcc_txfree_notify(FAR struct ipcc_lower_s *ipcc) +{ + int semval; + + if ((nxsem_get_value(&ipcc->txsem, &semval) == 0) && semval > 0) + { + /* Notify all poll/select waiters that they can write to the driver. + * Do it only when there are no already blocked writers to avoid + * situation where thread that is polling gets notified only to + * be blocked in write() because another thread have written to + * buffer before polling thread could. + */ + + ipcc_pollnotify(ipcc, POLLOUT); + return; + } + + /* Notify all blocked writers that data is available to write */ + + do + { + nxsem_post(&ipcc->txsem); + } + while (nxsem_get_value(&ipcc->txsem, &semval) == 0 && semval <= 0); +} + +/**************************************************************************** + * Name: ipcc_write + * + * Description: + * Writes data to IPCC memory so that another CPU can read the contents. + * Will block untill whole buffer is copied unless signal is received + * or O_NONBLOCK flag is set. + * + * Input Parameters: + * filep - file on vfs associated with the driver + * buffer - buffer to copy to IPCC memory + * buflen - size of the buffer... buffer + * + * Returned Value: + * Number of successfully written bytes into the IPCC memory or netagted + * errno when no data could be written. + * + * Assumptions/Limitations: + * + ****************************************************************************/ + +ssize_t ipcc_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct ipcc_driver_s *priv; + ssize_t nwritten; + int ret; + + /* Get our private data structure */ + + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + priv = filep->f_inode->i_private; + + /* Get exclusive access to driver */ + + if ((ret = nxsem_wait(&priv->exclsem))) + { + /* nxsem_wait() will return on signal, we did not start + * any transfer yet, so we can safely return with error + */ + + return ret; + } + + for (nwritten = 0; ; ) + { +#ifdef CONFIG_IPCC_BUFFERED + /* Buffered write, if buffer is empty try to write directly to + * IPCC memory, else buffer data in circbuf - it will be written + * in interrupt handler when IPCC tx channel is free. + */ + + if (circbuf_used(&priv->ipcc->txbuf) == 0) + { + /* Write buffer is empty, we can try and write data directly + * to IPCC memory thus omitting copying to buffer. + */ + + nwritten += priv->ipcc->ops.write(priv->ipcc, buffer + nwritten, + buflen - nwritten); + if (nwritten == (ssize_t)buflen || nwritten < 0) + { + /* We've managed to write whole buffer to IPCC memory, + * there is nothing else for use to do + * --or-- + * lower half driver returned error during write, + * + * either way we return with nwritten which will either + * be number of bytes written or negated errno. + */ + + nxsem_post(&priv->exclsem); + return nwritten; + } + } + + /* Either, there is already some data on the txbuffer, which + * means IPCC is occupied, or txbuffer is empty, but we could + * not write whole buffer to IPCC memory. In either case we + * copy what is left in data to buffer. + */ + + nwritten += circbuf_write(&priv->ipcc->txbuf, buffer + nwritten, + (ssize_t)buflen - nwritten); + + /* Notify lower half that new data on circ buffer is available */ + + priv->ipcc->ops.write_notify(priv->ipcc); + + if (nwritten == (ssize_t)buflen) + { + /* All outstanding data has been copied to txbuffer, we're done */ + + nxsem_post(&priv->exclsem); + return nwritten; + } + +#else /* CONFIG_IPCC_BUFFERED */ + /* Unbuffered write, write data directly to lower driver */ + + nwritten += priv->ipcc->ops.write(&priv->ipcc, buffer, buflen); Review Comment: You don't. IPCC write() can't really fail. IPCC uses only RAM and some registers to send data. These things cannot really fail, and if they do, then it's a critical hardware failure that I don't think we should care about. There is possibility that this will always return 0, but in that case second CPU simply does not consume data or never informs us that data has been read - it's a bug in IPCC implementation of second CPU. With that bug we can also hang in semaphore waiting for the interrupt. If user expects such situations, O_NONBLOCK then should be used. That said, that nwritten < 0 check is useless and I will remove it. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org