server: Call the satisfied methods after removing the thread wait.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d5380f0d00
commit
e0760ce933
|
@ -583,7 +583,7 @@ void make_wait_abandoned( struct wait_queue_entry *entry )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finish waiting */
|
/* finish waiting */
|
||||||
static void end_wait( struct thread *thread )
|
static unsigned int end_wait( struct thread *thread, unsigned int status )
|
||||||
{
|
{
|
||||||
struct thread_wait *wait = thread->wait;
|
struct thread_wait *wait = thread->wait;
|
||||||
struct wait_queue_entry *entry;
|
struct wait_queue_entry *entry;
|
||||||
|
@ -591,10 +591,26 @@ static void end_wait( struct thread *thread )
|
||||||
|
|
||||||
assert( wait );
|
assert( wait );
|
||||||
thread->wait = wait->next;
|
thread->wait = wait->next;
|
||||||
|
|
||||||
|
if (status < wait->count) /* wait satisfied, tell it to the objects */
|
||||||
|
{
|
||||||
|
if (wait->select == SELECT_WAIT_ALL)
|
||||||
|
{
|
||||||
|
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||||
|
entry->obj->ops->satisfied( entry->obj, entry );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry = wait->queues + status;
|
||||||
|
entry->obj->ops->satisfied( entry->obj, entry );
|
||||||
|
}
|
||||||
|
if (wait->abandoned) status += STATUS_ABANDONED_WAIT_0;
|
||||||
|
}
|
||||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||||
entry->obj->ops->remove_queue( entry->obj, entry );
|
entry->obj->ops->remove_queue( entry->obj, entry );
|
||||||
if (wait->user) remove_timeout_user( wait->user );
|
if (wait->user) remove_timeout_user( wait->user );
|
||||||
free( wait );
|
free( wait );
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build the thread wait structure */
|
/* build the thread wait structure */
|
||||||
|
@ -624,7 +640,7 @@ static int wait_on( const select_op_t *select_op, unsigned int count, struct obj
|
||||||
if (!obj->ops->add_queue( obj, entry ))
|
if (!obj->ops->add_queue( obj, entry ))
|
||||||
{
|
{
|
||||||
wait->count = i;
|
wait->count = i;
|
||||||
end_wait( current );
|
end_wait( current, get_error() );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -672,25 +688,14 @@ static int check_wait( struct thread *thread )
|
||||||
* want to do something when signaled, even if others are not */
|
* want to do something when signaled, even if others are not */
|
||||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||||
not_ok |= !entry->obj->ops->signaled( entry->obj, entry );
|
not_ok |= !entry->obj->ops->signaled( entry->obj, entry );
|
||||||
if (not_ok) goto other_checks;
|
if (!not_ok) return STATUS_WAIT_0;
|
||||||
/* Wait satisfied: tell it to all objects */
|
|
||||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
|
||||||
entry->obj->ops->satisfied( entry->obj, entry );
|
|
||||||
return wait->abandoned ? STATUS_ABANDONED_WAIT_0 : STATUS_WAIT_0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
|
||||||
{
|
if (entry->obj->ops->signaled( entry->obj, entry )) return i;
|
||||||
if (!entry->obj->ops->signaled( entry->obj, entry )) continue;
|
|
||||||
/* Wait satisfied: tell it to the object */
|
|
||||||
entry->obj->ops->satisfied( entry->obj, entry );
|
|
||||||
if (wait->abandoned) i += STATUS_ABANDONED_WAIT_0;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
other_checks:
|
|
||||||
if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
|
if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
|
||||||
if (wait->timeout <= current_time) return STATUS_TIMEOUT;
|
if (wait->timeout <= current_time) return STATUS_TIMEOUT;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -728,8 +733,8 @@ int wake_thread( struct thread *thread )
|
||||||
if ((signaled = check_wait( thread )) == -1) break;
|
if ((signaled = check_wait( thread )) == -1) break;
|
||||||
|
|
||||||
cookie = thread->wait->cookie;
|
cookie = thread->wait->cookie;
|
||||||
|
signaled = end_wait( thread, signaled );
|
||||||
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
|
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
|
||||||
end_wait( thread );
|
|
||||||
if (cookie && send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
|
if (cookie && send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
|
||||||
{
|
{
|
||||||
if (!count) count = -1;
|
if (!count) count = -1;
|
||||||
|
@ -752,13 +757,9 @@ int wake_thread_queue_entry( struct wait_queue_entry *entry )
|
||||||
|
|
||||||
assert( wait->select != SELECT_WAIT_ALL );
|
assert( wait->select != SELECT_WAIT_ALL );
|
||||||
|
|
||||||
signaled = entry - wait->queues;
|
|
||||||
entry->obj->ops->satisfied( entry->obj, entry );
|
|
||||||
if (wait->abandoned) signaled += STATUS_ABANDONED_WAIT_0;
|
|
||||||
|
|
||||||
cookie = wait->cookie;
|
cookie = wait->cookie;
|
||||||
|
signaled = end_wait( thread, entry - wait->queues );
|
||||||
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
|
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d\n", thread->id, signaled );
|
||||||
end_wait( thread );
|
|
||||||
|
|
||||||
if (!cookie || send_thread_wakeup( thread, cookie, signaled ) != -1)
|
if (!cookie || send_thread_wakeup( thread, cookie, signaled ) != -1)
|
||||||
wake_thread( thread ); /* check other waits too */
|
wake_thread( thread ); /* check other waits too */
|
||||||
|
@ -778,7 +779,7 @@ static void thread_timeout( void *ptr )
|
||||||
if (thread->suspend + thread->process->suspend > 0) return; /* suspended, ignore it */
|
if (thread->suspend + thread->process->suspend > 0) return; /* suspended, ignore it */
|
||||||
|
|
||||||
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=TIMEOUT\n", thread->id );
|
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=TIMEOUT\n", thread->id );
|
||||||
end_wait( thread );
|
end_wait( thread, STATUS_TIMEOUT );
|
||||||
|
|
||||||
assert( cookie );
|
assert( cookie );
|
||||||
if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
|
if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
|
||||||
|
@ -836,7 +837,7 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
|
||||||
{
|
{
|
||||||
if (!signal_object( select_op->signal_and_wait.signal ))
|
if (!signal_object( select_op->signal_and_wait.signal ))
|
||||||
{
|
{
|
||||||
end_wait( current );
|
end_wait( current, get_error() );
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
/* check if we woke ourselves up */
|
/* check if we woke ourselves up */
|
||||||
|
@ -863,8 +864,7 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
|
||||||
if ((ret = check_wait( current )) != -1)
|
if ((ret = check_wait( current )) != -1)
|
||||||
{
|
{
|
||||||
/* condition is already satisfied */
|
/* condition is already satisfied */
|
||||||
end_wait( current );
|
set_error( end_wait( current, ret ));
|
||||||
set_error( ret );
|
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,7 +874,7 @@ static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, c
|
||||||
if (!(current->wait->user = add_timeout_user( current->wait->timeout,
|
if (!(current->wait->user = add_timeout_user( current->wait->timeout,
|
||||||
thread_timeout, current->wait )))
|
thread_timeout, current->wait )))
|
||||||
{
|
{
|
||||||
end_wait( current );
|
end_wait( current, get_error() );
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1106,7 +1106,7 @@ void kill_thread( struct thread *thread, int violent_death )
|
||||||
thread->id, thread->exit_code );
|
thread->id, thread->exit_code );
|
||||||
if (thread->wait)
|
if (thread->wait)
|
||||||
{
|
{
|
||||||
while (thread->wait) end_wait( thread );
|
while (thread->wait) end_wait( thread, STATUS_THREAD_IS_TERMINATING );
|
||||||
send_thread_wakeup( thread, 0, thread->exit_code );
|
send_thread_wakeup( thread, 0, thread->exit_code );
|
||||||
/* if it is waiting on the socket, we don't need to send a SIGQUIT */
|
/* if it is waiting on the socket, we don't need to send a SIGQUIT */
|
||||||
violent_death = 0;
|
violent_death = 0;
|
||||||
|
|
Loading…
Reference in New Issue