Tracing: Work Queue tracing

Add Work tracing, default tracing hooks, and documentation.

Signed-off-by: Torbjörn Leksell <torbjorn.leksell@percepio.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Torbjörn Leksell 2021-03-26 14:41:18 +01:00 committed by Anas Nashif
commit 7a646b3f8e
3 changed files with 380 additions and 14 deletions

View file

@ -2990,10 +2990,7 @@ int k_work_submit_to_queue(struct k_work_q *queue,
*
* @return as with k_work_submit_to_queue().
*/
static inline int k_work_submit(struct k_work *work)
{
return k_work_submit_to_queue(&k_sys_work_q, work);
}
extern int k_work_submit(struct k_work *work);
/** @brief Wait for last-submitted instance to complete.
*
@ -3277,11 +3274,8 @@ int k_work_schedule_for_queue(struct k_work_q *queue,
*
* @return as with k_work_schedule_for_queue().
*/
static inline int k_work_schedule(struct k_work_delayable *dwork,
k_timeout_t delay)
{
return k_work_schedule_for_queue(&k_sys_work_q, dwork, delay);
}
extern int k_work_schedule(struct k_work_delayable *dwork,
k_timeout_t delay);
/** @brief Reschedule a work item to a queue after a delay.
*
@ -3328,11 +3322,8 @@ int k_work_reschedule_for_queue(struct k_work_q *queue,
*
* @return as with k_work_reschedule_for_queue().
*/
static inline int k_work_reschedule(struct k_work_delayable *dwork,
k_timeout_t delay)
{
return k_work_reschedule_for_queue(&k_sys_work_q, dwork, delay);
}
extern int k_work_reschedule(struct k_work_delayable *dwork,
k_timeout_t delay);
/** @brief Flush delayable work.
*

View file

@ -314,6 +314,288 @@
/**
* @brief Work Tracing APIs
* @defgroup work_tracing_apis Work Tracing APIs
* @ingroup tracing_apis
* @{
*/
/**
* @brief Trace initialisation of a Work structure
* @param work Work structure
*/
#define sys_port_trace_k_work_init(work)
/**
* @brief Trace submit work to work queue call entry
* @param queue Work queue structure
* @param work Work structure
*/
#define sys_port_trace_k_work_submit_to_queue_enter(queue, work)
/**
* @brief Trace submit work to work queue call exit
* @param queue Work queue structure
* @param work Work structure
* @param ret Return value
*/
#define sys_port_trace_k_work_submit_to_queue_exit(queue, work, ret)
/**
* @brief Trace submit work to system work queue call entry
* @param work Work structure
*/
#define sys_port_trace_k_work_submit_enter(work)
/**
* @brief Trace submit work to system work queue call exit
* @param work Work structure
* @param ret Return value
*/
#define sys_port_trace_k_work_submit_exit(work, ret)
/**
* @brief Trace flush work call entry
* @param work Work structure
*/
#define sys_port_trace_k_work_flush_enter(work)
/**
* @brief Trace flush work call blocking
* @param work Work structure
* @param timeout Timeout period
*/
#define sys_port_trace_k_work_flush_blocking(work, timeout)
/**
* @brief Trace flush work call exit
* @param work Work structure
* @param ret Return value
*/
#define sys_port_trace_k_work_flush_exit(work, ret)
/**
* @brief Trace cancel work call entry
* @param work Work structure
*/
#define sys_port_trace_k_work_cancel_enter(work)
/**
* @brief Trace cancel work call exit
* @param work Work structure
* @param ret Return value
*/
#define sys_port_trace_k_work_cancel_exit(work, ret)
/**
* @brief Trace cancel sync work call entry
* @param work Work structure
* @param sync Sync object
*/
#define sys_port_trace_k_work_cancel_sync_enter(work, sync)
/**
* @brief Trace cancel sync work call blocking
* @param work Work structure
* @param sync Sync object
*/
#define sys_port_trace_k_work_cancel_sync_blocking(work, sync)
/**
* @brief Trace cancel sync work call exit
* @param work Work structure
* @param sync Sync object
* @param ret Return value
*/
#define sys_port_trace_k_work_cancel_sync_exit(work, sync, ret)
/**
* @}
*/ /* end of work_tracing_apis */
/**
* @brief Work Queue Tracing APIs
* @defgroup work_q_tracing_apis Work Queue Tracing APIs
* @ingroup tracing_apis
* @{
*/
/**
* @brief Trace start of a Work Queue call entry
* @param queue Work Queue structure
*/
#define sys_port_trace_k_work_queue_start_enter(queue)
/**
* @brief Trace start of a Work Queue call exit
* @param queue Work Queue structure
*/
#define sys_port_trace_k_work_queue_start_exit(queue)
/**
* @brief Trace Work Queue drain call entry
* @param queue Work Queue structure
*/
#define sys_port_trace_k_work_queue_drain_enter(queue)
/**
* @brief Trace Work Queue drain call exit
* @param queue Work Queue structure
* @param ret Return value
*/
#define sys_port_trace_k_work_queue_drain_exit(queue, ret)
/**
* @brief Trace Work Queue unplug call entry
* @param queue Work Queue structure
*/
#define sys_port_trace_k_work_queue_unplug_enter(queue)
/**
* @brief Trace Work Queue unplug call exit
* @param queue Work Queue structure
* @param ret Return value
*/
#define sys_port_trace_k_work_queue_unplug_exit(queue, ret)
/**
* @}
*/ /* end of work_q_tracing_apis */
/**
* @brief Work Delayable Tracing APIs
* @defgroup work_delayable_tracing_apis Work Delayable Tracing APIs
* @ingroup tracing_apis
* @{
*/
/**
* @brief Trace initialisation of a Delayable Work structure
* @param dwork Delayable Work structure
*/
#define sys_port_trace_k_work_delayable_init(dwork)
/**
* @brief Trace schedule delayable work for queue enter
* @param queue Work Queue structure
* @param dwork Delayable Work structure
* @param delay Delay period
*/
#define sys_port_trace_k_work_schedule_for_queue_enter(queue, dwork, delay)
/**
* @brief Trace schedule delayable work for queue exit
* @param queue Work Queue structure
* @param dwork Delayable Work structure
* @param delay Delay period
* @param ret Return value
*/
#define sys_port_trace_k_work_schedule_for_queue_exit(queue, dwork, delay, ret)
/**
* @brief Trace schedule delayable work for system work queue enter
* @param dwork Delayable Work structure
* @param delay Delay period
*/
#define sys_port_trace_k_work_schedule_enter(dwork, delay)
/**
* @brief Trace schedule delayable work for system work queue exit
* @param dwork Delayable Work structure
* @param delay Delay period
* @param ret Return value
*/
#define sys_port_trace_k_work_schedule_exit(dwork, delay, ret)
/**
* @brief Trace reschedule delayable work for queue enter
* @param queue Work Queue structure
* @param dwork Delayable Work structure
* @param delay Delay period
*/
#define sys_port_trace_k_work_reschedule_for_queue_enter(queue, dwork, delay)
/**
* @brief Trace reschedule delayable work for queue exit
* @param queue Work Queue structure
* @param dwork Delayable Work structure
* @param delay Delay period
* @param ret Return value
*/
#define sys_port_trace_k_work_reschedule_for_queue_exit(queue, dwork, delay, ret)
/**
* @brief Trace reschedule delayable work for system queue enter
* @param dwork Delayable Work structure
* @param delay Delay period
*/
#define sys_port_trace_k_work_reschedule_enter(dwork, delay)
/**
* @brief Trace reschedule delayable work for system queue exit
* @param dwork Delayable Work structure
* @param delay Delay period
* @param ret Return value
*/
#define sys_port_trace_k_work_reschedule_exit(dwork, delay, ret)
/**
* @brief Trace delayable work flush enter
* @param dwork Delayable Work structure
* @param sync Sync object
*/
#define sys_port_trace_k_work_flush_delayable_enter(dwork, sync)
/**
* @brief Trace delayable work flush exit
* @param dwork Delayable Work structure
* @param sync Sync object
* @param ret Return value
*/
#define sys_port_trace_k_work_flush_delayable_exit(dwork, sync, ret)
/**
* @brief Trace delayable work cancel enter
* @param dwork Delayable Work structure
*/
#define sys_port_trace_k_work_cancel_delayable_enter(dwork)
/**
* @brief Trace delayable work cancel enter
* @param dwork Delayable Work structure
* @param ret Return value
*/
#define sys_port_trace_k_work_cancel_delayable_exit(dwork, ret)
/**
* @brief Trace delayable work cancel sync enter
* @param dwork Delayable Work structure
* @param sync Sync object
*/
#define sys_port_trace_k_work_cancel_delayable_sync_enter(dwork, sync)
/**
* @brief Trace delayable work cancel sync enter
* @param dwork Delayable Work structure
* @param sync Sync object
* @param ret Return value
*/
#define sys_port_trace_k_work_cancel_delayable_sync_exit(dwork, sync, ret)
/**
* @}
*/ /* end of work_delayable_tracing_apis */
/**
* @brief Work Poll Tracing APIs
* @defgroup work_poll_tracing_apis Work Poll Tracing APIs

View file

@ -138,6 +138,8 @@ void k_work_init(struct k_work *work,
__ASSERT_NO_MSG(handler != NULL);
*work = (struct k_work)Z_WORK_INITIALIZER(handler);
SYS_PORT_TRACING_OBJ_INIT(k_work, work);
}
static inline int work_busy_get_locked(const struct k_work *work)
@ -359,6 +361,9 @@ int k_work_submit_to_queue(struct k_work_q *queue,
__ASSERT_NO_MSG(work != NULL);
k_spinlock_key_t key = k_spin_lock(&lock);
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, submit_to_queue, queue, work);
int ret = submit_to_queue_locked(work, &queue);
k_spin_unlock(&lock, key);
@ -372,6 +377,18 @@ int k_work_submit_to_queue(struct k_work_q *queue,
k_yield();
}
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, submit_to_queue, queue, work, ret);
return ret;
}
int k_work_submit(struct k_work *work)
{
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, submit, work);
int ret = k_work_submit_to_queue(&k_sys_work_q, work);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, submit, work, ret);
return ret;
}
@ -420,6 +437,8 @@ bool k_work_flush(struct k_work *work,
__ASSERT_NO_MSG(arch_mem_coherent(sync));
#endif
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, flush, work);
struct z_work_flusher *flusher = &sync->flusher;
k_spinlock_key_t key = k_spin_lock(&lock);
@ -429,9 +448,13 @@ bool k_work_flush(struct k_work *work,
/* If necessary wait until the flusher item completes */
if (need_flush) {
SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_work, flush, work, K_FOREVER);
k_sem_take(&flusher->sem, K_FOREVER);
}
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, flush, work, need_flush);
return need_flush;
}
@ -503,11 +526,15 @@ int k_work_cancel(struct k_work *work)
__ASSERT_NO_MSG(work != NULL);
__ASSERT_NO_MSG(!flag_test(&work->flags, K_WORK_DELAYABLE_BIT));
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, cancel, work);
k_spinlock_key_t key = k_spin_lock(&lock);
int ret = cancel_async_locked(work);
k_spin_unlock(&lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, cancel, work, ret);
return ret;
}
@ -522,6 +549,8 @@ bool k_work_cancel_sync(struct k_work *work,
__ASSERT_NO_MSG(arch_mem_coherent(sync));
#endif
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, cancel_sync, work, sync);
struct z_work_canceller *canceller = &sync->canceller;
k_spinlock_key_t key = k_spin_lock(&lock);
bool pending = (work_busy_get_locked(work) != 0U);
@ -535,9 +564,12 @@ bool k_work_cancel_sync(struct k_work *work,
k_spin_unlock(&lock, key);
if (need_wait) {
SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_work, cancel_sync, work, sync);
k_sem_take(&canceller->sem, K_FOREVER);
}
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, cancel_sync, work, sync, pending);
return pending;
}
@ -711,6 +743,8 @@ void k_work_queue_start(struct k_work_q *queue,
__ASSERT_NO_MSG(!flag_test(&queue->flags, K_WORK_QUEUE_STARTED_BIT));
uint32_t flags = K_WORK_QUEUE_STARTED;
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work_queue, start, queue);
sys_slist_init(&queue->pending);
z_waitq_init(&queue->notifyq);
z_waitq_init(&queue->drainq);
@ -734,6 +768,8 @@ void k_work_queue_start(struct k_work_q *queue,
}
k_thread_start(&queue->thread);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work_queue, start, queue);
}
int k_work_queue_drain(struct k_work_q *queue,
@ -742,6 +778,8 @@ int k_work_queue_drain(struct k_work_q *queue,
__ASSERT_NO_MSG(queue);
__ASSERT_NO_MSG(!k_is_in_isr());
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work_queue, drain, queue);
int ret = 0;
k_spinlock_key_t key = k_spin_lock(&lock);
@ -761,6 +799,8 @@ int k_work_queue_drain(struct k_work_q *queue,
k_spin_unlock(&lock, key);
}
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work_queue, drain, queue, ret);
return ret;
}
@ -768,6 +808,8 @@ int k_work_queue_unplug(struct k_work_q *queue)
{
__ASSERT_NO_MSG(queue);
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work_queue, unplug, queue);
int ret = -EALREADY;
k_spinlock_key_t key = k_spin_lock(&lock);
@ -777,6 +819,8 @@ int k_work_queue_unplug(struct k_work_q *queue)
k_spin_unlock(&lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work_queue, unplug, queue, ret);
return ret;
}
@ -824,6 +868,8 @@ void k_work_init_delayable(struct k_work_delayable *dwork,
},
};
z_init_timeout(&dwork->timeout);
SYS_PORT_TRACING_OBJ_INIT(k_work_delayable, dwork);
}
static inline int work_delayable_busy_get_locked(const struct k_work_delayable *dwork)
@ -933,6 +979,8 @@ int k_work_schedule_for_queue(struct k_work_q *queue,
{
__ASSERT_NO_MSG(dwork != NULL);
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, schedule_for_queue, queue, dwork, delay);
struct k_work *work = &dwork->work;
int ret = 0;
k_spinlock_key_t key = k_spin_lock(&lock);
@ -944,6 +992,20 @@ int k_work_schedule_for_queue(struct k_work_q *queue,
k_spin_unlock(&lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, schedule_for_queue, queue, dwork, delay, ret);
return ret;
}
int k_work_schedule(struct k_work_delayable *dwork,
k_timeout_t delay)
{
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, schedule, dwork, delay);
int ret = k_work_schedule_for_queue(&k_sys_work_q, dwork, delay);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, schedule, dwork, delay, ret);
return ret;
}
@ -953,6 +1015,8 @@ int k_work_reschedule_for_queue(struct k_work_q *queue,
{
__ASSERT_NO_MSG(dwork != NULL);
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, reschedule_for_queue, queue, dwork, delay);
int ret = 0;
k_spinlock_key_t key = k_spin_lock(&lock);
@ -964,6 +1028,20 @@ int k_work_reschedule_for_queue(struct k_work_q *queue,
k_spin_unlock(&lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, reschedule_for_queue, queue, dwork, delay, ret);
return ret;
}
int k_work_reschedule(struct k_work_delayable *dwork,
k_timeout_t delay)
{
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, reschedule, dwork, delay);
int ret = k_work_reschedule_for_queue(&k_sys_work_q, dwork, delay);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, reschedule, dwork, delay, ret);
return ret;
}
@ -971,10 +1049,15 @@ int k_work_cancel_delayable(struct k_work_delayable *dwork)
{
__ASSERT_NO_MSG(dwork != NULL);
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, cancel_delayable, dwork);
k_spinlock_key_t key = k_spin_lock(&lock);
int ret = cancel_delayable_async_locked(dwork);
k_spin_unlock(&lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, cancel_delayable, dwork, ret);
return ret;
}
@ -988,6 +1071,8 @@ bool k_work_cancel_delayable_sync(struct k_work_delayable *dwork,
__ASSERT_NO_MSG(arch_mem_coherent(sync));
#endif
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, cancel_delayable_sync, dwork, sync);
struct z_work_canceller *canceller = &sync->canceller;
k_spinlock_key_t key = k_spin_lock(&lock);
bool pending = (work_delayable_busy_get_locked(dwork) != 0U);
@ -1004,6 +1089,7 @@ bool k_work_cancel_delayable_sync(struct k_work_delayable *dwork,
k_sem_take(&canceller->sem, K_FOREVER);
}
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, cancel_delayable_sync, dwork, sync, pending);
return pending;
}
@ -1017,6 +1103,8 @@ bool k_work_flush_delayable(struct k_work_delayable *dwork,
__ASSERT_NO_MSG(arch_mem_coherent(sync));
#endif
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_work, flush_delayable, dwork, sync);
struct k_work *work = &dwork->work;
struct z_work_flusher *flusher = &sync->flusher;
k_spinlock_key_t key = k_spin_lock(&lock);
@ -1024,6 +1112,9 @@ bool k_work_flush_delayable(struct k_work_delayable *dwork,
/* If it's idle release the lock and return immediately. */
if (work_busy_get_locked(work) == 0U) {
k_spin_unlock(&lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, flush_delayable, dwork, sync, false);
return false;
}
@ -1046,6 +1137,8 @@ bool k_work_flush_delayable(struct k_work_delayable *dwork,
k_sem_take(&flusher->sem, K_FOREVER);
}
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_work, flush_delayable, dwork, sync, need_flush);
return need_flush;
}