diff --git a/include/nanokernel.h b/include/nanokernel.h index 0bd17044507..68462c32978 100644 --- a/include/nanokernel.h +++ b/include/nanokernel.h @@ -618,27 +618,224 @@ struct nano_sem { int nsig; }; +/** + * + * @brief Initialize a nanokernel semaphore object + * + * This function initializes a nanokernel semaphore object structure. After + * initialization, the semaphore count will be 0. + * + * It may be called from either a fiber or task context. + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_sem_init(struct nano_sem *chan); + /* scheduling context independent methods (when context is not known) */ + +/** + * + * @brief Give a nanokernel semaphore + * + * This is a convenience wrapper for the context-specific APIs. This is + * helpful whenever the exact scheduling context is not known, but should + * be avoided when the context is known up-front (to avoid unnecessary + * overhead). + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_sem_give(struct nano_sem *chan); + +/** + * + * @brief Take a nanokernel semaphore, poll/pend if not available + * + * This is a convenience wrapper for the context-specific APIs. This is + * helpful whenever the exact scheduling context is not known, but should + * be avoided when the context is known up-front (to avoid unnecessary + * overhead). + * + * It's only valid to call this API from a fiber or a task. + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_sem_take_wait(struct nano_sem *chan); + /* methods for ISRs */ + +/** + * + * @brief Give a nanokernel semaphore (no context switch) + * + * This routine performs a "give" operation on a nanokernel sempahore object; + * it may be call from an ISR context. A fiber pending on + * the semaphore object will be made ready, but will NOT be scheduled to + * execute. + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_isr_sem_give(struct nano_sem *chan); + +/** + * + * @brief Take a nanokernel semaphore, fail if unavailable + * + * Attempt to take a nanokernel sempahore; it may be called from a + * ISR context. + * + * If the semaphore is not available, this function returns immediately, i.e. + * a wait (pend) operation will NOT be performed. + * + * @param chan Pointer to a nano_sem structure. + * + * @return 1 if semaphore is available, 0 otherwise + */ extern int nano_isr_sem_take(struct nano_sem *chan); + /* methods for fibers */ + +/** + * + * @brief Give a nanokernel semaphore (no context switch) + * + * This routine performs a "give" operation on a nanokernel sempahore object; + * it may be call from a fiber context. A fiber pending on + * the semaphore object will be made ready, but will NOT be scheduled to + * execute. + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_fiber_sem_give(struct nano_sem *chan); + +/** + * + * @brief Take a nanokernel semaphore, fail if unavailable + * + * Attempt to take a nanokernel sempahore; it may be called from a fiber + * context. + * + * If the semaphore is not available, this function returns immediately, i.e. + * a wait (pend) operation will NOT be performed. + * + * @param chan Pointer to a nano_sem structure. + * + * @return 1 if semaphore is available, 0 otherwise + */ extern int nano_fiber_sem_take(struct nano_sem *chan); + +/** + * + * @brief Test a nanokernel semaphore, wait if unavailable + * + * Take a nanokernel sempahore; it can only be called from a fiber context. + * + * If the nanokernel semaphore is not available, i.e. the event counter + * is 0, the calling fiber context will wait (pend) until the semaphore is + * given (via nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_fiber_sem_take_wait(struct nano_sem *chan); #ifdef CONFIG_NANO_TIMEOUTS + +/** + * @brief test a nanokernel semaphore, wait with a timeout if unavailable + * + * Take a nanokernel sempahore; it can only be called from a fiber context. + * + * If the nanokernel semaphore is not available, i.e. the event counter + * is 0, the calling fiber context will wait (pend) until the semaphore is + * given (via nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). A + * timeout can be specified. + * + * @param sem the semaphore to take + * @param timeout_in_ticks time to wait in ticks + * + * @param chan Pointer to a nano_sem structure. + * + * @return 1 if semaphore is available, 0 if timed out + */ extern int nano_fiber_sem_take_wait_timeout(struct nano_sem *chan, int32_t timeout); #endif /* methods for tasks */ + +/** + * + * @brief Give a nanokernel semaphore + * + * This routine performs a "give" operation on a nanokernel sempahore object; + * it can only be called from a task context. A fiber pending on the + * semaphore object will be made ready, and will preempt the running task + * immediately. + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_task_sem_give(struct nano_sem *chan); + +/** + * + * @brief Take a nanokernel semaphore, fail if unavailable + * + * Attempt to take a nanokernel sempahore; it may be called from a task + * context. + * + * If the semaphore is not available, this function returns immediately, i.e. + * a wait (pend) operation will NOT be performed. + * + * @param chan Pointer to a nano_sem structure. + * + * @return 1 if semaphore is available, 0 otherwise + */ extern int nano_task_sem_take(struct nano_sem *chan); + +/** + * + * @brief Take a nanokernel semaphore, poll if unavailable + * + * Take a nanokernel sempahore; it can only be called from a task context. + * + * If the nanokernel semaphore is not available, i.e. the event counter + * is 0, the calling task will poll until the semaphore is given + * (via nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). + * + * @param chan Pointer to a nano_sem structure. + * + * @return N/A + */ extern void nano_task_sem_take_wait(struct nano_sem *chan); #ifdef CONFIG_NANO_TIMEOUTS + +/** + * @brief test a nanokernel semaphore, poll with a timeout if unavailable + * + * Take a nanokernel sempahore; it can only be called from a task context. + * + * If the nanokernel semaphore is not available, i.e. the event counter is 0, + * the calling task will poll until the semaphore is given (via + * nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). A timeout can be + * specified. + * + * @param chan the semaphore to take + * @param timeout time to wait in ticks + * + * @return 1 if semaphore is available, 0 if timed out + */ extern int nano_task_sem_take_wait_timeout(struct nano_sem *chan, int32_t timeout); #endif diff --git a/kernel/nanokernel/nano_sema.c b/kernel/nanokernel/nano_sema.c index ed1616c493f..a2b79230a20 100644 --- a/kernel/nanokernel/nano_sema.c +++ b/kernel/nanokernel/nano_sema.c @@ -1,5 +1,3 @@ -/* nanokernel semaphore object */ - /* * Copyright (c) 2010-2015 Wind River Systems, Inc. * @@ -30,25 +28,30 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* -DESCRIPTION -This module provides the nanokernel semaphore object implementation, -including the following APIs: +/** + * @file + * + * @brief Nanokernel semaphore object. + * + * This module provides the nanokernel semaphore object implementation, + * including the following APIs: + * + * nano_sem_init + * nano_fiber_sem_give, nano_task_sem_give, nano_isr_sem_give + * nano_fiber_sem_take, nano_task_sem_take, nano_isr_sem_take + * nano_fiber_sem_take_wait, nano_task_sem_take_wait - nano_sem_init - nano_fiber_sem_give, nano_task_sem_give, nano_isr_sem_give - nano_fiber_sem_take, nano_task_sem_take, nano_isr_sem_take - nano_fiber_sem_take_wait, nano_task_sem_take_wait + * The semaphores are of the 'counting' type, i.e. each 'give' operation will + * increment the internal count by 1, if no context is pending on it. The 'init' + * call initializes the count to 0. Following multiple 'give' operations, the + * same number of 'take' operations can be performed without the calling context + * having to pend on the semaphore. + */ -The semaphores are of the 'counting' type, i.e. each 'give' operation will -increment the internal count by 1, if no context is pending on it. The 'init' -call initializes the count to 0. Following multiple 'give' operations, the -same number of 'take' operations can be performed without the calling context -having to pend on the semaphore. - -INTERNAL -In some cases the compiler "alias" attribute is used to map two or more -APIs to the same function, since they have identical implementations. +/** + * INTERNAL + * In some cases the compiler "alias" attribute is used to map two or more + * APIs to the same function, since they have identical implementations. */ #include @@ -57,25 +60,12 @@ APIs to the same function, since they have identical implementations. #include /** - * - * @brief Initialize a nanokernel semaphore object - * - * This function initializes a nanokernel semaphore object structure. After - * initialization, the semaphore count will be 0. - * - * It may be called from either a fiber or task context. - * - * @return N/A - * * INTERNAL * Although the existing implementation will support invocation from an ISR * context, for future flexibility, this API will be restricted from ISR * level invocation. */ - -void nano_sem_init( - struct nano_sem *sem /* semaphore object to initialize */ - ) +void nano_sem_init(struct nano_sem *sem) { sem->nsig = 0; _nano_wait_q_init(&sem->wait_q); @@ -91,26 +81,13 @@ FUNC_ALIAS(_sem_give_non_preemptible, nano_fiber_sem_give, void); #endif /** - * - * @brief Give a nanokernel semaphore (no context switch) - * - * This routine performs a "give" operation on a nanokernel sempahore object; - * it may be call from either a fiber or an ISR context. A fiber pending on - * the semaphore object will be made ready, but will NOT be scheduled to - * execute. - * - * @return N/A - * * INTERNAL * This function is capable of supporting invocations from both a fiber and an * ISR context. However, the nano_isr_sem_give and nano_fiber_sem_give aliases * are created to support any required implementation differences in the future * without introducing a source code migration issue. */ - -void _sem_give_non_preemptible( - struct nano_sem *sem /* semaphore on which to signal */ - ) +void _sem_give_non_preemptible(struct nano_sem *sem) { tCCS *ccs; unsigned int imask; @@ -127,21 +104,7 @@ void _sem_give_non_preemptible( irq_unlock_inline(imask); } -/** - * - * @brief Give a nanokernel semaphore - * - * This routine performs a "give" operation on a nanokernel sempahore object; - * it can only be called from a task context. A fiber pending on the - * semaphore object will be made ready, and will preempt the running task - * immediately. - * - * @return N/A - */ - -void nano_task_sem_give( - struct nano_sem *sem /* semaphore on which to signal */ - ) +void nano_task_sem_give(struct nano_sem *sem) { tCCS *ccs; unsigned int imask; @@ -160,16 +123,6 @@ void nano_task_sem_give( irq_unlock_inline(imask); } -/** - * - * @brief Give a nanokernel semaphore - * - * This is a convenience wrapper for the context-specific APIs. This is - * helpful whenever the exact scheduling context is not known, but should - * be avoided when the context is known up-front (to avoid unnecessary - * overhead). - */ - void nano_sem_give(struct nano_sem *sem) { static void (*func[3])(struct nano_sem *sem) = { @@ -182,21 +135,8 @@ FUNC_ALIAS(_sem_take, nano_isr_sem_take, int); FUNC_ALIAS(_sem_take, nano_fiber_sem_take, int); FUNC_ALIAS(_sem_take, nano_task_sem_take, int); -/** - * - * @brief Take a nanokernel semaphore, fail if unavailable - * - * Attempt to take a nanokernel sempahore; it may be called from a fiber, task, - * or ISR context. - * - * If the semaphore is not available, this function returns immediately, i.e. - * a wait (pend) operation will NOT be performed. - * - * @return 1 if semaphore is available, 0 otherwise - */ - int _sem_take( - struct nano_sem *sem /* semaphore on which to test */ + struct nano_sem *sem ) { unsigned int imask; @@ -211,26 +151,12 @@ int _sem_take( } /** - * - * @brief Test a nanokernel semaphore, wait if unavailable - * - * Take a nanokernel sempahore; it can only be called from a fiber context. - * - * If the nanokernel semaphore is not available, i.e. the event counter - * is 0, the calling fiber context will wait (pend) until the semaphore is - * given (via nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). - * - * @return N/A - * * INTERNAL * There exists a separate nano_task_sem_take_wait() implementation since a task * context cannot pend on a nanokernel object. Instead, tasks will poll * the sempahore object. */ - -void nano_fiber_sem_take_wait( - struct nano_sem *sem /* semaphore on which to wait */ - ) +void nano_fiber_sem_take_wait(struct nano_sem *sem) { unsigned int imask; @@ -244,22 +170,7 @@ void nano_fiber_sem_take_wait( } } -/** - * - * @brief Take a nanokernel semaphore, poll if unavailable - * - * Take a nanokernel sempahore; it can only be called from a task context. - * - * If the nanokernel semaphore is not available, i.e. the event counter - * is 0, the calling task will poll until the semaphore is given - * (via nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). - * - * @return N/A - */ - -void nano_task_sem_take_wait( - struct nano_sem *sem /* semaphore on which to wait */ - ) +void nano_task_sem_take_wait(struct nano_sem *sem) { unsigned int imask; @@ -285,17 +196,6 @@ void nano_task_sem_take_wait( irq_unlock_inline(imask); } -/** - * - * @brief Take a nanokernel semaphore, poll/pend if not available - * - * This is a convenience wrapper for the context-specific APIs. This is - * helpful whenever the exact scheduling context is not known, but should - * be avoided when the context is known up-front (to avoid unnecessary - * overhead). - * - * It's only valid to call this API from a fiber or a task. - */ void nano_sem_take_wait(struct nano_sem *sem) { static void (*func[3])(struct nano_sem *sem) = { @@ -305,24 +205,8 @@ void nano_sem_take_wait(struct nano_sem *sem) } #ifdef CONFIG_NANO_TIMEOUTS -/** - * @brief test a nanokernel semaphore, wait with a timeout if unavailable - * - * Take a nanokernel sempahore; it can only be called from a fiber context. - * - * If the nanokernel semaphore is not available, i.e. the event counter - * is 0, the calling fiber context will wait (pend) until the semaphore is - * given (via nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). A - * timeout can be specified. - * - * @param sem the semaphore to take - * @param timeout_in_ticks time to wait in ticks - * - * @return 1 if semaphore is available, 0 if timed out - */ -int nano_fiber_sem_take_wait_timeout(struct nano_sem *sem, - int32_t timeout_in_ticks) +int nano_fiber_sem_take_wait_timeout(struct nano_sem *sem, int32_t timeout_in_ticks) { unsigned int key = irq_lock_inline(); @@ -346,24 +230,7 @@ int nano_fiber_sem_take_wait_timeout(struct nano_sem *sem, return 1; } -/** - * @brief test a nanokernel semaphore, poll with a timeout if unavailable - * - * Take a nanokernel sempahore; it can only be called from a task context. - * - * If the nanokernel semaphore is not available, i.e. the event counter is 0, - * the calling task will poll until the semaphore is given (via - * nano_fiber_sem_give/nano_task_sem_give/nano_isr_sem_give). A timeout can be - * specified. - * - * @param sem the semaphore to take - * @param timeout time to wait in ticks - * - * @return 1 if semaphore is available, 0 if timed out - */ - -int nano_task_sem_take_wait_timeout(struct nano_sem *sem, - int32_t timeout_in_ticks) +int nano_task_sem_take_wait_timeout(struct nano_sem *sem, int32_t timeout_in_ticks) { int64_t cur_ticks, limit; unsigned int key;