condition.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Copyright (c) 2013-2018 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. * Locking order : mutex -> sleep queue
  19. */
  20. #include <assert.h>
  21. #include <stdbool.h>
  22. #include <stddef.h>
  23. #include <stdint.h>
  24. #include <kern/condition.h>
  25. #include <kern/condition_types.h>
  26. #include <kern/mutex.h>
  27. #include <kern/sleepq.h>
  28. static struct sleepq*
  29. condition_sleepq_lend (const void *addr)
  30. {
  31. union sync_key key;
  32. sync_key_init (&key, addr);
  33. key.local.addr |= 1;
  34. return (sleepq_lend_key (&key));
  35. }
  36. static int
  37. condition_wait_common (struct condition *condition, struct mutex *mutex,
  38. bool timed, uint64_t ticks)
  39. {
  40. assert (mutex_locked (mutex));
  41. _Auto sleepq = condition_sleepq_lend (condition);
  42. int error;
  43. mutex_unlock (mutex);
  44. if (timed)
  45. error = sleepq_timedwait (sleepq, "cond", ticks);
  46. else
  47. {
  48. sleepq_wait (sleepq, "cond");
  49. error = 0;
  50. }
  51. sleepq_return (sleepq);
  52. mutex_lock (mutex);
  53. return (error);
  54. }
  55. void
  56. condition_wait (struct condition *condition, struct mutex *mutex)
  57. {
  58. int error = condition_wait_common (condition, mutex, false, 0);
  59. assert (!error);
  60. }
  61. int
  62. condition_timedwait (struct condition *condition,
  63. struct mutex *mutex, uint64_t ticks)
  64. {
  65. return (condition_wait_common (condition, mutex, true, ticks));
  66. }
  67. static struct sleepq*
  68. condition_sleepq_acquire (const void *addr)
  69. {
  70. union sync_key key;
  71. sync_key_init (&key, addr);
  72. key.local.addr |= 1;
  73. return (sleepq_acquire_key (&key));
  74. }
  75. void
  76. condition_signal (struct condition *condition)
  77. {
  78. _Auto sleepq = condition_sleepq_acquire (condition);
  79. if (! sleepq)
  80. return;
  81. sleepq_signal (sleepq);
  82. sleepq_release (sleepq);
  83. }
  84. void
  85. condition_broadcast (struct condition *condition)
  86. {
  87. _Auto sleepq = condition_sleepq_acquire (condition);
  88. if (! sleepq)
  89. return;
  90. sleepq_broadcast (sleepq);
  91. sleepq_release (sleepq);
  92. }