Feature #15002 ยป 0001-thread.c-sleep_-reduce-the-effect-of-spurious-interr.patch
signal.c | ||
---|---|---|
1039 | 1039 |
} |
1040 | 1040 |
#endif |
1041 | 1041 | |
1042 |
static void
|
|
1042 |
static int
|
|
1043 | 1043 |
signal_exec(VALUE cmd, int safe, int sig) |
1044 | 1044 |
{ |
1045 | 1045 |
rb_execution_context_t *ec = GET_EC(); |
... | ... | |
1053 | 1053 |
* 3. rb_signal_exec runs on queued signal |
1054 | 1054 |
*/ |
1055 | 1055 |
if (IMMEDIATE_P(cmd)) |
1056 |
return; |
|
1056 |
return FALSE;
|
|
1057 | 1057 | |
1058 | 1058 |
ec->interrupt_mask |= TRAP_INTERRUPT_MASK; |
1059 | 1059 |
EC_PUSH_TAG(ec); |
... | ... | |
1069 | 1069 |
/* XXX: should be replaced with rb_threadptr_pending_interrupt_enque() */ |
1070 | 1070 |
EC_JUMP_TAG(ec, state); |
1071 | 1071 |
} |
1072 |
return TRUE; |
|
1072 | 1073 |
} |
1073 | 1074 | |
1074 | 1075 |
void |
... | ... | |
1093 | 1094 |
} |
1094 | 1095 |
} |
1095 | 1096 | |
1096 |
void |
|
1097 |
/* returns true if a trap handler was run, false otherwise */ |
|
1098 |
int |
|
1097 | 1099 |
rb_signal_exec(rb_thread_t *th, int sig) |
1098 | 1100 |
{ |
1099 | 1101 |
rb_vm_t *vm = GET_VM(); |
... | ... | |
1131 | 1133 |
rb_threadptr_signal_exit(th); |
1132 | 1134 |
} |
1133 | 1135 |
else { |
1134 |
signal_exec(cmd, safe, sig); |
|
1136 |
return signal_exec(cmd, safe, sig);
|
|
1135 | 1137 |
} |
1138 |
return FALSE; |
|
1136 | 1139 |
} |
1137 | 1140 | |
1138 | 1141 |
static sighandler_t |
thread.c | ||
---|---|---|
187 | 187 |
}; \ |
188 | 188 |
} while(0) |
189 | 189 | |
190 |
/* |
|
191 |
* returns true if this thread was spuriously interrupted, false otherwise |
|
192 |
* (e.g. hit by Thread#run or ran a Ruby-level Signal.trap handler) |
|
193 |
*/ |
|
190 | 194 |
#define RUBY_VM_CHECK_INTS_BLOCKING(ec) vm_check_ints_blocking(ec) |
191 |
static inline void
|
|
195 |
static inline int
|
|
192 | 196 |
vm_check_ints_blocking(rb_execution_context_t *ec) |
193 | 197 |
{ |
194 | 198 |
rb_thread_t *th = rb_ec_thread_ptr(ec); |
195 | 199 | |
196 | 200 |
if (LIKELY(rb_threadptr_pending_interrupt_empty_p(th))) { |
197 |
if (LIKELY(!RUBY_VM_INTERRUPTED_ANY(ec))) return; |
|
201 |
if (LIKELY(!RUBY_VM_INTERRUPTED_ANY(ec))) return FALSE;
|
|
198 | 202 |
} |
199 | 203 |
else { |
200 | 204 |
th->pending_interrupt_queue_checked = 0; |
201 | 205 |
RUBY_VM_SET_INTERRUPT(ec); |
202 | 206 |
} |
203 |
rb_threadptr_execute_interrupts(th, 1); |
|
207 |
return rb_threadptr_execute_interrupts(th, 1);
|
|
204 | 208 |
} |
205 | 209 | |
206 | 210 |
static int |
... | ... | |
1179 | 1183 |
{ |
1180 | 1184 |
enum rb_thread_status prev_status = th->status; |
1181 | 1185 |
enum rb_thread_status status; |
1186 |
int woke; |
|
1182 | 1187 | |
1183 | 1188 |
status = fl & SLEEP_DEADLOCKABLE ? THREAD_STOPPED_FOREVER : THREAD_STOPPED; |
1184 | 1189 |
th->status = status; |
... | ... | |
1192 | 1197 |
if (fl & SLEEP_DEADLOCKABLE) { |
1193 | 1198 |
th->vm->sleeper--; |
1194 | 1199 |
} |
1195 |
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
|
1196 |
if (!(fl & SLEEP_SPURIOUS_CHECK)) |
|
1200 |
woke = vm_check_ints_blocking(th->ec);
|
|
1201 |
if (woke && !(fl & SLEEP_SPURIOUS_CHECK))
|
|
1197 | 1202 |
break; |
1198 | 1203 |
} |
1199 | 1204 |
th->status = prev_status; |
... | ... | |
1283 | 1288 |
{ |
1284 | 1289 |
struct timespec end; |
1285 | 1290 |
enum rb_thread_status prev_status = th->status; |
1291 |
int woke; |
|
1286 | 1292 | |
1287 | 1293 |
getclockofday(&end); |
1288 | 1294 |
timespec_add(&end, &ts); |
... | ... | |
1290 | 1296 |
RUBY_VM_CHECK_INTS_BLOCKING(th->ec); |
1291 | 1297 |
while (th->status == THREAD_STOPPED) { |
1292 | 1298 |
native_sleep(th, &ts); |
1293 |
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
|
1294 |
if (!(fl & SLEEP_SPURIOUS_CHECK)) |
|
1299 |
woke = vm_check_ints_blocking(th->ec);
|
|
1300 |
if (woke && !(fl & SLEEP_SPURIOUS_CHECK))
|
|
1295 | 1301 |
break; |
1296 | 1302 |
if (timespec_update_expire(&ts, &end)) |
1297 | 1303 |
break; |
... | ... | |
2153 | 2159 |
return interrupt & (rb_atomic_t)~ec->interrupt_mask; |
2154 | 2160 |
} |
2155 | 2161 | |
2156 |
MJIT_FUNC_EXPORTED void
|
|
2162 |
MJIT_FUNC_EXPORTED int
|
|
2157 | 2163 |
rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) |
2158 | 2164 |
{ |
2159 | 2165 |
rb_atomic_t interrupt; |
2160 | 2166 |
int postponed_job_interrupt = 0; |
2167 |
int ret = FALSE; |
|
2161 | 2168 | |
2162 |
if (th->ec->raised_flag) return; |
|
2169 |
if (th->ec->raised_flag) return ret;
|
|
2163 | 2170 | |
2164 | 2171 |
while ((interrupt = threadptr_get_interrupts(th)) != 0) { |
2165 | 2172 |
int sig; |
... | ... | |
2189 | 2196 |
} |
2190 | 2197 |
th->status = THREAD_RUNNABLE; |
2191 | 2198 |
while ((sig = rb_get_next_signal()) != 0) { |
2192 |
rb_signal_exec(th, sig); |
|
2199 |
ret |= rb_signal_exec(th, sig);
|
|
2193 | 2200 |
} |
2194 | 2201 |
th->status = prev_status; |
2195 | 2202 |
} |
... | ... | |
2198 | 2205 |
if (pending_interrupt && threadptr_pending_interrupt_active_p(th)) { |
2199 | 2206 |
VALUE err = rb_threadptr_pending_interrupt_deque(th, blocking_timing ? INTERRUPT_ON_BLOCKING : INTERRUPT_NONE); |
2200 | 2207 |
thread_debug("rb_thread_execute_interrupts: %"PRIdVALUE"\n", err); |
2208 |
ret = TRUE; |
|
2201 | 2209 | |
2202 | 2210 |
if (err == Qundef) { |
2203 | 2211 |
/* no error */ |
... | ... | |
2237 | 2245 |
rb_thread_schedule_limits(limits_us); |
2238 | 2246 |
} |
2239 | 2247 |
} |
2248 |
return ret; |
|
2240 | 2249 |
} |
2241 | 2250 | |
2242 | 2251 |
void |
vm_core.h | ||
---|---|---|
1736 | 1736 | |
1737 | 1737 |
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt); |
1738 | 1738 |
int rb_signal_buff_size(void); |
1739 |
void rb_signal_exec(rb_thread_t *th, int sig);
|
|
1739 |
int rb_signal_exec(rb_thread_t *th, int sig);
|
|
1740 | 1740 |
void rb_threadptr_check_signal(rb_thread_t *mth); |
1741 | 1741 |
void rb_threadptr_signal_raise(rb_thread_t *th, int sig); |
1742 | 1742 |
void rb_threadptr_signal_exit(rb_thread_t *th); |
1743 |
void rb_threadptr_execute_interrupts(rb_thread_t *, int);
|
|
1743 |
int rb_threadptr_execute_interrupts(rb_thread_t *, int);
|
|
1744 | 1744 |
void rb_threadptr_interrupt(rb_thread_t *th); |
1745 | 1745 |
void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th); |
1746 | 1746 |
void rb_threadptr_pending_interrupt_clear(rb_thread_t *th); |
1747 |
- |