From e23933a0042cd306c844dc6a4df11c6d5d33d8ed Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 1 Aug 2015 07:30:23 -0600 Subject: [PATCH] sem_tickwait(): Add a new, non-standard function to perform timed semaphore waits. It is functionally equialent to the standard sem_timedwait(), but more efficient for use in higher performance device drivers. Requested by Max Nekyudov --- ChangeLog | 3 + include/nuttx/semaphore.h | 25 ++++++- sched/semaphore/Make.defs | 7 +- sched/semaphore/sem_initialize.c | 21 +----- sched/semaphore/sem_timedwait.c | 110 ++++--------------------------- sched/semaphore/sem_waitirq.c | 20 ------ sched/semaphore/semaphore.h | 8 ++- 7 files changed, 50 insertions(+), 144 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9dddf346c3..4d8c6feddf 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10776,4 +10776,7 @@ Based comments from Anton D. Kachalov (2015-07-29). * STM32 F4: Add DMA support to the ADC driver for STM32 F4. From Max Kriegler (2015-07-30). + * sem_tickwait(): Added this furnction for internaluse within the + OS. It is a non-standard but more efficient version of sem_timedwait() + for use in higher performance device drviers (2015-08-01). diff --git a/include/nuttx/semaphore.h b/include/nuttx/semaphore.h index 33e701cc80..a7ed6d5804 100644 --- a/include/nuttx/semaphore.h +++ b/include/nuttx/semaphore.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/semaphore.h * - * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ ****************************************************************************/ /**************************************************************************** - * Public Data + * Public Type Definitions ****************************************************************************/ #ifdef CONFIG_FS_NAMED_SEMAPHORES @@ -64,7 +64,6 @@ struct nsem_inode_s FAR struct inode *ns_inode; /* Containing inode */ sem_t ns_sem; /* The semaphore */ - }; #endif @@ -86,6 +85,26 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: sem_tickwait + * + * Description: + * This function is a lighter weight version of sem_timedwait(). It is + * non-standard and intended only for use within the RTOS. + * + * Parameters: + * sem - Semaphore object + * ticks - Ticks to wait until the semaphore is posted. If ticks is + * zero, then this function is equivalent to sem_trywait(). + * + * Return Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. -ETIMEDOUT is returned on the timeout condition. + * + ****************************************************************************/ + +int sem_tickwait(FAR sem_t *sem, uint32_t ticks); + #undef EXTERN #ifdef __cplusplus } diff --git a/sched/semaphore/Make.defs b/sched/semaphore/Make.defs index 44b7e21d06..53b6a540ef 100644 --- a/sched/semaphore/Make.defs +++ b/sched/semaphore/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # sched/semaphore/Make.defs # -# Copyright (C) 2014 Gregory Nutt. All rights reserved. +# Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -33,8 +33,9 @@ # ############################################################################ -CSRCS += sem_destroy.c sem_wait.c sem_trywait.c sem_timedwait.c -CSRCS += sem_post.c sem_recover.c sem_waitirq.c +CSRCS += sem_destroy.c sem_wait.c sem_trywait.c sem_tickwait.c +CSRCS += sem_timedwait.c sem_timeout.c sem_post.c sem_recover.c +CSRCS += sem_waitirq.c ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) CSRCS += sem_initialize.c sem_holder.c diff --git a/sched/semaphore/sem_initialize.c b/sched/semaphore/sem_initialize.c index 2468da1db1..d91a8602fe 100644 --- a/sched/semaphore/sem_initialize.c +++ b/sched/semaphore/sem_initialize.c @@ -45,26 +45,6 @@ #ifdef CONFIG_PRIORITY_INHERITANCE -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Global Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -83,6 +63,7 @@ * None * * Assumptions: + * Called once during OS startup initialization * ****************************************************************************/ diff --git a/sched/semaphore/sem_timedwait.c b/sched/semaphore/sem_timedwait.c index a73e278051..503aed2322 100644 --- a/sched/semaphore/sem_timedwait.c +++ b/sched/semaphore/sem_timedwait.c @@ -53,75 +53,6 @@ #include "clock/clock.h" #include "semaphore/semaphore.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Global Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sem_timeout - * - * Description: - * This function is called if the timeout elapses before the message queue - * becomes non-empty. - * - * Parameters: - * argc - the number of arguments (should be 1) - * pid - the task ID of the task to wakeup - * - * Return Value: - * None - * - * Assumptions: - * - ****************************************************************************/ - -static void sem_timeout(int argc, wdparm_t pid) -{ - FAR struct tcb_s *wtcb; - irqstate_t flags; - - /* Disable interrupts to avoid race conditions */ - - flags = irqsave(); - - /* Get the TCB associated with this pid. It is possible that - * task may no longer be active when this watchdog goes off. - */ - - wtcb = sched_gettcb((pid_t)pid); - - /* It is also possible that an interrupt/context switch beat us to the - * punch and already changed the task's state. - */ - - if (wtcb && wtcb->task_state == TSTATE_WAIT_SEM) - { - /* Cancel the semaphore wait */ - - sem_waitirq(wtcb, ETIMEDOUT); - } - - /* Interrupts may now be enabled. */ - - irqrestore(flags); -} - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -147,9 +78,8 @@ static void sem_timeout(int argc, wdparm_t pid) * abstime - The absolute time to wait until a timeout is declared. * * Return Value: - * One success, the length of the selected message in bytes is - * returned. On failure, -1 (ERROR) is returned and the errno - * is set appropriately: + * Zero (OK) is returned on success. On failure, -1 (ERROR) is returned + * and the errno is set appropriately: * * EINVAL The sem argument does not refer to a valid semaphore. Or the * thread would have blocked, and the abstime parameter specified @@ -213,10 +143,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) { /* We got it! */ - irqrestore(flags); - wd_delete(rtcb->waitdog); - rtcb->waitdog = NULL; - return OK; + goto success_with_irqdisabled; } /* We will have to wait for the semaphore. Make sure that we were provided @@ -226,7 +153,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { errcode = EINVAL; - goto errout_disabled; + goto errout_with_irqdisabled; } /* Convert the timespec to clock ticks. We must have interrupts @@ -240,20 +167,20 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) if (errcode == OK && ticks <= 0) { errcode = ETIMEDOUT; - goto errout_disabled; + goto errout_with_irqdisabled; } /* Handle any time-related errors */ if (errcode != OK) { - goto errout_disabled; + goto errout_with_irqdisabled; } /* Start the watchdog */ errcode = OK; - wd_start(rtcb->waitdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); + (void)wd_start(rtcb->waitdog, ticks, (wdentry_t)sem_timeout, 1, getpid()); /* Now perform the blocking wait */ @@ -271,28 +198,17 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime) /* We can now restore interrupts and delete the watchdog */ + /* Success exits */ + +success_with_irqdisabled: irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; + return OK; - /* We are either returning success or an error detected by sem_wait() - * or the timeout detected by sem_timeout(). The 'errno' value has - * been set appropriately by sem_wait() or sem_timeout() in those - * cases. - */ + /* Error exits */ - if (ret < 0) - { - /* On failure, restore the errno value returned by sem_wait */ - - set_errno(errcode); - } - - return ret; - -/* Error exits */ - -errout_disabled: +errout_with_irqdisabled: irqrestore(flags); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; diff --git a/sched/semaphore/sem_waitirq.c b/sched/semaphore/sem_waitirq.c index 5e9298f396..e80ef66cd7 100644 --- a/sched/semaphore/sem_waitirq.c +++ b/sched/semaphore/sem_waitirq.c @@ -45,26 +45,6 @@ #include "semaphore/semaphore.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Global Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Variables - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/sched/semaphore/semaphore.h b/sched/semaphore/semaphore.h index d5764347a4..e40141c9cb 100644 --- a/sched/semaphore/semaphore.h +++ b/sched/semaphore/semaphore.h @@ -1,7 +1,7 @@ /**************************************************************************** * sched/semaphore/semaphore.h * - * Copyright (C) 2007, 2009-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -81,8 +81,14 @@ void sem_initialize(void); # define sem_initialize() #endif +/* Wake up a thread that is waiting on semaphore */ + void sem_waitirq(FAR struct tcb_s *wtcb, int errcode); +/* Handle semaphore timer expiration */ + +void sem_timeout(int argc, wdparm_t pid); + /* Recover semaphore resources with a task or thread is destroyed */ void sem_recover(FAR struct tcb_s *tcb);