17
17
#include <errno.h>
18
18
#include <ksched.h>
19
19
#include <zephyr/sys/printk.h>
20
+ #include <zephyr/logging/log.h>
21
+
22
+ LOG_MODULE_DECLARE (os , CONFIG_KERNEL_LOG_LEVEL );
20
23
21
24
static inline void flag_clear (uint32_t * flagp ,
22
25
uint32_t bit )
@@ -599,6 +602,52 @@ bool k_work_cancel_sync(struct k_work *work,
599
602
return pending ;
600
603
}
601
604
605
+ #if defined(CONFIG_WORKQUEUE_WORK_TIMEOUT )
606
+ static void workto_handler (struct _timeout * to )
607
+ {
608
+ struct k_work_q * queue = CONTAINER_OF (to , struct k_work_q , workto );
609
+ k_spinlock_key_t key ;
610
+ const char * name ;
611
+ struct k_work * work ;
612
+ k_work_handler_t handler ;
613
+
614
+ key = k_spin_lock (& lock );
615
+
616
+ name = k_thread_name_get (& queue -> thread );
617
+ work = queue -> work ;
618
+ handler = work -> handler ;
619
+
620
+ if (name != NULL ) {
621
+ LOG_ERR ("queue %s blocked by work %p with handler %p" , name , work , handler );
622
+ } else {
623
+ LOG_ERR ("queue %p blocked by work %p with handler %p" , queue , work , handler );
624
+ }
625
+
626
+ k_spin_unlock (& lock , key );
627
+
628
+ k_oops ();
629
+ }
630
+
631
+ static void work_timeout_start_locked (struct k_work_q * queue , struct k_work * work )
632
+ {
633
+ if (K_TIMEOUT_EQ (queue -> work_timeout , K_FOREVER )) {
634
+ return ;
635
+ }
636
+
637
+ queue -> work = work ;
638
+ z_add_timeout (& queue -> workto , workto_handler , queue -> work_timeout );
639
+ }
640
+
641
+ static void work_timeout_stop_locked (struct k_work_q * queue )
642
+ {
643
+ if (K_TIMEOUT_EQ (queue -> work_timeout , K_FOREVER )) {
644
+ return ;
645
+ }
646
+
647
+ z_abort_timeout (& queue -> workto );
648
+ }
649
+ #endif /* defined(CONFIG_WORKQUEUE_WORK_TIMEOUT) */
650
+
602
651
/* Loop executed by a work queue thread.
603
652
*
604
653
* @param workq_ptr pointer to the work queue structure
@@ -678,6 +727,10 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3)
678
727
continue ;
679
728
}
680
729
730
+ #if defined(CONFIG_WORKQUEUE_WORK_TIMEOUT )
731
+ work_timeout_start_locked (queue , work );
732
+ #endif /* defined(CONFIG_WORKQUEUE_WORK_TIMEOUT) */
733
+
681
734
k_spin_unlock (& lock , key );
682
735
683
736
__ASSERT_NO_MSG (handler != NULL );
@@ -690,6 +743,10 @@ static void work_queue_main(void *workq_ptr, void *p2, void *p3)
690
743
*/
691
744
key = k_spin_lock (& lock );
692
745
746
+ #if defined(CONFIG_WORKQUEUE_WORK_TIMEOUT )
747
+ work_timeout_stop_locked (queue );
748
+ #endif /* defined(CONFIG_WORKQUEUE_WORK_TIMEOUT) */
749
+
693
750
flag_clear (& work -> flags , K_WORK_RUNNING_BIT );
694
751
if (flag_test (& work -> flags , K_WORK_FLUSHING_BIT )) {
695
752
finalize_flush_locked (work );
@@ -761,6 +818,14 @@ void k_work_queue_start(struct k_work_q *queue,
761
818
queue -> thread .base .user_options |= K_ESSENTIAL ;
762
819
}
763
820
821
+ #if defined(CONFIG_WORKQUEUE_WORK_TIMEOUT )
822
+ if ((cfg != NULL ) && (cfg -> work_timeout_ms )) {
823
+ queue -> work_timeout = K_MSEC (cfg -> work_timeout_ms );
824
+ } else {
825
+ queue -> work_timeout = K_FOREVER ;
826
+ }
827
+ #endif /* defined(CONFIG_WORKQUEUE_WORK_TIMEOUT) */
828
+
764
829
k_thread_start (& queue -> thread );
765
830
766
831
SYS_PORT_TRACING_OBJ_FUNC_EXIT (k_work_queue , start , queue );
0 commit comments