Project

General

Profile

Feature #14452 ยป 0001-thread.c-favor-timespec-internally.patch

normalperson (Eric Wong), 02/05/2018 07:50 PM

View differences:

thread.c
91 91
static VALUE sym_never;
92 92
static ID id_locals;
93 93

  
94
static void sleep_timeval(rb_thread_t *th, struct timeval time, int spurious_check);
94
static void sleep_timespec(rb_thread_t *, struct timespec, int spurious_check);
95 95
static void sleep_forever(rb_thread_t *th, int nodeadlock, int spurious_check);
96 96
static void rb_thread_sleep_deadly_allow_spurious_wakeup(void);
97 97
static int rb_threadptr_dead(rb_thread_t *th);
98 98
static void rb_check_deadlock(rb_vm_t *vm);
99 99
static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th);
100 100
static const char *thread_status_name(rb_thread_t *th, int detail);
101
static void timeval_add(struct timeval *, const struct timeval *);
102
static void timeval_sub(struct timeval *, const struct timeval *);
103
static int timeval_update_expire(struct timeval *, const struct timeval *);
104
static void getclockofday(struct timeval *);
101
static void timespec_add(struct timespec *, const struct timespec *);
102
static void timespec_sub(struct timespec *, const struct timespec *);
103
static int timespec_update_expire(struct timespec *, const struct timespec *);
104
static void getclockofday(struct timespec *);
105 105

  
106 106
#define eKillSignal INT2FIX(0)
107 107
#define eTerminateSignal INT2FIX(1)
......
209 209
#  define USE_POLL
210 210
#endif
211 211

  
212
#ifdef USE_POLL
213
static inline struct timespec *
212
static struct timespec *
214 213
timespec_for(struct timespec *ts, const struct timeval *tv)
215 214
{
216 215
    if (tv) {
......
220 219
    }
221 220
    return 0;
222 221
}
223
#endif
222

  
223
static struct timeval *
224
timeval_for(struct timeval *tv, const struct timespec *ts)
225
{
226
    if (tv && ts) {
227
        tv->tv_sec = ts->tv_sec;
228
        tv->tv_usec = ts->tv_nsec / 1000;
229
        return tv;
230
    }
231
    return 0;
232
}
224 233

  
225 234
#if THREAD_DEBUG
226 235
#ifdef HAVE_VA_ARGS_MACRO
......
529 538
	terminate_all(vm, th);
530 539

  
531 540
	while (vm_living_thread_num(vm) > 1) {
532
	    struct timeval tv = { 1, 0 };
541
	    struct timespec ts = { 1, 0 };
533 542
	    /*
534 543
	     * Thread exiting routine in thread_start_func_2 notify
535 544
	     * me when the last sub-thread exit.
536 545
	     */
537 546
	    sleeping = 1;
538
	    native_sleep(th, &tv);
547
	    native_sleep(th, &ts);
539 548
	    RUBY_VM_CHECK_INTS_BLOCKING(ec);
540 549
	    sleeping = 0;
541 550
	}
......
873 882

  
874 883
struct join_arg {
875 884
    rb_thread_t *target, *waiting;
876
    struct timeval *limit;
885
    struct timespec *limit;
877 886
};
878 887

  
879 888
static VALUE
......
902 911
{
903 912
    struct join_arg *p = (struct join_arg *)arg;
904 913
    rb_thread_t *target_th = p->target, *th = p->waiting;
905
    struct timeval to;
914
    struct timespec to;
906 915

  
907 916
    if (p->limit) {
908 917
        getclockofday(&to);
909
        timeval_add(&to, p->limit);
918
        timespec_add(&to, p->limit);
910 919
    }
911 920

  
912 921
    while (target_th->status != THREAD_KILLED) {
......
918 927
	    th->vm->sleeper--;
919 928
	}
920 929
	else {
921
            if (timeval_update_expire(p->limit, &to)) {
930
            if (timespec_update_expire(p->limit, &to)) {
922 931
		thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
923 932
			     thread_id_str(target_th));
924 933
		return Qfalse;
......
935 944
}
936 945

  
937 946
static VALUE
938
thread_join(rb_thread_t *target_th, struct timeval *tv)
947
thread_join(rb_thread_t *target_th, struct timespec *ts)
939 948
{
940 949
    rb_thread_t *th = GET_THREAD();
941 950
    struct join_arg arg;
......
949 958

  
950 959
    arg.target = target_th;
951 960
    arg.waiting = th;
952
    arg.limit = tv;
961
    arg.limit = ts;
953 962

  
954 963
    thread_debug("thread_join (thid: %"PRI_THREAD_ID", status: %s)\n",
955 964
		 thread_id_str(target_th), thread_status_name(target_th, TRUE));
......
994 1003
    return target_th->self;
995 1004
}
996 1005

  
997
static struct timeval double2timeval(double);
1006
static struct timespec double2timespec(double);
998 1007

  
999 1008
/*
1000 1009
 *  call-seq:
......
1039 1048
thread_join_m(int argc, VALUE *argv, VALUE self)
1040 1049
{
1041 1050
    VALUE limit;
1042
    struct timeval timeval;
1043
    struct timeval *tv = 0;
1051
    struct timespec timespec;
1052
    struct timespec *ts = 0;
1044 1053

  
1045 1054
    rb_scan_args(argc, argv, "01", &limit);
1046 1055

  
......
1051 1060
    switch (TYPE(limit)) {
1052 1061
      case T_NIL: break;
1053 1062
      case T_FIXNUM:
1054
        timeval.tv_sec = NUM2TIMET(limit);
1055
        timeval.tv_usec = 0;
1056
        tv = &timeval;
1063
        timespec.tv_sec = NUM2TIMET(limit);
1064
        timespec.tv_nsec = 0;
1065
        ts = &timespec;
1057 1066
        break;
1058 1067
      default:
1059
        timeval = double2timeval(rb_num2dbl(limit));
1060
        tv = &timeval;
1068
        timespec = double2timespec(rb_num2dbl(limit));
1069
        ts = &timespec;
1061 1070
    }
1062 1071

  
1063
    return thread_join(rb_thread_ptr(self), tv);
1072
    return thread_join(rb_thread_ptr(self), ts);
1064 1073
}
1065 1074

  
1066 1075
/*
......
1090 1099
 */
1091 1100

  
1092 1101
/*
1093
 * The type of tv_sec in struct timeval is time_t in POSIX.
1094
 * But several systems violate POSIX.
1095
 *
1096
 * OpenBSD 5.2 (amd64):
1097
 *   time_t: int (signed 32bit integer)
1098
 *   tv_sec: long (signed 64bit integer)
1099
 *
1100
 * MinGW-w64 (x64):
1101
 *   time_t: long long (signed 64bit integer)
1102
 *   tv_sec: long (signed 32bit integer)
1102
 * Back when we used "struct timeval", not all platforms implemented
1103
 * tv_sec as time_t.  Nowadays we use "struct timespec" and tv_sec
1104
 * seems to be implemented more consistently across platforms.
1105
 * At least other parts of our code hasn't had to deal with non-time_t
1106
 * tv_sec in timespec...
1103 1107
 */
1108
#define TIMESPEC_SEC_MAX TIMET_MAX
1109
#define TIMESPEC_SEC_MIN TIMET_MIN
1104 1110

  
1105
#if SIGNEDNESS_OF_TIME_T < 0	/* signed */
1106
# define TIMEVAL_SEC_MAX SIGNED_INTEGER_MAX(TYPEOF_TIMEVAL_TV_SEC)
1107
# define TIMEVAL_SEC_MIN SIGNED_INTEGER_MIN(TYPEOF_TIMEVAL_TV_SEC)
1108
#elif SIGNEDNESS_OF_TIME_T > 0	/* unsigned */
1109
# define TIMEVAL_SEC_MAX ((TYPEOF_TIMEVAL_TV_SEC)(~(unsigned_time_t)0))
1110
# define TIMEVAL_SEC_MIN ((TYPEOF_TIMEVAL_TV_SEC)0)
1111
#endif
1112

  
1113
static struct timeval
1114
double2timeval(double d)
1111
static struct timespec
1112
double2timespec(double d)
1115 1113
{
1116
    /* assume timeval.tv_sec has same signedness as time_t */
1117
    const double TIMEVAL_SEC_MAX_PLUS_ONE = (2*(double)(TIMEVAL_SEC_MAX/2+1));
1114
    /* assume timespec.tv_sec has same signedness as time_t */
1115
    const double TIMESPEC_SEC_MAX_PLUS_ONE = TIMET_MAX_PLUS_ONE;
1118 1116

  
1119
    struct timeval time;
1117
    struct timespec time;
1120 1118

  
1121
    if (TIMEVAL_SEC_MAX_PLUS_ONE <= d) {
1122
        time.tv_sec = TIMEVAL_SEC_MAX;
1123
        time.tv_usec = 999999;
1119
    if (TIMESPEC_SEC_MAX_PLUS_ONE <= d) {
1120
        time.tv_sec = TIMESPEC_SEC_MAX;
1121
        time.tv_nsec = 999999999;
1124 1122
    }
1125
    else if (d <= TIMEVAL_SEC_MIN) {
1126
        time.tv_sec = TIMEVAL_SEC_MIN;
1127
        time.tv_usec = 0;
1123
    else if (d <= TIMESPEC_SEC_MIN) {
1124
        time.tv_sec = TIMESPEC_SEC_MIN;
1125
        time.tv_nsec = 0;
1128 1126
    }
1129 1127
    else {
1130
        time.tv_sec = (TYPEOF_TIMEVAL_TV_SEC)d;
1131
        time.tv_usec = (int)((d - (time_t)d) * 1e6);
1132
        if (time.tv_usec < 0) {
1133
            time.tv_usec += (int)1e6;
1128
        time.tv_sec = (time_t)d;
1129
        time.tv_nsec = (long)((d - (time_t)d) * 1e9);
1130
        if (time.tv_nsec < 0) {
1131
            time.tv_nsec += (long)1e9;
1134 1132
            time.tv_sec -= 1;
1135 1133
        }
1136 1134
    }
......
1162 1160
}
1163 1161

  
1164 1162
static void
1165
getclockofday(struct timeval *tp)
1163
getclockofday(struct timespec *ts)
1166 1164
{
1167 1165
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1168
    struct timespec ts;
1169

  
1170
    if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
1171
	tp->tv_sec = ts.tv_sec;
1172
	tp->tv_usec = (int)(ts.tv_nsec / 1000);
1173
    }
1174
    else
1166
    if (clock_gettime(CLOCK_MONOTONIC, ts) == 0)
1167
        return;
1175 1168
#endif
1176
    {
1177
        gettimeofday(tp, NULL);
1178
    }
1169
    rb_timespec_now(ts);
1179 1170
}
1180 1171

  
1181 1172
static void
1182
timeval_add(struct timeval *dst, const struct timeval *tv)
1173
timespec_add(struct timespec *dst, const struct timespec *ts)
1183 1174
{
1184
    if (TIMEVAL_SEC_MAX - tv->tv_sec < dst->tv_sec)
1185
        dst->tv_sec = TIMEVAL_SEC_MAX;
1175
    if (TIMESPEC_SEC_MAX - ts->tv_sec < dst->tv_sec)
1176
        dst->tv_sec = TIMESPEC_SEC_MAX;
1186 1177
    else
1187
        dst->tv_sec += tv->tv_sec;
1188
    if ((dst->tv_usec += tv->tv_usec) >= 1000000) {
1189
	if (dst->tv_sec == TIMEVAL_SEC_MAX) {
1190
            dst->tv_usec = 999999;
1178
        dst->tv_sec += ts->tv_sec;
1179
    if ((dst->tv_nsec += ts->tv_nsec) >= 1000000000) {
1180
	if (dst->tv_sec == TIMESPEC_SEC_MAX) {
1181
            dst->tv_nsec = 999999999;
1191 1182
	}
1192 1183
	else {
1193 1184
            dst->tv_sec++;
1194
            dst->tv_usec -= 1000000;
1185
            dst->tv_nsec -= 1000000000;
1195 1186
	}
1196 1187
    }
1197 1188
}
1198 1189

  
1199 1190
static void
1200
timeval_sub(struct timeval *dst, const struct timeval *tv)
1191
timespec_sub(struct timespec *dst, const struct timespec *tv)
1201 1192
{
1202 1193
    dst->tv_sec -= tv->tv_sec;
1203
    if ((dst->tv_usec -= tv->tv_usec) < 0) {
1194
    if ((dst->tv_nsec -= tv->tv_nsec) < 0) {
1204 1195
	--dst->tv_sec;
1205
	dst->tv_usec += 1000000;
1196
	dst->tv_nsec += 1000000000;
1206 1197
    }
1207 1198
}
1208 1199

  
1209 1200
static int
1210
timeval_update_expire(struct timeval *tv, const struct timeval *to)
1201
timespec_update_expire(struct timespec *ts, const struct timespec *to)
1211 1202
{
1212
    struct timeval tvn;
1203
    struct timespec now;
1213 1204

  
1214
    getclockofday(&tvn);
1215
    if (to->tv_sec < tvn.tv_sec) return 1;
1216
    if (to->tv_sec == tvn.tv_sec && to->tv_usec <= tvn.tv_usec) return 1;
1217
    thread_debug("timeval_update_expire: "
1205
    getclockofday(&now);
1206
    if (to->tv_sec < now.tv_sec) return 1;
1207
    if (to->tv_sec == now.tv_sec && to->tv_nsec <= now.tv_nsec) return 1;
1208
    thread_debug("timespec_update_expire: "
1218 1209
		 "%"PRI_TIMET_PREFIX"d.%.6ld > %"PRI_TIMET_PREFIX"d.%.6ld\n",
1219
		 (time_t)to->tv_sec, (long)to->tv_usec,
1220
		 (time_t)tvn.tv_sec, (long)tvn.tv_usec);
1221
    *tv = *to;
1222
    timeval_sub(tv, &tvn);
1210
		 (time_t)to->tv_sec, (long)to->tv_nsec,
1211
		 (time_t)now.tv_sec, (long)now.tv_nsec);
1212
    *ts = *to;
1213
    timespec_sub(ts, &now);
1223 1214
    return 0;
1224 1215
}
1225 1216

  
1226 1217
static void
1227
sleep_timeval(rb_thread_t *th, struct timeval tv, int spurious_check)
1218
sleep_timespec(rb_thread_t *th, struct timespec ts, int spurious_check)
1228 1219
{
1229
    struct timeval to;
1220
    struct timespec to;
1230 1221
    enum rb_thread_status prev_status = th->status;
1231 1222

  
1232 1223
    getclockofday(&to);
1233
    timeval_add(&to, &tv);
1224
    timespec_add(&to, &ts);
1234 1225
    th->status = THREAD_STOPPED;
1235 1226
    RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
1236 1227
    while (th->status == THREAD_STOPPED) {
1237
	native_sleep(th, &tv);
1228
	native_sleep(th, &ts);
1238 1229
	RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
1239
	if (timeval_update_expire(&tv, &to))
1230
	if (timespec_update_expire(&ts, &to))
1240 1231
	    break;
1241 1232
	if (!spurious_check)
1242 1233
	    break;
......
1269 1260
rb_thread_wait_for(struct timeval time)
1270 1261
{
1271 1262
    rb_thread_t *th = GET_THREAD();
1272
    sleep_timeval(th, time, 1);
1263
    struct timespec ts;
1264

  
1265
    timespec_for(&ts, &time);
1266
    sleep_timespec(th, ts, 1);
1273 1267
}
1274 1268

  
1275 1269
/*
......
3766 3760
    ((fds1) ? rb_fd_dup(fds1, fds2) : (void)0)
3767 3761

  
3768 3762
static inline int
3769
update_timeval(struct timeval *timeout, const struct timeval *to)
3763
update_timespec(struct timespec *timeout, const struct timespec *to)
3770 3764
{
3771 3765
    if (timeout) {
3772
        struct timeval tvn;
3766
        struct timespec now;
3773 3767

  
3774
        getclockofday(&tvn);
3768
        getclockofday(&now);
3775 3769
        *timeout = *to;
3776
        timeval_sub(timeout, &tvn);
3770
        timespec_sub(timeout, &now);
3777 3771

  
3778 3772
        if (timeout->tv_sec < 0)  timeout->tv_sec = 0;
3779
        if (timeout->tv_usec < 0) timeout->tv_usec = 0;
3773
        if (timeout->tv_nsec < 0) timeout->tv_nsec = 0;
3780 3774
    }
3781 3775
    return TRUE;
3782 3776
}
......
3790 3784
    rb_fdset_t MAYBE_UNUSED(orig_read);
3791 3785
    rb_fdset_t MAYBE_UNUSED(orig_write);
3792 3786
    rb_fdset_t MAYBE_UNUSED(orig_except);
3793
    struct timeval to;
3787
    struct timespec to;
3788
    struct timespec ts;
3794 3789
    rb_thread_t *th = GET_THREAD();
3795 3790

  
3796 3791
#define do_select_update() \
3797 3792
    (restore_fdset(readfds, &orig_read), \
3798 3793
     restore_fdset(writefds, &orig_write), \
3799 3794
     restore_fdset(exceptfds, &orig_except), \
3800
     update_timeval(timeout, &to))
3795
     update_timespec(&ts, &to))
3801 3796

  
3802 3797
    if (timeout) {
3803 3798
        getclockofday(&to);
3804
        timeval_add(&to, timeout);
3799
        timespec_add(&to, timespec_for(&ts, timeout));
3805 3800
    }
3806 3801

  
3807 3802
#define fd_init_copy(f) \
......
3816 3811

  
3817 3812
	BLOCKING_REGION({
3818 3813
	    result = native_fd_select(n, readfds, writefds, exceptfds,
3819
				      timeout, th);
3814
				      timeval_for(timeout, &ts), th);
3820 3815
	    if (result < 0) lerrno = errno;
3821 3816
	}, ubf_select, th, FALSE);
3822 3817

  
......
3935 3930
    struct pollfd fds;
3936 3931
    int result = 0, lerrno;
3937 3932
    struct timespec ts;
3938
    struct timeval to;
3933
    struct timespec to;
3934
    struct timespec *tsp = 0;
3939 3935
    rb_thread_t *th = GET_THREAD();
3940 3936

  
3941 3937
    if (timeout) {
3942 3938
        getclockofday(&to);
3943
        timeval_add(&to, timeout);
3939
        timespec_add(&to, timespec_for(&ts, timeout));
3940
        tsp = &ts;
3944 3941
    }
3945 3942

  
3946 3943
    fds.fd = fd;
......
3950 3947
        fds.revents = 0;
3951 3948
        lerrno = 0;
3952 3949
        BLOCKING_REGION({
3953
            result = ppoll(&fds, 1, timespec_for(&ts, timeout), NULL);
3950
            result = ppoll(&fds, 1, tsp, NULL);
3954 3951
            if (result < 0) lerrno = errno;
3955 3952
        }, ubf_select, th, FALSE);
3956 3953

  
3957 3954
        RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
3958 3955
    } while (result < 0 && retryable(errno = lerrno) &&
3959
            update_timeval(timeout, &to));
3956
            update_timespec(&ts, &to));
3960 3957
    if (result < 0) return -1;
3961 3958

  
3962 3959
    if (fds.revents & POLLNVAL) {
thread_pthread.c
366 366
native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel)
367 367
{
368 368
    int ret;
369
    struct timeval tv;
370 369
    struct timespec timeout;
371 370
    struct timespec now;
372 371

  
......
381 380
    if (cond->clockid != CLOCK_REALTIME)
382 381
	rb_bug("unsupported clockid %"PRIdVALUE, (SIGNED_VALUE)cond->clockid);
383 382
#endif
384

  
385
    ret = gettimeofday(&tv, 0);
386
    if (ret != 0)
387
	rb_sys_fail(0);
388
    now.tv_sec = tv.tv_sec;
389
    now.tv_nsec = tv.tv_usec * 1000;
383
    rb_timespec_now(&now);
390 384

  
391 385
#if USE_MONOTONIC_COND
392 386
  out:
393 387
#endif
394 388
    timeout.tv_sec = now.tv_sec;
395 389
    timeout.tv_nsec = now.tv_nsec;
396
    timeout.tv_sec += timeout_rel.tv_sec;
397
    timeout.tv_nsec += timeout_rel.tv_nsec;
398

  
399
    if (timeout.tv_nsec >= 1000*1000*1000) {
400
	timeout.tv_sec++;
401
	timeout.tv_nsec -= 1000*1000*1000;
402
    }
390
    timespec_add(&timeout, &timeout_rel);
403 391

  
404 392
    if (timeout.tv_sec < now.tv_sec)
405 393
	timeout.tv_sec = TIMET_MAX;
......
905 893
{
906 894
    rb_nativethread_cond_t cond = RB_NATIVETHREAD_COND_INIT;
907 895
    volatile rb_thread_t *th_area = 0;
908
    struct timeval tv;
909 896
    struct timespec ts;
910 897
    struct cached_thread_entry *entry =
911 898
      (struct cached_thread_entry *)malloc(sizeof(struct cached_thread_entry));
......
914 901
	return 0; /* failed -> terminate thread immediately */
915 902
    }
916 903

  
917
    gettimeofday(&tv, 0);
918
    ts.tv_sec = tv.tv_sec + 60;
919
    ts.tv_nsec = tv.tv_usec * 1000;
904
    rb_timespec_now(&ts);
905
    ts.tv_sec += 60;
920 906

  
921 907
    rb_native_mutex_lock(&thread_cache_lock);
922 908
    {
......
1072 1058
}
1073 1059

  
1074 1060
static void
1075
native_sleep(rb_thread_t *th, struct timeval *timeout_tv)
1061
native_sleep(rb_thread_t *th, struct timespec *timeout_rel)
1076 1062
{
1077 1063
    struct timespec timeout;
1078 1064
    rb_nativethread_lock_t *lock = &th->interrupt_lock;
1079 1065
    rb_nativethread_cond_t *cond = &th->native_thread_data.sleep_cond;
1080 1066

  
1081
    if (timeout_tv) {
1082
	struct timespec timeout_rel;
1083

  
1084
	timeout_rel.tv_sec = timeout_tv->tv_sec;
1085
	timeout_rel.tv_nsec = timeout_tv->tv_usec * 1000;
1086

  
1067
    if (timeout_rel) {
1087 1068
	/* Solaris cond_timedwait() return EINVAL if an argument is greater than
1088 1069
	 * current_time + 100,000,000.  So cut up to 100,000,000.  This is
1089 1070
	 * considered as a kind of spurious wakeup.  The caller to native_sleep
......
1092 1073
	 * See also [Bug #1341] [ruby-core:29702]
1093 1074
	 * http://download.oracle.com/docs/cd/E19683-01/816-0216/6m6ngupgv/index.html
1094 1075
	 */
1095
	if (timeout_rel.tv_sec > 100000000) {
1096
	    timeout_rel.tv_sec = 100000000;
1097
	    timeout_rel.tv_nsec = 0;
1076
	if (timeout_rel->tv_sec > 100000000) {
1077
	    timeout_rel->tv_sec = 100000000;
1078
	    timeout_rel->tv_nsec = 0;
1098 1079
	}
1099 1080

  
1100
	timeout = native_cond_timeout(cond, timeout_rel);
1081
	timeout = native_cond_timeout(cond, *timeout_rel);
1101 1082
    }
1102 1083

  
1103 1084
    GVL_UNLOCK_BEGIN();
......
1111 1092
	    thread_debug("native_sleep: interrupted before sleep\n");
1112 1093
	}
1113 1094
	else {
1114
	    if (!timeout_tv)
1115
                rb_native_cond_wait(cond, lock);
1095
	    if (!timeout_rel)
1096
		rb_native_cond_wait(cond, lock);
1116 1097
	    else
1117 1098
		native_cond_timedwait(cond, lock, &timeout);
1118 1099
	}
thread_sync.c
252 252

  
253 253
	while (mutex->th != th) {
254 254
	    enum rb_thread_status prev_status = th->status;
255
	    struct timeval *timeout = 0;
256
	    struct timeval tv = { 0, 100000 }; /* 100ms */
255
	    struct timespec *timeout = 0;
256
	    struct timespec ts = { 0, 100000000 }; /* 100ms */
257 257

  
258 258
	    th->status = THREAD_STOPPED_FOREVER;
259 259
	    th->locking_mutex = self;
......
265 265
	     */
266 266
	    if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
267 267
		!patrol_thread) {
268
		timeout = &tv;
268
		timeout = &ts;
269 269
		patrol_thread = th;
270 270
	    }
271 271

  
......
427 427
static VALUE
428 428
rb_mutex_wait_for(VALUE time)
429 429
{
430
    struct timeval *t = (struct timeval *)time;
431
    sleep_timeval(GET_THREAD(), *t, 0); /* permit spurious check */
430
    struct timespec *t = (struct timespec*)time;
431
    sleep_timespec(GET_THREAD(), *t, 0); /* permit spurious check */
432 432
    return Qnil;
433 433
}
434 434

  
......
447 447
	rb_ensure(rb_mutex_sleep_forever, Qnil, rb_mutex_lock, self);
448 448
    }
449 449
    else {
450
	rb_ensure(rb_mutex_wait_for, (VALUE)&t, rb_mutex_lock, self);
450
        struct timespec ts;
451
        VALUE tsp = (VALUE)timespec_for(&ts, &t);
452

  
453
        rb_ensure(rb_mutex_wait_for, tsp, rb_mutex_lock, self);
451 454
    }
452 455
    end = time(0) - beg;
453 456
    return INT2FIX(end);
thread_win32.c
271 271
}
272 272

  
273 273
static void
274
native_sleep(rb_thread_t *th, struct timeval *tv)
274
native_sleep(rb_thread_t *th, struct timespec *ts)
275 275
{
276
    const volatile DWORD msec = (tv) ?
277
	(DWORD)(tv->tv_sec * 1000 + tv->tv_usec / 1000) : INFINITE;
276
    const volatile DWORD msec = (ts) ?
277
	(DWORD)(tv->tv_sec * 1000 + tv->tv_nsec / 1000000) : INFINITE;
278 278

  
279 279
    GVL_UNLOCK_BEGIN();
280 280
    {
281
-