dpc.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright (c) 2008 Travis Geiselbrecht
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files
  6. * (the "Software"), to deal in the Software without restriction,
  7. * including without limitation the rights to use, copy, modify, merge,
  8. * publish, distribute, sublicense, and/or sell copies of the Software,
  9. * and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <debug.h>
  24. #include <list.h>
  25. #include <malloc.h>
  26. #include <err.h>
  27. #include <kernel/dpc.h>
  28. #include <kernel/thread.h>
  29. #include <kernel/event.h>
  30. struct dpc {
  31. struct list_node node;
  32. dpc_callback cb;
  33. void *arg;
  34. };
  35. static struct list_node dpc_list = LIST_INITIAL_VALUE(dpc_list);
  36. static event_t dpc_event;
  37. static int dpc_thread_routine(void *arg);
  38. void dpc_init(void)
  39. {
  40. thread_t *thread_dpc;
  41. event_init(&dpc_event, false, 0);
  42. thread_dpc = thread_create("dpc", &dpc_thread_routine, NULL, DPC_PRIORITY, DEFAULT_STACK_SIZE);
  43. if (thread_dpc)
  44. thread_resume(thread_dpc);
  45. else {
  46. dprintf(CRITICAL, "Error: Cannot create dpc thread!\n");
  47. assert(0);
  48. }
  49. }
  50. status_t dpc_queue(dpc_callback cb, void *arg, uint flags)
  51. {
  52. struct dpc *dpc;
  53. dpc = malloc(sizeof(struct dpc));
  54. if (!dpc) {
  55. dprintf(CRITICAL, "Error: %s fails to allocate memory!\n", __func__);
  56. assert(0);
  57. return ERR_NO_MEMORY;
  58. }
  59. dpc->cb = cb;
  60. dpc->arg = arg;
  61. enter_critical_section();
  62. list_add_tail(&dpc_list, &dpc->node);
  63. event_signal(&dpc_event, (flags & DPC_FLAG_NORESCHED) ? false : true);
  64. exit_critical_section();
  65. return NO_ERROR;
  66. }
  67. static int dpc_thread_routine(void *arg)
  68. {
  69. for (;;) {
  70. event_wait(&dpc_event);
  71. enter_critical_section();
  72. struct dpc *dpc = list_remove_head_type(&dpc_list, struct dpc, node);
  73. if (!dpc)
  74. event_unsignal(&dpc_event);
  75. exit_critical_section();
  76. if (dpc) {
  77. // dprintf("dpc calling %p, arg %p\n", dpc->cb, dpc->arg);
  78. dpc->cb(dpc->arg);
  79. free(dpc);
  80. }
  81. }
  82. return 0;
  83. }