2 * Copyright (c) 2018 The strace developers.
5 * SPDX-License-Identifier: LGPL-2.1-or-later
10 struct inject_delay_data {
11 struct timespec ts_enter;
12 struct timespec ts_exit;
15 static struct inject_delay_data *delay_data_vec;
16 static size_t delay_data_vec_capacity; /* size of the arena */
17 static size_t delay_data_vec_size; /* size of the used arena */
19 static timer_t delay_timer = (timer_t) -1;
20 static bool delay_timer_is_armed;
23 expand_delay_data_vec(void)
25 const size_t old_capacity = delay_data_vec_capacity;
26 delay_data_vec = xgrowarray(delay_data_vec, &delay_data_vec_capacity,
27 sizeof(*delay_data_vec));
28 memset(delay_data_vec + old_capacity, 0,
29 (delay_data_vec_capacity - old_capacity)
30 * sizeof(*delay_data_vec));
34 alloc_delay_data(void)
36 const uint16_t rval = delay_data_vec_size;
38 if (rval < delay_data_vec_size)
39 error_func_msg_and_die("delay index overflow");
41 if (delay_data_vec_size == delay_data_vec_capacity)
42 expand_delay_data_vec();
44 ++delay_data_vec_size;
49 fill_delay_data(uint16_t delay_idx, struct timespec *val, bool isenter)
51 if (delay_idx >= delay_data_vec_size)
52 error_func_msg_and_die("delay_idx >= delay_data_vec_size");
56 ts = &(delay_data_vec[delay_idx].ts_enter);
58 ts = &(delay_data_vec[delay_idx].ts_exit);
64 is_delay_timer_created(void)
66 return delay_timer != (timer_t) -1;
70 is_delay_timer_armed(void)
72 return delay_timer_is_armed;
76 delay_timer_expired(void)
78 delay_timer_is_armed = false;
82 arm_delay_timer(const struct tcb *const tcp)
84 const struct itimerspec its = {
85 .it_value = tcp->delay_expiration_time
88 if (timer_settime(delay_timer, TIMER_ABSTIME, &its, NULL))
89 perror_msg_and_die("timer_settime");
91 delay_timer_is_armed = true;
93 debug_func_msg("timer set to %lld.%09ld for pid %d",
94 (long long) tcp->delay_expiration_time.tv_sec,
95 (long) tcp->delay_expiration_time.tv_nsec,
100 delay_tcb(struct tcb *tcp, uint16_t delay_idx, bool isenter)
102 if (delay_idx >= delay_data_vec_size)
103 error_func_msg_and_die("delay_idx >= delay_data_vec_size");
105 debug_func_msg("delaying pid %d on %s",
106 tcp->pid, isenter ? "enter" : "exit");
107 tcp->flags |= TCB_DELAYED;
109 struct timespec *ts_diff;
111 ts_diff = &(delay_data_vec[delay_idx].ts_enter);
113 ts_diff = &(delay_data_vec[delay_idx].ts_exit);
115 struct timespec ts_now;
116 clock_gettime(CLOCK_MONOTONIC, &ts_now);
117 ts_add(&tcp->delay_expiration_time, &ts_now, ts_diff);
119 if (is_delay_timer_created()) {
120 struct itimerspec its;
121 if (timer_gettime(delay_timer, &its))
122 perror_msg_and_die("timer_gettime");
124 const struct timespec *const ts_old = &its.it_value;
125 if (ts_nz(ts_old) && ts_cmp(ts_diff, ts_old) > 0)
128 if (timer_create(CLOCK_MONOTONIC, NULL, &delay_timer))
129 perror_msg_and_die("timer_create");
132 arm_delay_timer(tcp);