semaphore.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright (c) 2017-2019 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. * Semaphores are resource-counting sleeping synchronization objects.
  19. * They are used to synchronize access to resources and signal events.
  20. *
  21. * The main operations supported by semaphores are waiting and signalling.
  22. * A semaphore is implemented as a counter with an initial value. Waiting
  23. * on a semaphore means decrementing that counter, whereas signalling
  24. * means incrementing it. Waiting can only succeed if the semaphore value
  25. * is strictly greater than 0.
  26. *
  27. * The use of semaphores is generally discouraged. Mutexes are recommended
  28. * to implement preemptible critical sections, and spinlocks combined with
  29. * calls to thread_sleep() and thread_wakeup() are recommended for
  30. * non-preemptible critical sections. The reason is that a semaphore
  31. * internally already uses a spinlock, but that internal lock may not be
  32. * used to serialize access to anything else. This means that the only case
  33. * where a semaphore may be an efficient synchronization mechanism is
  34. * real-time signalling, e.g. an interrupt handler signalling a thread.
  35. * Here, "real-time" means that there is a guarantee that the thread has
  36. * always consumed the data produced by the interrupt handler before the
  37. * latter runs again.
  38. *
  39. * Since the kernel is an incomplete program without applications, it is
  40. * impossible to perform an analysis providing the real-time guarantee.
  41. * As a result, semaphores may only be used by application code.
  42. */
  43. #ifndef KERN_SEMAPHORE_H
  44. #define KERN_SEMAPHORE_H
  45. #include <assert.h>
  46. #include <errno.h>
  47. #include <stdint.h>
  48. struct semaphore
  49. {
  50. uint16_t value;
  51. uint16_t max_value;
  52. };
  53. // Initialize a semaphore.
  54. void semaphore_init (struct semaphore *semaphore, uint16_t value,
  55. uint16_t max_value);
  56. /*
  57. * Attempt to decrement a semaphore.
  58. *
  59. * This function may not sleep.
  60. *
  61. * Return 0 on success, EAGAIN if the semaphore could not be decremented.
  62. */
  63. int semaphore_trywait (struct semaphore *semaphore);
  64. /*
  65. * Wait on a semaphore.
  66. *
  67. * If the semaphore value cannot be decremented, the calling thread sleeps
  68. * until the semaphore value is incremented.
  69. */
  70. void semaphore_wait (struct semaphore *semaphore);
  71. /*
  72. * Wait on a semaphore, with a time boundary.
  73. *
  74. * The time boundary is an absolute time in ticks.
  75. *
  76. * If successful, the semaphore is decremented, otherwise an error is returned.
  77. */
  78. int semaphore_timedwait (struct semaphore *semaphore, uint64_t ticks);
  79. /*
  80. * Signal a semaphore.
  81. *
  82. * This function attempts to increment the semaphore value. If successful, and
  83. * if one or more threads are waiting on the semaphore, one of them is awoken.
  84. *
  85. * A semaphore may safely be signalled from interrupt context.
  86. *
  87. * If successful, the semaphore is incremented. Otherwise, if the semaphore
  88. * value is already at its maximum before calling this function, EOVERFLOW
  89. * is returned.
  90. */
  91. int semaphore_post (struct semaphore *semaphore);
  92. #endif