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. #include <kern/semaphore_i.h>
  49. struct semaphore;
  50. /*
  51. * Initialize a semaphore.
  52. */
  53. void semaphore_init(struct semaphore *semaphore, uint16_t value,
  54. uint16_t max_value);
  55. /*
  56. * Attempt to decrement a semaphore.
  57. *
  58. * This function may not sleep.
  59. *
  60. * Return 0 on success, EAGAIN if the semaphore could not be decremented.
  61. */
  62. int semaphore_trywait(struct semaphore *semaphore);
  63. /*
  64. * Wait on a semaphore.
  65. *
  66. * If the semaphore value cannot be decremented, the calling thread sleeps
  67. * until the semaphore value is incremented.
  68. */
  69. void semaphore_wait(struct semaphore *semaphore);
  70. /*
  71. * Wait on a semaphore, with a time boundary.
  72. *
  73. * The time boundary is an absolute time in ticks.
  74. *
  75. * If successful, the semaphore is decremented, otherwise an error is returned.
  76. */
  77. int semaphore_timedwait(struct semaphore *semaphore, uint64_t ticks);
  78. /*
  79. * Signal a semaphore.
  80. *
  81. * This function attempts to increment the semaphore value. If successful, and
  82. * if one or more threads are waiting on the semaphore, one of them is awoken.
  83. *
  84. * A semaphore may safely be signalled from interrupt context.
  85. *
  86. * If successful, the semaphore is incremented. Otherwise, if the semaphore
  87. * value is already at its maximum before calling this function, EOVERFLOW
  88. * is returned.
  89. */
  90. int semaphore_post(struct semaphore *semaphore);
  91. #endif /* KERN_SEMAPHORE_H */