clock.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Time.h>
  7. #include <Kernel/Process.h>
  8. #include <Kernel/Time/TimeManagement.h>
  9. namespace Kernel {
  10. KResultOr<FlatPtr> Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts)
  11. {
  12. VERIFY_NO_PROCESS_BIG_LOCK(this);
  13. REQUIRE_PROMISE(stdio);
  14. if (!TimeManagement::is_valid_clock_id(clock_id))
  15. return EINVAL;
  16. auto ts = TimeManagement::the().current_time(clock_id).to_timespec();
  17. if (!copy_to_user(user_ts, &ts))
  18. return EFAULT;
  19. return 0;
  20. }
  21. KResultOr<FlatPtr> Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> user_ts)
  22. {
  23. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
  24. REQUIRE_PROMISE(settime);
  25. if (!is_superuser())
  26. return EPERM;
  27. auto ts = copy_time_from_user(user_ts);
  28. if (!ts.has_value())
  29. return EFAULT;
  30. switch (clock_id) {
  31. case CLOCK_REALTIME:
  32. TimeManagement::the().set_epoch_time(ts.value());
  33. break;
  34. default:
  35. return EINVAL;
  36. }
  37. return 0;
  38. }
  39. KResultOr<FlatPtr> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_params*> user_params)
  40. {
  41. VERIFY_NO_PROCESS_BIG_LOCK(this);
  42. REQUIRE_PROMISE(stdio);
  43. Syscall::SC_clock_nanosleep_params params;
  44. if (!copy_from_user(&params, user_params))
  45. return EFAULT;
  46. Optional<Time> requested_sleep = copy_time_from_user(params.requested_sleep);
  47. if (!requested_sleep.has_value())
  48. return EFAULT;
  49. bool is_absolute;
  50. switch (params.flags) {
  51. case 0:
  52. is_absolute = false;
  53. break;
  54. case TIMER_ABSTIME:
  55. is_absolute = true;
  56. break;
  57. default:
  58. return EINVAL;
  59. }
  60. if (!TimeManagement::is_valid_clock_id(params.clock_id))
  61. return EINVAL;
  62. bool was_interrupted;
  63. if (is_absolute) {
  64. was_interrupted = Thread::current()->sleep_until(params.clock_id, requested_sleep.value()).was_interrupted();
  65. } else {
  66. Time remaining_sleep;
  67. was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep.value(), &remaining_sleep).was_interrupted();
  68. timespec remaining_sleep_ts = remaining_sleep.to_timespec();
  69. if (was_interrupted && params.remaining_sleep && !copy_to_user(params.remaining_sleep, &remaining_sleep_ts))
  70. return EFAULT;
  71. }
  72. if (was_interrupted)
  73. return EINTR;
  74. return 0;
  75. }
  76. KResultOr<FlatPtr> Process::sys$adjtime(Userspace<const timeval*> user_delta, Userspace<timeval*> user_old_delta)
  77. {
  78. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
  79. if (user_old_delta) {
  80. timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment();
  81. timeval old_delta;
  82. timespec_to_timeval(old_delta_ts, old_delta);
  83. if (!copy_to_user(user_old_delta, &old_delta))
  84. return EFAULT;
  85. }
  86. if (user_delta) {
  87. REQUIRE_PROMISE(settime);
  88. if (!is_superuser())
  89. return EPERM;
  90. auto delta = copy_time_from_user(user_delta);
  91. if (!delta.has_value())
  92. return EFAULT;
  93. // FIXME: Should use AK::Time internally
  94. TimeManagement::the().set_remaining_epoch_time_adjustment(delta->to_timespec());
  95. }
  96. return 0;
  97. }
  98. KResultOr<FlatPtr> Process::sys$gettimeofday(Userspace<timeval*> user_tv)
  99. {
  100. VERIFY_NO_PROCESS_BIG_LOCK(this);
  101. REQUIRE_PROMISE(stdio);
  102. auto tv = kgettimeofday().to_timeval();
  103. if (!copy_to_user(user_tv, &tv))
  104. return EFAULT;
  105. return 0;
  106. }
  107. }