mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* thread.c (thread_start_func_2): wake up joining threads.
* thread.c (sleep_forever, sleep_timeval): return when interrupted. [ruby-dev:35542] * thread.c (timer_thread_function): restore main thread status. [ruby-core:17270] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18094 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
aba40d1a38
commit
47e3f4e1ae
4 changed files with 73 additions and 58 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
Thu Jul 17 04:19:33 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* thread.c (thread_start_func_2): wake up joining threads.
|
||||||
|
|
||||||
|
* thread.c (sleep_forever, sleep_timeval): return when interrupted.
|
||||||
|
[ruby-dev:35542]
|
||||||
|
|
||||||
|
* thread.c (timer_thread_function): restore main thread status.
|
||||||
|
[ruby-core:17270]
|
||||||
|
|
||||||
Thu Jul 17 01:27:38 2008 Yusuke Endoh <mame@tsg.ne.jp>
|
Thu Jul 17 01:27:38 2008 Yusuke Endoh <mame@tsg.ne.jp>
|
||||||
|
|
||||||
* io.c (appendline): remove invalid access.
|
* io.c (appendline): remove invalid access.
|
||||||
|
|
89
thread.c
89
thread.c
|
@ -105,7 +105,7 @@ static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_call
|
||||||
|
|
||||||
#define BLOCKING_REGION(exec, ubf, ubfarg) do { \
|
#define BLOCKING_REGION(exec, ubf, ubfarg) do { \
|
||||||
rb_thread_t *__th = GET_THREAD(); \
|
rb_thread_t *__th = GET_THREAD(); \
|
||||||
int __prev_status = __th->status; \
|
enum rb_thread_status __prev_status = __th->status; \
|
||||||
struct rb_unblock_callback __oldubf; \
|
struct rb_unblock_callback __oldubf; \
|
||||||
set_unblock_function(__th, ubf, ubfarg, &__oldubf); \
|
set_unblock_function(__th, ubf, ubfarg, &__oldubf); \
|
||||||
__th->status = THREAD_STOPPED; \
|
__th->status = THREAD_STOPPED; \
|
||||||
|
@ -413,6 +413,11 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
|
||||||
while (join_th) {
|
while (join_th) {
|
||||||
if (join_th == main_th) errinfo = Qnil;
|
if (join_th == main_th) errinfo = Qnil;
|
||||||
rb_thread_interrupt(join_th);
|
rb_thread_interrupt(join_th);
|
||||||
|
switch (join_th->status) {
|
||||||
|
case THREAD_STOPPED: case THREAD_STOPPED_FOREVER:
|
||||||
|
join_th->status = THREAD_RUNNABLE;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
join_th = join_th->join_list_next;
|
join_th = join_th->join_list_next;
|
||||||
}
|
}
|
||||||
if (th != main_th) rb_check_deadlock(th->vm);
|
if (th != main_th) rb_check_deadlock(th->vm);
|
||||||
|
@ -714,7 +719,21 @@ double2timeval(double d)
|
||||||
static void
|
static void
|
||||||
sleep_forever(rb_thread_t *th, int deadlockable)
|
sleep_forever(rb_thread_t *th, int deadlockable)
|
||||||
{
|
{
|
||||||
native_sleep(th, 0, deadlockable);
|
enum rb_thread_status prev_status = th->status;
|
||||||
|
|
||||||
|
th->status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
|
||||||
|
do {
|
||||||
|
if (deadlockable) {
|
||||||
|
th->vm->sleeper++;
|
||||||
|
rb_check_deadlock(th->vm);
|
||||||
|
}
|
||||||
|
native_sleep(th, 0);
|
||||||
|
if (deadlockable) {
|
||||||
|
th->vm->sleeper--;
|
||||||
|
}
|
||||||
|
RUBY_VM_CHECK_INTS();
|
||||||
|
} while (th->status == THREAD_STOPPED_FOREVER);
|
||||||
|
th->status = prev_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -736,7 +755,33 @@ getclockofday(struct timeval *tp)
|
||||||
static void
|
static void
|
||||||
sleep_timeval(rb_thread_t *th, struct timeval tv)
|
sleep_timeval(rb_thread_t *th, struct timeval tv)
|
||||||
{
|
{
|
||||||
native_sleep(th, &tv, 0);
|
struct timeval to, tvn;
|
||||||
|
enum rb_thread_status prev_status = th->status;
|
||||||
|
|
||||||
|
getclockofday(&to);
|
||||||
|
to.tv_sec += tv.tv_sec;
|
||||||
|
if ((to.tv_usec += tv.tv_usec) >= 1000000) {
|
||||||
|
to.tv_sec++;
|
||||||
|
to.tv_usec -= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
th->status = THREAD_STOPPED;
|
||||||
|
do {
|
||||||
|
native_sleep(th, &tv);
|
||||||
|
RUBY_VM_CHECK_INTS();
|
||||||
|
getclockofday(&tvn);
|
||||||
|
if (to.tv_sec < tvn.tv_sec) break;
|
||||||
|
if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break;
|
||||||
|
thread_debug("sleep_timeval: %ld.%.6ld > %ld.%.6ld\n",
|
||||||
|
(long)to.tv_sec, to.tv_usec,
|
||||||
|
(long)tvn.tv_sec, tvn.tv_usec);
|
||||||
|
tv.tv_sec = to.tv_sec - tvn.tv_sec;
|
||||||
|
if ((tv.tv_usec = to.tv_usec - tvn.tv_usec) < 0) {
|
||||||
|
--tv.tv_sec;
|
||||||
|
tv.tv_usec += 1000000;
|
||||||
|
}
|
||||||
|
} while (th->status == THREAD_STOPPED);
|
||||||
|
th->status = prev_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -789,29 +834,7 @@ void
|
||||||
rb_thread_wait_for(struct timeval time)
|
rb_thread_wait_for(struct timeval time)
|
||||||
{
|
{
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
struct timeval to, tvn;
|
|
||||||
|
|
||||||
getclockofday(&to);
|
|
||||||
to.tv_sec += time.tv_sec;
|
|
||||||
if ((to.tv_usec += time.tv_usec) >= 1000000) {
|
|
||||||
to.tv_sec++;
|
|
||||||
to.tv_usec -= 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
sleep_timeval(th, time);
|
sleep_timeval(th, time);
|
||||||
getclockofday(&tvn);
|
|
||||||
if (to.tv_sec < tvn.tv_sec) break;
|
|
||||||
if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break;
|
|
||||||
thread_debug("sleep_timeval: %ld.%.6ld > %ld.%.6ld\n",
|
|
||||||
(long)to.tv_sec, to.tv_usec,
|
|
||||||
(long)tvn.tv_sec, tvn.tv_usec);
|
|
||||||
time.tv_sec = to.tv_sec - tvn.tv_sec;
|
|
||||||
if ((time.tv_usec = to.tv_usec - tvn.tv_usec) < 0) {
|
|
||||||
--time.tv_sec;
|
|
||||||
time.tv_usec += 1000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -913,7 +936,7 @@ rb_thread_execute_interrupts(rb_thread_t *th)
|
||||||
{
|
{
|
||||||
if (th->raised_flag) return;
|
if (th->raised_flag) return;
|
||||||
while (th->interrupt_flag) {
|
while (th->interrupt_flag) {
|
||||||
int status = th->status;
|
enum rb_thread_status status = th->status;
|
||||||
th->status = THREAD_RUNNABLE;
|
th->status = THREAD_RUNNABLE;
|
||||||
th->interrupt_flag = 0;
|
th->interrupt_flag = 0;
|
||||||
|
|
||||||
|
@ -1161,6 +1184,9 @@ rb_thread_wakeup(VALUE thread)
|
||||||
rb_raise(rb_eThreadError, "killed thread");
|
rb_raise(rb_eThreadError, "killed thread");
|
||||||
}
|
}
|
||||||
rb_thread_ready(th);
|
rb_thread_ready(th);
|
||||||
|
if (th->status != THREAD_TO_KILL) {
|
||||||
|
th->status = THREAD_RUNNABLE;
|
||||||
|
}
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2114,10 +2140,15 @@ timer_thread_function(void *arg)
|
||||||
|
|
||||||
/* check signal */
|
/* check signal */
|
||||||
if (vm->buffered_signal_size && vm->main_thread->exec_signal == 0) {
|
if (vm->buffered_signal_size && vm->main_thread->exec_signal == 0) {
|
||||||
vm->main_thread->exec_signal = rb_get_next_signal(vm);
|
rb_thread_t *mth = vm->main_thread;
|
||||||
|
enum rb_thread_status prev_status = mth->status;
|
||||||
|
mth->exec_signal = rb_get_next_signal(vm);
|
||||||
|
thread_debug("main_thread: %s\n", thread_status_name(prev_status));
|
||||||
thread_debug("buffered_signal_size: %ld, sig: %d\n",
|
thread_debug("buffered_signal_size: %ld, sig: %d\n",
|
||||||
(long)vm->buffered_signal_size, vm->main_thread->exec_signal);
|
(long)vm->buffered_signal_size, vm->main_thread->exec_signal);
|
||||||
rb_thread_interrupt(vm->main_thread);
|
if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
|
||||||
|
rb_thread_interrupt(mth);
|
||||||
|
mth->status = prev_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -2635,7 +2666,7 @@ rb_mutex_lock(VALUE self)
|
||||||
|
|
||||||
while (mutex->th != th) {
|
while (mutex->th != th) {
|
||||||
int interrupted;
|
int interrupted;
|
||||||
int prev_status = th->status;
|
enum rb_thread_status prev_status = th->status;
|
||||||
int last_thread = 0;
|
int last_thread = 0;
|
||||||
struct rb_unblock_callback oldubf;
|
struct rb_unblock_callback oldubf;
|
||||||
|
|
||||||
|
|
|
@ -493,9 +493,8 @@ ubf_select(void *ptr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
native_sleep(rb_thread_t *th, struct timeval *tv, int deadlockable)
|
native_sleep(rb_thread_t *th, struct timeval *tv)
|
||||||
{
|
{
|
||||||
int prev_status = th->status;
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
struct timeval tvn;
|
struct timeval tvn;
|
||||||
|
|
||||||
|
@ -509,15 +508,6 @@ native_sleep(rb_thread_t *th, struct timeval *tv, int deadlockable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tv && deadlockable) {
|
|
||||||
th->status = THREAD_STOPPED_FOREVER;
|
|
||||||
th->vm->sleeper++;
|
|
||||||
rb_check_deadlock(th->vm);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
th->status = THREAD_STOPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_debug("native_sleep %ld\n", tv ? tv->tv_sec : -1);
|
thread_debug("native_sleep %ld\n", tv ? tv->tv_sec : -1);
|
||||||
GVL_UNLOCK_BEGIN();
|
GVL_UNLOCK_BEGIN();
|
||||||
{
|
{
|
||||||
|
@ -555,9 +545,6 @@ native_sleep(rb_thread_t *th, struct timeval *tv, int deadlockable)
|
||||||
pthread_mutex_unlock(&th->interrupt_lock);
|
pthread_mutex_unlock(&th->interrupt_lock);
|
||||||
}
|
}
|
||||||
GVL_UNLOCK_END();
|
GVL_UNLOCK_END();
|
||||||
th->status = prev_status;
|
|
||||||
if (!tv && deadlockable) th->vm->sleeper--;
|
|
||||||
RUBY_VM_CHECK_INTS();
|
|
||||||
|
|
||||||
thread_debug("native_sleep done\n");
|
thread_debug("native_sleep done\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,9 +204,8 @@ rb_w32_Sleep(unsigned long msec)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
native_sleep(rb_thread_t *th, struct timeval *tv, int deadlockable)
|
native_sleep(rb_thread_t *th, struct timeval *tv)
|
||||||
{
|
{
|
||||||
int prev_status = th->status;
|
|
||||||
DWORD msec;
|
DWORD msec;
|
||||||
|
|
||||||
if (tv) {
|
if (tv) {
|
||||||
|
@ -216,15 +215,6 @@ native_sleep(rb_thread_t *th, struct timeval *tv, int deadlockable)
|
||||||
msec = INFINITE;
|
msec = INFINITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tv && deadlockable) {
|
|
||||||
th->status = THREAD_STOPPED_FOREVER;
|
|
||||||
th->vm->sleeper++;
|
|
||||||
rb_check_deadlock(th->vm);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
th->status = THREAD_STOPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
GVL_UNLOCK_BEGIN();
|
GVL_UNLOCK_BEGIN();
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
@ -249,9 +239,6 @@ native_sleep(rb_thread_t *th, struct timeval *tv, int deadlockable)
|
||||||
native_mutex_unlock(&th->interrupt_lock);
|
native_mutex_unlock(&th->interrupt_lock);
|
||||||
}
|
}
|
||||||
GVL_UNLOCK_END();
|
GVL_UNLOCK_END();
|
||||||
th->status = prev_status;
|
|
||||||
if (!tv && deadlockable) th->vm->sleeper--;
|
|
||||||
RUBY_VM_CHECK_INTS();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue