2011-03-15 21:26:34 +01:00
|
|
|
/****************************************************************************
|
2014-06-26 22:23:21 +02:00
|
|
|
* net/utils/net_lock.c
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
2021-02-19 12:45:37 +01:00
|
|
|
* 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
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
2021-02-19 12:45:37 +01:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
2021-02-19 12:45:37 +01:00
|
|
|
* 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.
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
2012-09-17 20:35:37 +02:00
|
|
|
#include <unistd.h>
|
2020-01-31 19:09:01 +01:00
|
|
|
#include <sched.h>
|
2011-03-15 21:26:34 +01:00
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <debug.h>
|
2020-01-04 11:37:46 +01:00
|
|
|
#include <time.h>
|
2011-03-15 21:26:34 +01:00
|
|
|
|
2016-02-14 15:38:44 +01:00
|
|
|
#include <nuttx/irq.h>
|
2020-01-04 11:37:46 +01:00
|
|
|
#include <nuttx/clock.h>
|
2017-10-05 15:24:54 +02:00
|
|
|
#include <nuttx/semaphore.h>
|
2022-03-21 23:47:09 +01:00
|
|
|
#include <nuttx/sched.h>
|
2018-07-07 16:26:13 +02:00
|
|
|
#include <nuttx/mm/iob.h>
|
2014-07-05 00:38:51 +02:00
|
|
|
#include <nuttx/net/net.h>
|
2011-03-15 21:26:34 +01:00
|
|
|
|
2014-06-26 22:23:21 +02:00
|
|
|
#include "utils/utils.h"
|
|
|
|
|
2011-03-15 21:26:34 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-03-21 23:47:09 +01:00
|
|
|
#define NO_HOLDER (INVALID_PROCESS_ID)
|
2011-03-15 21:26:34 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-09-06 08:18:45 +02:00
|
|
|
static rmutex_t g_netlock = NXRMUTEX_INITIALIZER;
|
2011-03-15 21:26:34 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-01-02 17:49:34 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: _net_timedwait
|
|
|
|
****************************************************************************/
|
2017-10-04 23:22:27 +02:00
|
|
|
|
2020-01-04 11:37:46 +01:00
|
|
|
static int
|
2020-02-23 09:50:23 +01:00
|
|
|
_net_timedwait(sem_t *sem, bool interruptible, unsigned int timeout)
|
2020-01-02 17:49:34 +01:00
|
|
|
{
|
|
|
|
unsigned int count;
|
|
|
|
irqstate_t flags;
|
|
|
|
int blresult;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
flags = enter_critical_section(); /* No interrupts */
|
|
|
|
sched_lock(); /* No context switches */
|
|
|
|
|
|
|
|
/* Release the network lock, remembering my count. net_breaklock will
|
|
|
|
* return a negated value if the caller does not hold the network lock.
|
|
|
|
*/
|
|
|
|
|
|
|
|
blresult = net_breaklock(&count);
|
|
|
|
|
|
|
|
/* Now take the semaphore, waiting if so requested. */
|
|
|
|
|
2020-01-04 11:37:46 +01:00
|
|
|
if (timeout != UINT_MAX)
|
2020-01-02 17:49:34 +01:00
|
|
|
{
|
|
|
|
/* Wait until we get the lock or until the timeout expires */
|
|
|
|
|
2020-02-23 09:50:23 +01:00
|
|
|
if (interruptible)
|
2020-01-02 17:49:34 +01:00
|
|
|
{
|
2022-05-10 03:32:31 +02:00
|
|
|
ret = nxsem_tickwait(sem, MSEC2TICK(timeout));
|
2020-01-02 17:49:34 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-05-10 03:32:31 +02:00
|
|
|
ret = nxsem_tickwait_uninterruptible(sem, MSEC2TICK(timeout));
|
2020-01-02 17:49:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2011-03-15 21:26:34 +01:00
|
|
|
{
|
2020-01-02 17:49:34 +01:00
|
|
|
/* Wait as long as necessary to get the lock */
|
2017-10-04 23:22:27 +02:00
|
|
|
|
2020-02-23 09:50:23 +01:00
|
|
|
if (interruptible)
|
2020-01-02 17:49:34 +01:00
|
|
|
{
|
|
|
|
ret = nxsem_wait(sem);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = nxsem_wait_uninterruptible(sem);
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 23:22:27 +02:00
|
|
|
|
2020-01-02 17:49:34 +01:00
|
|
|
/* Recover the network lock at the proper count (if we held it before) */
|
2011-03-15 21:26:34 +01:00
|
|
|
|
2020-01-02 17:49:34 +01:00
|
|
|
if (blresult >= 0)
|
|
|
|
{
|
|
|
|
net_restorelock(count);
|
2011-03-15 21:26:34 +01:00
|
|
|
}
|
2019-04-14 17:37:25 +02:00
|
|
|
|
2020-01-02 17:49:34 +01:00
|
|
|
sched_unlock();
|
|
|
|
leave_critical_section(flags);
|
2019-04-14 17:37:25 +02:00
|
|
|
return ret;
|
2011-03-15 21:26:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: net_lock
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2017-09-01 15:13:03 +02:00
|
|
|
* Take the network lock
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* None
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2019-04-14 17:37:25 +02:00
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* failured (probably -ECANCELED).
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2019-04-14 17:37:25 +02:00
|
|
|
int net_lock(void)
|
2011-03-15 21:26:34 +01:00
|
|
|
{
|
2022-09-06 08:18:45 +02:00
|
|
|
return nxrmutex_lock(&g_netlock);
|
2011-03-15 21:26:34 +01:00
|
|
|
}
|
|
|
|
|
2020-06-15 10:23:25 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: net_trylock
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Try to take the network lock only when it is currently not locked.
|
|
|
|
* Otherwise, it locks the semaphore. In either
|
|
|
|
* case, the call returns without blocking.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* failured (probably -EAGAIN).
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int net_trylock(void)
|
|
|
|
{
|
2022-09-06 08:18:45 +02:00
|
|
|
return nxrmutex_trylock(&g_netlock);
|
2020-06-15 10:23:25 +02:00
|
|
|
}
|
|
|
|
|
2011-03-15 21:26:34 +01:00
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: net_unlock
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2017-09-01 15:13:03 +02:00
|
|
|
* Release the network lock.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* None
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-09-01 15:13:03 +02:00
|
|
|
* None
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
void net_unlock(void)
|
2011-03-15 21:26:34 +01:00
|
|
|
{
|
2022-09-06 08:18:45 +02:00
|
|
|
nxrmutex_unlock(&g_netlock);
|
2011-03-15 21:26:34 +01:00
|
|
|
}
|
|
|
|
|
2018-07-07 03:49:05 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: net_breaklock
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Break the lock, return information needed to restore re-entrant lock
|
|
|
|
* state.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int net_breaklock(FAR unsigned int *count)
|
|
|
|
{
|
|
|
|
DEBUGASSERT(count != NULL);
|
2022-09-06 08:18:45 +02:00
|
|
|
return nxrmutex_breaklock(&g_netlock, count);
|
2018-07-07 03:49:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2019-04-14 17:37:25 +02:00
|
|
|
* Name: net_restorelock
|
2018-07-07 03:49:05 +02:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Restore the locked state
|
|
|
|
*
|
2019-04-14 17:37:25 +02:00
|
|
|
* Returned Value:
|
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* failured (probably -ECANCELED).
|
|
|
|
*
|
2018-07-07 03:49:05 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
2019-04-14 17:37:25 +02:00
|
|
|
int net_restorelock(unsigned int count)
|
2018-07-07 03:49:05 +02:00
|
|
|
{
|
2022-09-06 08:18:45 +02:00
|
|
|
return nxrmutex_restorelock(&g_netlock, count);
|
2018-07-07 03:49:05 +02:00
|
|
|
}
|
|
|
|
|
2011-03-15 21:26:34 +01:00
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: net_timedwait
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2021-01-15 10:01:00 +01:00
|
|
|
* Atomically wait for sem (or a timeout) while temporarily releasing
|
2015-02-09 14:50:10 +01:00
|
|
|
* the lock on the network.
|
2011-03-15 21:26:34 +01:00
|
|
|
*
|
2018-07-07 19:39:55 +02:00
|
|
|
* Caution should be utilized. Because the network lock is relinquished
|
2021-01-15 10:01:00 +01:00
|
|
|
* during the wait, there could be changes in the network state that occur
|
2018-07-07 19:39:55 +02:00
|
|
|
* before the lock is recovered. Your design should account for this
|
|
|
|
* possibility.
|
|
|
|
*
|
2015-01-22 13:51:31 +01:00
|
|
|
* Input Parameters:
|
2015-02-09 14:50:10 +01:00
|
|
|
* sem - A reference to the semaphore to be taken.
|
2020-01-04 11:37:46 +01:00
|
|
|
* timeout - The relative time to wait until a timeout is declared.
|
2015-01-22 13:51:31 +01:00
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-09-01 15:13:03 +02:00
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* any failure.
|
2015-01-22 13:51:31 +01:00
|
|
|
*
|
2011-03-15 21:26:34 +01:00
|
|
|
****************************************************************************/
|
|
|
|
|
2020-01-04 11:37:46 +01:00
|
|
|
int net_timedwait(sem_t *sem, unsigned int timeout)
|
2011-03-15 21:26:34 +01:00
|
|
|
{
|
2020-01-04 11:37:46 +01:00
|
|
|
return _net_timedwait(sem, true, timeout);
|
2015-02-09 14:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: net_lockedwait
|
2015-02-09 14:50:10 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2017-09-01 15:13:03 +02:00
|
|
|
* Atomically wait for sem while temporarily releasing the network lock.
|
2015-02-09 14:50:10 +01:00
|
|
|
*
|
2018-07-07 19:39:55 +02:00
|
|
|
* Caution should be utilized. Because the network lock is relinquished
|
2021-01-15 10:01:00 +01:00
|
|
|
* during the wait, there could be changes in the network state that occur
|
2018-07-07 19:39:55 +02:00
|
|
|
* before the lock is recovered. Your design should account for this
|
|
|
|
* possibility.
|
|
|
|
*
|
2015-02-09 14:50:10 +01:00
|
|
|
* Input Parameters:
|
|
|
|
* sem - A reference to the semaphore to be taken.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-09-01 15:13:03 +02:00
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* any failure.
|
2015-02-09 14:50:10 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int net_lockedwait(sem_t *sem)
|
|
|
|
{
|
2020-01-04 11:37:46 +01:00
|
|
|
return net_timedwait(sem, UINT_MAX);
|
2015-02-09 14:50:10 +01:00
|
|
|
}
|
2011-03-15 21:26:34 +01:00
|
|
|
|
2020-01-02 17:49:34 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: net_timedwait_uninterruptible
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is wrapped version of net_timedwait(), which is
|
|
|
|
* uninterruptible and convenient for use.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* sem - A reference to the semaphore to be taken.
|
2020-01-04 11:37:46 +01:00
|
|
|
* timeout - The relative time to wait until a timeout is declared.
|
2020-01-02 17:49:34 +01:00
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* any failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-01-04 11:37:46 +01:00
|
|
|
int net_timedwait_uninterruptible(sem_t *sem, unsigned int timeout)
|
2020-01-02 17:49:34 +01:00
|
|
|
{
|
2020-01-04 11:37:46 +01:00
|
|
|
return _net_timedwait(sem, false, timeout);
|
2020-01-02 17:49:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: net_lockedwait_uninterruptible
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is wrapped version of net_lockedwait(), which is
|
|
|
|
* uninterruptible and convenient for use.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* sem - A reference to the semaphore to be taken.
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* Zero (OK) is returned on success; a negated errno value is returned on
|
|
|
|
* any failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int net_lockedwait_uninterruptible(sem_t *sem)
|
|
|
|
{
|
2020-01-04 11:37:46 +01:00
|
|
|
return net_timedwait_uninterruptible(sem, UINT_MAX);
|
2020-01-02 17:49:34 +01:00
|
|
|
}
|
|
|
|
|
2022-02-17 05:42:35 +01:00
|
|
|
#ifdef CONFIG_MM_IOB
|
|
|
|
|
2018-07-07 16:26:13 +02:00
|
|
|
/****************************************************************************
|
2022-02-17 05:42:35 +01:00
|
|
|
* Name: net_timedalloc
|
2018-07-07 16:26:13 +02:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Allocate an IOB. If no IOBs are available, then atomically wait for
|
|
|
|
* for the IOB while temporarily releasing the lock on the network.
|
2022-05-10 03:32:31 +02:00
|
|
|
* This function is wrapped version of nxsem_tickwait(), this wait will
|
2022-02-17 05:42:35 +01:00
|
|
|
* be terminated when the specified timeout expires.
|
2018-07-07 16:26:13 +02:00
|
|
|
*
|
2018-07-07 19:39:55 +02:00
|
|
|
* Caution should be utilized. Because the network lock is relinquished
|
2021-01-15 10:01:00 +01:00
|
|
|
* during the wait, there could be changes in the network state that occur
|
2018-07-07 19:39:55 +02:00
|
|
|
* before the lock is recovered. Your design should account for this
|
|
|
|
* possibility.
|
|
|
|
*
|
2018-07-07 16:26:13 +02:00
|
|
|
* Input Parameters:
|
2022-02-17 05:42:35 +01:00
|
|
|
* throttled - An indication of the IOB allocation is "throttled"
|
|
|
|
* timeout - The relative time to wait until a timeout is declared.
|
2018-07-07 16:26:13 +02:00
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* A pointer to the newly allocated IOB is returned on success. NULL is
|
|
|
|
* returned on any allocation failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-08-08 04:21:03 +02:00
|
|
|
FAR struct iob_s *net_iobtimedalloc(bool throttled, unsigned int timeout)
|
2018-07-07 16:26:13 +02:00
|
|
|
{
|
|
|
|
FAR struct iob_s *iob;
|
|
|
|
|
2022-08-08 04:21:03 +02:00
|
|
|
iob = iob_tryalloc(throttled);
|
2022-02-17 05:42:35 +01:00
|
|
|
if (iob == NULL && timeout != 0)
|
2018-07-07 16:26:13 +02:00
|
|
|
{
|
|
|
|
unsigned int count;
|
|
|
|
int blresult;
|
|
|
|
|
|
|
|
/* There are no buffers available now. We will have to wait for one to
|
|
|
|
* become available. But let's not do that with the network locked.
|
|
|
|
*/
|
|
|
|
|
|
|
|
blresult = net_breaklock(&count);
|
2022-08-08 04:21:03 +02:00
|
|
|
iob = iob_timedalloc(throttled, timeout);
|
2018-07-07 16:26:13 +02:00
|
|
|
if (blresult >= 0)
|
|
|
|
{
|
|
|
|
net_restorelock(count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return iob;
|
|
|
|
}
|
2022-02-17 05:42:35 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: net_ioballoc
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Allocate an IOB. If no IOBs are available, then atomically wait for
|
|
|
|
* for the IOB while temporarily releasing the lock on the network.
|
|
|
|
*
|
|
|
|
* Caution should be utilized. Because the network lock is relinquished
|
|
|
|
* during the wait, there could be changes in the network state that occur
|
|
|
|
* before the lock is recovered. Your design should account for this
|
|
|
|
* possibility.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* throttled - An indication of the IOB allocation is "throttled"
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* A pointer to the newly allocated IOB is returned on success. NULL is
|
|
|
|
* returned on any allocation failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-08-08 04:21:03 +02:00
|
|
|
FAR struct iob_s *net_ioballoc(bool throttled)
|
2022-02-17 05:42:35 +01:00
|
|
|
{
|
2022-08-08 04:21:03 +02:00
|
|
|
return net_iobtimedalloc(throttled, UINT_MAX);
|
2022-02-17 05:42:35 +01:00
|
|
|
}
|
2018-07-07 16:26:13 +02:00
|
|
|
#endif
|