Skip to content

Commit c45e4ac

Browse files
hujun260xiaoxiang781216
authored andcommitted
boardcrtl: change BOARDCTL_TESTSET to BOARDIOC_SPINLOCK
reason: BOARDIOC_SPINLOCK can support the combined semantics of disabling interrupts (irq), trylock, and spinlock. Signed-off-by: hujun5 <[email protected]>
1 parent 659448a commit c45e4ac

File tree

5 files changed

+105
-64
lines changed

5 files changed

+105
-64
lines changed

boards/Kconfig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4815,12 +4815,11 @@ config BOARDCTL_USBDEVCTRL
48154815
---help---
48164816
Enables support for the BOARDIOC_USBDEV_CONTROL boardctl() command.
48174817

4818-
config BOARDCTL_TESTSET
4819-
bool "Architecture-specific test/set operation"
4818+
config BOARDCTL_SPINLOCK
4819+
bool "spinlock specific operation"
48204820
default n
48214821
---help---
48224822
Enables support for the BOARDIOC_SPINLOCK boardctl() command.
4823-
Architecture specific logic must provide up_testset() interface.
48244823

48254824
config BOARDCTL_IRQ_AFFINITY
48264825
bool "Set an IRQ affinity to CPUs by software"

boards/boardctl.c

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@
5353
# include <nuttx/usb/composite.h>
5454
#endif
5555

56-
#ifdef CONFIG_BOARDCTL_TESTSET
57-
# include <nuttx/spinlock.h>
58-
#endif
59-
6056
#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_BUILTIN)
6157
# include <nuttx/lib/builtin.h>
6258
#endif
@@ -344,7 +340,7 @@ static inline int boardctl_pmctrl(FAR struct boardioc_pm_ctrl_s *ctrl)
344340

345341
int boardctl(unsigned int cmd, uintptr_t arg)
346342
{
347-
int ret;
343+
int ret = OK;
348344

349345
switch (cmd)
350346
{
@@ -586,7 +582,6 @@ int boardctl(unsigned int cmd, uintptr_t arg)
586582

587583
DEBUGASSERT(symdesc != NULL);
588584
exec_setsymtab(symdesc->symtab, symdesc->nsymbols);
589-
ret = OK;
590585
}
591586
break;
592587
#endif
@@ -608,7 +603,6 @@ int boardctl(unsigned int cmd, uintptr_t arg)
608603

609604
DEBUGASSERT(symdesc != NULL);
610605
modlib_setsymtab(symdesc->symtab, symdesc->nsymbols);
611-
ret = OK;
612606
}
613607
break;
614608
#endif
@@ -643,7 +637,6 @@ int boardctl(unsigned int cmd, uintptr_t arg)
643637
DEBUGASSERT(builtin != NULL);
644638
builtin_setlist(builtin->builtins, builtin->count);
645639
#endif
646-
ret = OK;
647640
}
648641
break;
649642
#endif
@@ -789,27 +782,65 @@ int boardctl(unsigned int cmd, uintptr_t arg)
789782

790783
#endif /* CONFIG_NXTERM */
791784

792-
#ifdef CONFIG_BOARDCTL_TESTSET
793-
/* CMD: BOARDIOC_TESTSET
794-
* DESCRIPTION: Access architecture-specific up_testset() operation
795-
* ARG: A pointer to a write-able spinlock object. On
796-
* success the preceding spinlock state is returned:
797-
* 0=unlocked, 1=locked.
798-
* CONFIGURATION: CONFIG_BOARDCTL_TESTSET
799-
* DEPENDENCIES: Architecture-specific logic provides up_testset()
785+
#ifdef CONFIG_BOARDCTL_SPINLOCK
786+
/* CMD: BOARDIOC_SPINLOCK
787+
* DESCRIPTION: Access spinlock specific operation
788+
* ARG: A pointer to a write-able boardioc_spinlock_s
789+
* object.
790+
* CONFIGURATION: CONFIG_BOARDCTL_SPINLOCK
791+
* DEPENDENCIES: spinlock specific logic
800792
*/
801793

802-
case BOARDIOC_TESTSET:
794+
case BOARDIOC_SPINLOCK:
803795
{
804-
volatile FAR spinlock_t *lock = (volatile FAR spinlock_t *)arg;
796+
FAR struct boardioc_spinlock_s *spinlock =
797+
(FAR struct boardioc_spinlock_s *)arg;
798+
FAR volatile spinlock_t *lock = spinlock->lock;
799+
FAR irqstate_t *flags = spinlock->flags;
805800

806-
if (lock == NULL)
801+
if (spinlock->action == BOARDIOC_SPINLOCK_LOCK)
807802
{
808-
ret = -EINVAL;
803+
if (flags != NULL)
804+
{
805+
*flags = up_irq_save();
806+
}
807+
808+
if (lock != NULL)
809+
{
810+
spin_lock(lock);
811+
}
812+
}
813+
else if (spinlock->action == BOARDIOC_SPINLOCK_TRYLOCK)
814+
{
815+
if (flags != NULL)
816+
{
817+
*flags = up_irq_save();
818+
}
819+
820+
if (!spin_trylock(lock))
821+
{
822+
ret = -EBUSY;
823+
if (flags != NULL)
824+
{
825+
up_irq_restore(*flags);
826+
}
827+
}
828+
}
829+
else if (spinlock->action == BOARDIOC_SPINLOCK_UNLOCK)
830+
{
831+
if (flags != NULL)
832+
{
833+
up_irq_restore(*flags);
834+
}
835+
836+
if (lock != NULL)
837+
{
838+
spin_unlock(lock);
839+
}
809840
}
810841
else
811842
{
812-
ret = up_testset(lock) == SP_LOCKED ? 1 : 0;
843+
ret = -EINVAL;
813844
}
814845
}
815846
break;

include/sys/boardctl.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
# include <nuttx/nx/nxterm.h>
4343
#endif
4444

45+
#ifdef CONFIG_BOARDCTL_SPINLOCK
46+
# include <nuttx/spinlock.h>
47+
#endif
48+
4549
#ifdef CONFIG_BOARDCTL
4650

4751
/****************************************************************************
@@ -173,13 +177,12 @@
173177
* CONFIGURATION: CONFIG_NXTERM
174178
* DEPENDENCIES: Base NX terminal logic provides nxterm_ioctl_tap()
175179
*
176-
* CMD: BOARDIOC_TESTSET
177-
* DESCRIPTION: Access architecture-specific up_testset() operation
178-
* ARG: A pointer to a write-able spinlock object. On success
179-
* the preceding spinlock state is returned: 0=unlocked,
180-
* 1=locked.
181-
* CONFIGURATION: CONFIG_BOARDCTL_TESTSET
182-
* DEPENDENCIES: Architecture-specific logic provides up_testset()
180+
* CMD: BOARDIOC_SPINLOCK
181+
* DESCRIPTION: spinlock specific operation
182+
* ARG: A pointer to a write-able boardioc_spinlock_s
183+
*
184+
* CONFIGURATION: CONFIG_BOARDCTL_SPINLOCK
185+
* DEPENDENCIES: spinlock specific logic
183186
*
184187
* CMD: BOARDIOC_RESET_CAUSE
185188
* DESCRIPTION: Get the cause of last-time board reset
@@ -204,7 +207,7 @@
204207
#define BOARDIOC_VNC_START _BOARDIOC(0x000e)
205208
#define BOARDIOC_NXTERM _BOARDIOC(0x000f)
206209
#define BOARDIOC_NXTERM_IOCTL _BOARDIOC(0x0010)
207-
#define BOARDIOC_TESTSET _BOARDIOC(0x0011)
210+
#define BOARDIOC_SPINLOCK _BOARDIOC(0x0011)
208211
#define BOARDIOC_UNIQUEKEY _BOARDIOC(0x0012)
209212
#define BOARDIOC_SWITCH_BOOT _BOARDIOC(0x0013)
210213
#define BOARDIOC_BOOT_IMAGE _BOARDIOC(0x0014)
@@ -280,6 +283,22 @@ struct boardioc_romdisk_s
280283
};
281284
#endif
282285

286+
#ifdef CONFIG_BOARDCTL_SPINLOCK
287+
enum boardioc_spinlock_e
288+
{
289+
BOARDIOC_SPINLOCK_LOCK = 0, /* call up_irq_save or/and spin_lock */
290+
BOARDIOC_SPINLOCK_TRYLOCK = 1, /* call up_irq_save or/and spin_trylock */
291+
BOARDIOC_SPINLOCK_UNLOCK = 2, /* call up_irq_restore or/and spin_unlock */
292+
};
293+
294+
struct boardioc_spinlock_s
295+
{
296+
enum boardioc_spinlock_e action; /* see enum boardioc_spinlock_e */
297+
FAR irqstate_t *flags; /* whether we need to disable int */
298+
FAR volatile spinlock_t *lock; /* whether we need to call spinlock */
299+
};
300+
#endif
301+
283302
/* In order to full describe a symbol table, a vector containing the address
284303
* of the symbol table and the number of elements in the symbol table is
285304
* required.

libs/libc/pthread/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ config PTHREAD_SPINLOCKS
1010
bool "pthread spinlock support"
1111
default n
1212
depends on SPINLOCK && (BUILD_FLAT || BOARDCTL)
13-
select BOARDCTL_TESTSET if !BUILD_FLAT
13+
select BOARDCTL_SPINLOCK
1414
---help---
1515
Enable support for pthread spinlocks.
1616

libs/libc/pthread/pthread_spinlock.c

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ int pthread_spin_destroy(pthread_spinlock_t *lock)
163163

164164
int pthread_spin_lock(pthread_spinlock_t *lock)
165165
{
166+
struct boardioc_spinlock_s spinlock;
166167
pthread_t me = pthread_self();
167168
int ret;
168169

@@ -176,22 +177,10 @@ int pthread_spin_lock(pthread_spinlock_t *lock)
176177
return EDEADLOCK;
177178
}
178179

179-
/* Loop until we successfully take the spinlock (i.e., until the previous
180-
* state of the spinlock was SP_UNLOCKED).
181-
* NOTE that the test/set operation is performed via boardctl() to avoid a
182-
* variety of issues. An option might be to move the implementation of
183-
* up_testset() to libs/libc/machine.
184-
*/
185-
186-
do
187-
{
188-
#ifdef CONFIG_BUILD_FLAT
189-
ret = up_testset(&lock->sp_lock) == SP_LOCKED ? 1 : 0;
190-
#else
191-
ret = boardctl(BOARDIOC_TESTSET, (uintptr_t)&lock->sp_lock);
192-
#endif
193-
}
194-
while (ret == 1);
180+
spinlock.action = BOARDIOC_SPINLOCK_LOCK;
181+
spinlock.lock = &lock->sp_lock;
182+
spinlock.flags = NULL;
183+
ret = boardctl(BOARDIOC_SPINLOCK, (uintptr_t)&spinlock);
195184

196185
/* Check for success (previous state was SP_UNLOCKED) */
197186

@@ -233,6 +222,7 @@ int pthread_spin_lock(pthread_spinlock_t *lock)
233222

234223
int pthread_spin_trylock(pthread_spinlock_t *lock)
235224
{
225+
struct boardioc_spinlock_s spinlock;
236226
pthread_t me = pthread_self();
237227
int ret;
238228

@@ -249,21 +239,18 @@ int pthread_spin_trylock(pthread_spinlock_t *lock)
249239
{
250240
/* Perform the test/set operation via boardctl() */
251241

252-
ret = boardctl(BOARDIOC_TESTSET, (uintptr_t)&lock->sp_lock);
253-
switch (ret)
242+
spinlock.action = BOARDIOC_SPINLOCK_TRYLOCK;
243+
spinlock.lock = &lock->sp_lock;
244+
spinlock.flags = NULL;
245+
ret = boardctl(BOARDIOC_SPINLOCK, (uintptr_t)&spinlock);
246+
if (ret == 0) /* Previously unlocked. We hold the spinlock */
254247
{
255-
case 0: /* Previously unlocked. We hold the spinlock */
256-
lock->sp_holder = me;
257-
break;
258-
259-
case 1: /* Previously locked. We did not get the spinlock */
260-
ret = EBUSY;
261-
break;
262-
263-
default:
264-
DEBUGASSERT(ret < 0);
265-
ret = -ret;
266-
break;
248+
lock->sp_holder = me;
249+
}
250+
else /* Previously locked. We did not get the spinlock */
251+
{
252+
DEBUGASSERT(ret < 0);
253+
ret = -ret;
267254
}
268255
}
269256

@@ -301,6 +288,7 @@ int pthread_spin_trylock(pthread_spinlock_t *lock)
301288

302289
int pthread_spin_unlock(pthread_spinlock_t *lock)
303290
{
291+
struct boardioc_spinlock_s spinlock;
304292
pthread_t me = pthread_self();
305293

306294
DEBUGASSERT(lock != NULL &&
@@ -319,7 +307,11 @@ int pthread_spin_unlock(pthread_spinlock_t *lock)
319307
/* Release the lock */
320308

321309
lock->sp_holder = IMPOSSIBLE_THREAD;
322-
spin_initialize(&lock->sp_lock, SP_UNLOCKED);
310+
spinlock.action = BOARDIOC_SPINLOCK_UNLOCK;
311+
spinlock.lock = &lock->sp_lock;
312+
spinlock.flags = NULL;
313+
boardctl(BOARDIOC_SPINLOCK, (uintptr_t)&spinlock);
314+
323315
return OK;
324316
}
325317

0 commit comments

Comments
 (0)