Threads queues completed in NIL.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10155 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2017-04-11 11:08:36 +00:00
parent ca129dc5b4
commit 477baaed5a
6 changed files with 178 additions and 132 deletions

View File

@ -34,8 +34,8 @@
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/> <stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/> <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList/&gt;"/> <stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList/&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;globalVariableList/&gt;&#13;&#10;"/> <stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;globalVariableList/&gt;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList/&gt;&#13;&#10;"/> <stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList/&gt;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/> <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="NIL-STM32F303-DISCOVERY"/> <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="NIL-STM32F303-DISCOVERY"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/> <booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>

View File

@ -48,68 +48,4 @@
/* Module exported functions. */ /* Module exported functions. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @brief Dequeues and wakes up one thread from the queue, if any.
*
* @param[in] tqp pointer to the threads queue object
* @param[in] msg the message code
*
* @iclass
*/
void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
semaphore_t *sp = &tqp->sem;
if (chSemGetCounterI(&tqp->sem) < (cnt_t)0) {
thread_t *tp = nil.threads;
while (true) {
/* Is this thread waiting on this semaphore?*/
if (tp->u1.semp == sp) {
sp->cnt++;
chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting");
(void) chSchReadyI(tp, msg);
return;
}
tp++;
chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
"pointer out of range");
}
}
}
/**
* @brief Dequeues and wakes up all threads from the queue.
*
* @param[in] tqp pointer to the threads queue object
* @param[in] msg the message code
*
* @iclass
*/
void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
semaphore_t *sp = &tqp->sem;
thread_t *tp;
cnt_t cnt;
cnt = sp->cnt;
sp->cnt = (cnt_t)0;
tp = nil.threads;
while (cnt < (cnt_t)0) {
chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
"pointer out of range");
/* Is this thread waiting on this semaphore?*/
if (tp->u1.semp == sp) {
chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting");
cnt++;
(void) chSchReadyI(tp, msg);
}
tp++;
}
}
/** @} */ /** @} */

View File

@ -219,6 +219,8 @@ struct event_source {
*/ */
typedef semaphore_t mutex_t; typedef semaphore_t mutex_t;
#if 0
/** /**
* @brief Type of a thread queue. * @brief Type of a thread queue.
* @details A thread queue is a queue of sleeping threads, queued threads * @details A thread queue is a queue of sleeping threads, queued threads
@ -227,8 +229,9 @@ typedef semaphore_t mutex_t;
* because there are no real threads. * because there are no real threads.
*/ */
typedef struct { typedef struct {
semaphore_t sem; thread_reference_t tr;
} threads_queue_t; } threads_queue_t;
#endif
/*===========================================================================*/ /*===========================================================================*/
/* Module macros. */ /* Module macros. */
@ -444,8 +447,7 @@ typedef struct {
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg);
void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -766,7 +768,7 @@ static inline void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {
*/ */
static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) { static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
chSemObjectInit(&tqp->sem, (cnt_t)0); chThdQueueObjectInit(tqp);
} }
/** /**
@ -795,7 +797,33 @@ static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
static inline msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, static inline msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp,
systime_t time) { systime_t time) {
return chSemWaitTimeoutS(&tqp->sem, time); return chThdEnqueueTimeoutS(tqp, time);
}
/**
* @brief Dequeues and wakes up one thread from the queue, if any.
*
* @param[in] tqp pointer to the threads queue object
* @param[in] msg the message code
*
* @iclass
*/
static inline void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
chThdDequeueNextI(tqp, msg);
}
/**
* @brief Dequeues and wakes up all threads from the queue.
*
* @param[in] tqp pointer to the threads queue object
* @param[in] msg the message code
*
* @iclass
*/
static inline void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
chThdDequeueAllI(tqp, msg);
} }
/** /**

View File

@ -534,6 +534,9 @@ struct nil_thread {
void *p; /**< @brief Generic pointer. */ void *p; /**< @brief Generic pointer. */
thread_reference_t *trp; /**< @brief Pointer to thread reference.*/ thread_reference_t *trp; /**< @brief Pointer to thread reference.*/
threads_queue_t *tqp; /**< @brief Pointer to thread queue. */ threads_queue_t *tqp; /**< @brief Pointer to thread queue. */
#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
semaphore_t *semp; /**< @brief Pointer to semaphore. */
#endif
#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) #if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
eventmask_t ewmask; /**< @brief Enabled events mask. */ eventmask_t ewmask; /**< @brief Enabled events mask. */
#endif #endif
@ -911,6 +914,29 @@ struct nil_system {
#define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec)) #define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
/** @} */ /** @} */
/**
* @name Threads queues
*/
/**
* @brief Data part of a static threads queue object initializer.
* @details This macro should be used when statically initializing a threads
* queue that is part of a bigger structure.
*
* @param[in] name the name of the threads queue variable
*/
#define _THREADS_QUEUE_DATA(name) {(cnt_t)0}
/**
* @brief Static threads queue object initializer.
* @details Statically initialized threads queues require no explicit
* initialization using @p queue_init().
*
* @param[in] name the name of the threads queue variable
*/
#define _THREADS_QUEUE_DECL(name) \
threads_queue_t name = _THREADS_QUEUE_DATA(name)
/** @} */
/** /**
* @name Semaphores macros * @name Semaphores macros
* @{ * @{
@ -1367,6 +1393,7 @@ extern "C" {
void chThdResumeI(thread_reference_t *trp, msg_t msg); void chThdResumeI(thread_reference_t *trp, msg_t msg);
void chThdSleep(systime_t timeout); void chThdSleep(systime_t timeout);
void chThdSleepUntil(systime_t abstime); void chThdSleepUntil(systime_t abstime);
msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout);
void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg); void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg);
void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg); void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg); void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);

View File

@ -757,6 +757,45 @@ void chThdSleepUntil(systime_t abstime) {
chSysUnlock(); chSysUnlock();
} }
/**
* @brief Enqueues the caller thread on a threads queue object.
* @details The caller thread is enqueued and put to sleep until it is
* dequeued or the specified timeouts expires.
*
* @param[in] tqp pointer to the threads queue object
* @param[in] timeout the timeout in system ticks, the special values are
* handled as follow:
* - @a TIME_INFINITE the thread enters an infinite sleep
* state.
* - @a TIME_IMMEDIATE the thread is not enqueued and
* the function returns @p MSG_TIMEOUT as if a timeout
* occurred.
* .
* @return The message from @p osalQueueWakeupOneI() or
* @p osalQueueWakeupAllI() functions.
* @retval MSG_TIMEOUT if the thread has not been dequeued within the
* specified timeout or if the function has been
* invoked with @p TIME_IMMEDIATE as timeout
* specification.
*
* @sclass
*/
msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout) {
chDbgCheckClassS();
chDbgCheck(tqp != NULL);
chDbgAssert(tqp->cnt <= (cnt_t)0, "invalid counter");
if (TIME_IMMEDIATE == timeout) {
return MSG_TIMEOUT;
}
tqp->cnt--;
nil.current->u1.tqp = tqp;
return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
}
/** /**
* @brief Dequeues and wakes up one thread from the threads queue object. * @brief Dequeues and wakes up one thread from the threads queue object.
* @details Dequeues one thread from the queue without checking if the queue * @details Dequeues one thread from the queue without checking if the queue
@ -769,23 +808,23 @@ void chThdSleepUntil(systime_t abstime) {
* @iclass * @iclass
*/ */
void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) { void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
thread_reference_t tr = nil.threads; thread_t *tp = nil.threads;
chDbgAssert(tqp->cnt > (cnt_t)0, "empty queue"); chDbgAssert(tqp->cnt < (cnt_t)0, "empty queue");
while (true) { while (true) {
/* Is this thread waiting on this queue?*/ /* Is this thread waiting on this queue?*/
if (tr->u1.tqp == tqp) { if (tp->u1.tqp == tqp) {
tqp->cnt++; tqp->cnt++;
chDbgAssert(NIL_THD_IS_WTQUEUE(tr), "not waiting"); chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");
(void) chSchReadyI(tr, msg); (void) chSchReadyI(tp, msg);
return; return;
} }
tr++; tp++;
chDbgAssert(tr < &nil.threads[CH_CFG_NUM_THREADS], chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
"pointer out of range"); "pointer out of range");
} }
} }
@ -804,7 +843,7 @@ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
chDbgCheckClassI(); chDbgCheckClassI();
chDbgCheck(tqp != NULL); chDbgCheck(tqp != NULL);
if (tqp->cnt <= (cnt_t)0) { if (tqp->cnt < (cnt_t)0) {
chThdDoDequeueNextI(tqp, msg); chThdDoDequeueNextI(tqp, msg);
} }
} }
@ -903,7 +942,7 @@ msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) {
return MSG_TIMEOUT; return MSG_TIMEOUT;
} }
sp->cnt = cnt - (cnt_t)1; sp->cnt = cnt - (cnt_t)1;
nil.current->u1.tqp = (threads_queue_t *)sp; nil.current->u1.semp = sp;
return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout); return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
} }
sp->cnt = cnt - (cnt_t)1; sp->cnt = cnt - (cnt_t)1;
@ -942,7 +981,21 @@ void chSemSignalI(semaphore_t *sp) {
chDbgCheck(sp != NULL); chDbgCheck(sp != NULL);
if (++sp->cnt <= (cnt_t)0) { if (++sp->cnt <= (cnt_t)0) {
chThdDoDequeueNextI((threads_queue_t *)sp, MSG_OK); thread_t *tp = nil.threads;
while (true) {
/* Is this thread waiting on this semaphore?*/
if (tp->u1.semp == sp) {
chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");
(void) chSchReadyI(tp, MSG_OK);
return;
}
tp++;
chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
"pointer out of range");
}
} }
} }
@ -998,7 +1051,7 @@ void chSemResetI(semaphore_t *sp, cnt_t n) {
"pointer out of range"); "pointer out of range");
/* Is this thread waiting on this semaphore?*/ /* Is this thread waiting on this semaphore?*/
if (tp->u1.tqp == (threads_queue_t *)sp) { if (tp->u1.semp == sp) {
chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting"); chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");

View File

@ -65,6 +65,8 @@ a series of important improvements, new features have been added.
- Now uses the common ports architecture. - Now uses the common ports architecture.
- Now uses the new shared RTOS components. - Now uses the new shared RTOS components.
- Added implementation of thread queues directly in the kernel, removed it
from NIL OSAL.
- All new features are optional so there is no code size increase. - All new features are optional so there is no code size increase.
- Enhanced source-level compatibility with RT. - Enhanced source-level compatibility with RT.
- Enhanced debug features. - Enhanced debug features.