semaphore.cpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/assert.h"
  5. #include "core/hle/kernel/errors.h"
  6. #include "core/hle/kernel/kernel.h"
  7. #include "core/hle/kernel/object_address_table.h"
  8. #include "core/hle/kernel/semaphore.h"
  9. #include "core/hle/kernel/thread.h"
  10. namespace Kernel {
  11. Semaphore::Semaphore() {}
  12. Semaphore::~Semaphore() {}
  13. ResultVal<SharedPtr<Semaphore>> Semaphore::Create(VAddr guest_addr, VAddr mutex_addr,
  14. std::string name) {
  15. SharedPtr<Semaphore> semaphore(new Semaphore);
  16. // When the semaphore is created, some slots are reserved for other threads,
  17. // and the rest is reserved for the caller thread;
  18. semaphore->available_count = Memory::Read32(guest_addr);
  19. semaphore->name = std::move(name);
  20. semaphore->guest_addr = guest_addr;
  21. semaphore->mutex_addr = mutex_addr;
  22. // Semaphores are referenced by guest address, so track this in the kernel
  23. g_object_address_table.Insert(guest_addr, semaphore);
  24. return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
  25. }
  26. bool Semaphore::ShouldWait(Thread* thread) const {
  27. return available_count <= 0;
  28. }
  29. void Semaphore::Acquire(Thread* thread) {
  30. if (available_count <= 0)
  31. return;
  32. --available_count;
  33. UpdateGuestState();
  34. }
  35. ResultCode Semaphore::Release(s32 target) {
  36. ++available_count;
  37. UpdateGuestState();
  38. if (target == -1) {
  39. // When -1, wake up all waiting threads
  40. WakeupAllWaitingThreads();
  41. } else {
  42. // Otherwise, wake up just a single thread
  43. WakeupWaitingThread(GetHighestPriorityReadyThread());
  44. }
  45. return RESULT_SUCCESS;
  46. }
  47. void Semaphore::UpdateGuestState() {
  48. Memory::Write32(guest_addr, available_count);
  49. }
  50. } // namespace Kernel