Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

delay.c 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * Copyright (c) 2018 The strace developers.
  3. * All rights reserved.
  4. *
  5. * SPDX-License-Identifier: LGPL-2.1-or-later
  6. */
  7. #include "defs.h"
  8. struct inject_delay_data {
  9. struct timespec ts_enter;
  10. struct timespec ts_exit;
  11. };
  12. static struct inject_delay_data *delay_data_vec;
  13. static size_t delay_data_vec_capacity; /* size of the arena */
  14. static size_t delay_data_vec_size; /* size of the used arena */
  15. static timer_t delay_timer = (timer_t) -1;
  16. static bool delay_timer_is_armed;
  17. static void
  18. expand_delay_data_vec(void)
  19. {
  20. const size_t old_capacity = delay_data_vec_capacity;
  21. delay_data_vec = xgrowarray(delay_data_vec, &delay_data_vec_capacity,
  22. sizeof(*delay_data_vec));
  23. memset(delay_data_vec + old_capacity, 0,
  24. (delay_data_vec_capacity - old_capacity)
  25. * sizeof(*delay_data_vec));
  26. }
  27. uint16_t
  28. alloc_delay_data(void)
  29. {
  30. const uint16_t rval = delay_data_vec_size;
  31. if (rval < delay_data_vec_size)
  32. error_func_msg_and_die("delay index overflow");
  33. if (delay_data_vec_size == delay_data_vec_capacity)
  34. expand_delay_data_vec();
  35. ++delay_data_vec_size;
  36. return rval;
  37. }
  38. void
  39. fill_delay_data(uint16_t delay_idx, int intval, bool isenter)
  40. {
  41. if (delay_idx >= delay_data_vec_size)
  42. error_func_msg_and_die("delay_idx >= delay_data_vec_size");
  43. struct timespec *ts;
  44. if (isenter)
  45. ts = &(delay_data_vec[delay_idx].ts_enter);
  46. else
  47. ts = &(delay_data_vec[delay_idx].ts_exit);
  48. ts->tv_sec = intval / 1000000;
  49. ts->tv_nsec = intval % 1000000 * 1000;
  50. }
  51. static bool
  52. is_delay_timer_created(void)
  53. {
  54. return delay_timer != (timer_t) -1;
  55. }
  56. bool
  57. is_delay_timer_armed(void)
  58. {
  59. return delay_timer_is_armed;
  60. }
  61. void
  62. delay_timer_expired(void)
  63. {
  64. delay_timer_is_armed = false;
  65. }
  66. void
  67. arm_delay_timer(const struct tcb *const tcp)
  68. {
  69. const struct itimerspec its = {
  70. .it_value = tcp->delay_expiration_time
  71. };
  72. if (timer_settime(delay_timer, TIMER_ABSTIME, &its, NULL))
  73. perror_msg_and_die("timer_settime");
  74. delay_timer_is_armed = true;
  75. debug_func_msg("timer set to %lld.%09ld for pid %d",
  76. (long long) tcp->delay_expiration_time.tv_sec,
  77. (long) tcp->delay_expiration_time.tv_nsec,
  78. tcp->pid);
  79. }
  80. void
  81. delay_tcb(struct tcb *tcp, uint16_t delay_idx, bool isenter)
  82. {
  83. if (delay_idx >= delay_data_vec_size)
  84. error_func_msg_and_die("delay_idx >= delay_data_vec_size");
  85. debug_func_msg("delaying pid %d on %s",
  86. tcp->pid, isenter ? "enter" : "exit");
  87. tcp->flags |= TCB_DELAYED;
  88. struct timespec *ts_diff;
  89. if (isenter)
  90. ts_diff = &(delay_data_vec[delay_idx].ts_enter);
  91. else
  92. ts_diff = &(delay_data_vec[delay_idx].ts_exit);
  93. struct timespec ts_now;
  94. clock_gettime(CLOCK_MONOTONIC, &ts_now);
  95. ts_add(&tcp->delay_expiration_time, &ts_now, ts_diff);
  96. if (is_delay_timer_created()) {
  97. struct itimerspec its;
  98. if (timer_gettime(delay_timer, &its))
  99. perror_msg_and_die("timer_gettime");
  100. const struct timespec *const ts_old = &its.it_value;
  101. if (ts_nz(ts_old) && ts_cmp(ts_diff, ts_old) > 0)
  102. return;
  103. } else {
  104. if (timer_create(CLOCK_MONOTONIC, NULL, &delay_timer))
  105. perror_msg_and_die("timer_create");
  106. }
  107. arm_delay_timer(tcp);
  108. }