Project

General

Profile

Feature #15002 ยป 0001-thread.c-sleep_-reduce-the-effect-of-spurious-interr.patch

normalperson (Eric Wong), 08/17/2018 08:07 AM

View differences:

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
-