condvar.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2020 Intel Corporation.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <kernel.h>
  7. #include <kernel_structs.h>
  8. #include <toolchain.h>
  9. #include <ksched.h>
  10. #include <wait_q.h>
  11. #include <syscall_handler.h>
  12. static struct k_spinlock lock;
  13. int z_impl_k_condvar_init(struct k_condvar *condvar)
  14. {
  15. z_waitq_init(&condvar->wait_q);
  16. z_object_init(condvar);
  17. SYS_PORT_TRACING_OBJ_INIT(k_condvar, condvar, 0);
  18. return 0;
  19. }
  20. #ifdef CONFIG_USERSPACE
  21. int z_vrfy_k_condvar_init(struct k_condvar *condvar)
  22. {
  23. Z_OOPS(Z_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR));
  24. return z_impl_k_condvar_init(condvar);
  25. }
  26. #include <syscalls/k_condvar_init_mrsh.c>
  27. #endif
  28. int z_impl_k_condvar_signal(struct k_condvar *condvar)
  29. {
  30. k_spinlock_key_t key = k_spin_lock(&lock);
  31. SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, signal, condvar);
  32. struct k_thread *thread = z_unpend_first_thread(&condvar->wait_q);
  33. if (thread != NULL) {
  34. SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_condvar, signal, condvar, K_FOREVER);
  35. arch_thread_return_value_set(thread, 0);
  36. z_ready_thread(thread);
  37. z_reschedule(&lock, key);
  38. } else {
  39. k_spin_unlock(&lock, key);
  40. }
  41. SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, signal, condvar, 0);
  42. return 0;
  43. }
  44. #ifdef CONFIG_USERSPACE
  45. int z_vrfy_k_condvar_signal(struct k_condvar *condvar)
  46. {
  47. Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR));
  48. return z_impl_k_condvar_signal(condvar);
  49. }
  50. #include <syscalls/k_condvar_signal_mrsh.c>
  51. #endif
  52. int z_impl_k_condvar_broadcast(struct k_condvar *condvar)
  53. {
  54. struct k_thread *pending_thread;
  55. k_spinlock_key_t key;
  56. int woken = 0;
  57. key = k_spin_lock(&lock);
  58. SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, broadcast, condvar);
  59. /* wake up any threads that are waiting to write */
  60. while ((pending_thread = z_unpend_first_thread(&condvar->wait_q)) !=
  61. NULL) {
  62. woken++;
  63. arch_thread_return_value_set(pending_thread, 0);
  64. z_ready_thread(pending_thread);
  65. }
  66. SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, broadcast, condvar, woken);
  67. z_reschedule(&lock, key);
  68. return woken;
  69. }
  70. #ifdef CONFIG_USERSPACE
  71. int z_vrfy_k_condvar_broadcast(struct k_condvar *condvar)
  72. {
  73. Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR));
  74. return z_impl_k_condvar_broadcast(condvar);
  75. }
  76. #include <syscalls/k_condvar_broadcast_mrsh.c>
  77. #endif
  78. int z_impl_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex,
  79. k_timeout_t timeout)
  80. {
  81. k_spinlock_key_t key;
  82. int ret;
  83. SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, wait, condvar);
  84. key = k_spin_lock(&lock);
  85. k_mutex_unlock(mutex);
  86. ret = z_pend_curr(&lock, key, &condvar->wait_q, timeout);
  87. k_mutex_lock(mutex, K_FOREVER);
  88. SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, wait, condvar, ret);
  89. return ret;
  90. }
  91. #ifdef CONFIG_USERSPACE
  92. int z_vrfy_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex,
  93. k_timeout_t timeout)
  94. {
  95. Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR));
  96. Z_OOPS(Z_SYSCALL_OBJ(mutex, K_OBJ_MUTEX));
  97. return z_impl_k_condvar_wait(condvar, mutex, timeout);
  98. }
  99. #include <syscalls/k_condvar_wait_mrsh.c>
  100. #endif