work.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) 2013-2017 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. *
  18. * Deferred work queues.
  19. *
  20. * Works, like threads, are scheduled activities, but they are much shorter
  21. * and (usually) consume a lot less resources. They are allowed to block
  22. * and must run in thread context. This module provides thread pools to
  23. * concurrently handle queued works.
  24. */
  25. #ifndef KERN_WORK_H
  26. #define KERN_WORK_H
  27. #include <kern/init.h>
  28. // Work scheduling flags.
  29. #define WORK_HIGHPRIO 0x1 // Use a high priority worker thread.
  30. struct work;
  31. // Type for work functions.
  32. typedef void (*work_fn_t) (struct work *);
  33. /*
  34. * Deferred work.
  35. *
  36. * This structure should be embedded in objects related to the work. It
  37. * stores the work function and is passed to it as its only parameter.
  38. * The function can then find the containing object with the structof macro.
  39. */
  40. struct work
  41. {
  42. struct work *next;
  43. work_fn_t fn;
  44. };
  45. struct work_queue
  46. {
  47. struct work *first;
  48. struct work *last;
  49. unsigned int nr_works;
  50. };
  51. static inline void
  52. work_queue_init (struct work_queue *queue)
  53. {
  54. queue->first = NULL;
  55. queue->last = NULL;
  56. queue->nr_works = 0;
  57. }
  58. static inline unsigned int
  59. work_queue_nr_works (const struct work_queue *queue)
  60. {
  61. return (queue->nr_works);
  62. }
  63. static inline void
  64. work_queue_push (struct work_queue *queue, struct work *work)
  65. {
  66. work->next = NULL;
  67. if (queue->last == NULL)
  68. queue->first = work;
  69. else
  70. queue->last->next = work;
  71. queue->last = work;
  72. ++queue->nr_works;
  73. }
  74. static inline struct work*
  75. work_queue_pop (struct work_queue *queue)
  76. {
  77. struct work *work = queue->first;
  78. queue->first = work->next;
  79. if (queue->last == work)
  80. queue->last = NULL;
  81. --queue->nr_works;
  82. return (work);
  83. }
  84. static inline void
  85. work_queue_transfer (struct work_queue *dest, struct work_queue *src)
  86. {
  87. *dest = *src;
  88. }
  89. static inline void
  90. work_queue_concat (struct work_queue *queue1, struct work_queue *queue2)
  91. {
  92. if (queue2->nr_works == 0)
  93. return;
  94. else if (!queue1->nr_works)
  95. {
  96. *queue1 = *queue2;
  97. return;
  98. }
  99. queue1->last->next = queue2->first;
  100. queue1->last = queue2->last;
  101. queue1->nr_works += queue2->nr_works;
  102. }
  103. static inline void
  104. work_init (struct work *work, work_fn_t fn)
  105. {
  106. work->fn = fn;
  107. }
  108. /*
  109. * Schedule work for deferred processing.
  110. *
  111. * After being scheduled, a work queue must be reinitialized before
  112. * it can be reused.
  113. *
  114. * This function may be called from interrupt context.
  115. */
  116. void work_schedule (struct work *work, int flags);
  117. void work_queue_schedule (struct work_queue *queue, int flags);
  118. /*
  119. * Report a periodic event (normally the periodic timer interrupt) on the
  120. * current processor.
  121. *
  122. * Periodic events are used internally for optimizations.
  123. *
  124. * Interrupts and preemption must be disabled when calling this function.
  125. */
  126. void work_report_periodic_event (void);
  127. /*
  128. * This init operation provides :
  129. * - work / work queue initialization and scheduling
  130. */
  131. INIT_OP_DECLARE (work_bootstrap);
  132. #endif