workqueue.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #ifdef RT_USING_HEAP
  4. static void _workqueue_thread_entry(void* parameter)
  5. {
  6. struct rt_work* work;
  7. struct rt_workqueue* queue;
  8. queue = (struct rt_workqueue*) parameter;
  9. RT_ASSERT(queue != RT_NULL);
  10. while (1)
  11. {
  12. if (rt_list_isempty(&(queue->work_list)))
  13. {
  14. /* no software timer exist, suspend self. */
  15. rt_thread_suspend(rt_thread_self());
  16. rt_schedule();
  17. }
  18. /* we have work to do with. */
  19. rt_enter_critical();
  20. work = rt_list_entry(queue->work_list.next, struct rt_work, list);
  21. rt_list_remove(&(work->list));
  22. rt_exit_critical();
  23. /* do work */
  24. work->work_func(work, work->work_data);
  25. }
  26. }
  27. struct rt_workqueue *rt_workqueue_create(const char* name, rt_uint16_t stack_size, rt_uint8_t priority)
  28. {
  29. struct rt_workqueue *queue = RT_NULL;
  30. queue = (struct rt_workqueue*)RT_KERNEL_MALLOC(sizeof(struct rt_workqueue));
  31. if (queue != RT_NULL)
  32. {
  33. /* initialize work list */
  34. rt_list_init(&(queue->work_list));
  35. /* create the work thread */
  36. queue->work_thread = rt_thread_create(name, _workqueue_thread_entry, queue, stack_size, priority, 10);
  37. if (queue->work_thread == RT_NULL)
  38. {
  39. RT_KERNEL_FREE(queue);
  40. return RT_NULL;
  41. }
  42. rt_thread_startup(queue->work_thread);
  43. }
  44. return queue;
  45. }
  46. rt_err_t rt_workqueue_destroy(struct rt_workqueue* queue)
  47. {
  48. RT_ASSERT(queue != RT_NULL);
  49. rt_thread_delete(queue->work_thread);
  50. RT_KERNEL_FREE(queue);
  51. return RT_EOK;
  52. }
  53. rt_err_t rt_workqueue_dowork(struct rt_workqueue* queue, struct rt_work* work)
  54. {
  55. RT_ASSERT(queue != RT_NULL);
  56. RT_ASSERT(work != RT_NULL);
  57. rt_enter_critical();
  58. /* NOTE: the work MUST be initialized firstly */
  59. rt_list_remove(&(work->list));
  60. rt_list_insert_after(queue->work_list.prev, &(work->list));
  61. if (queue->work_thread->stat != RT_THREAD_READY)
  62. {
  63. rt_exit_critical();
  64. /* resume work thread */
  65. rt_thread_resume(queue->work_thread);
  66. rt_schedule();
  67. }
  68. else rt_exit_critical();
  69. return RT_EOK;
  70. }
  71. rt_err_t rt_workqueue_cancel_work(struct rt_workqueue* queue, struct rt_work* work)
  72. {
  73. RT_ASSERT(queue != RT_NULL);
  74. RT_ASSERT(work != RT_NULL);
  75. rt_enter_critical();
  76. rt_list_remove(&(work->list));
  77. rt_exit_critical();
  78. return RT_EOK;
  79. }
  80. #endif