mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-24 05:21:20 -08:00
multithreading: fix spinlock in ecl_wait_on_timed
process.woken_up was not set to nil before calling condition. This could lead to threads not waiting correctly on barriers and consequently to mp:process-join returning earlier than it should.
This commit is contained in:
parent
14a94c2b0e
commit
0080acd4ce
2 changed files with 10 additions and 10 deletions
|
|
@ -34,7 +34,7 @@ ecl_make_barrier(cl_object name, cl_index count)
|
|||
@(defun mp::make-barrier (count &key name)
|
||||
@
|
||||
if (count == ECL_T)
|
||||
count = ecl_make_fixnum(MOST_POSITIVE_FIXNUM);
|
||||
count = ecl_make_fixnum(MOST_POSITIVE_FIXNUM);
|
||||
@(return ecl_make_barrier(name, fixnnint(count)));
|
||||
@)
|
||||
|
||||
|
|
|
|||
|
|
@ -135,14 +135,6 @@ ecl_wait_on_timed(cl_env_ptr env, cl_object (*condition)(cl_env_ptr, cl_object),
|
|||
struct ecl_timeval start;
|
||||
ecl_get_internal_real_time(&start);
|
||||
|
||||
/* This spinlock is here because the default path (fair) is
|
||||
* too slow */
|
||||
for (iteration = 0; iteration < 10; iteration++) {
|
||||
cl_object output = condition(the_env,o);
|
||||
if (output != ECL_NIL)
|
||||
return output;
|
||||
}
|
||||
|
||||
/* 0) We reserve a record for the queue. In order to avoid
|
||||
* using the garbage collector, we reuse records */
|
||||
record = own_process->process.queue_record;
|
||||
|
|
@ -162,14 +154,22 @@ ecl_wait_on_timed(cl_env_ptr env, cl_object (*condition)(cl_env_ptr, cl_object),
|
|||
ecl_bds_bind(the_env, @'ext::*interrupts-enabled*', ECL_T);
|
||||
ecl_check_pending_interrupts(the_env);
|
||||
|
||||
/* This spinlock is here because the default path (fair) is
|
||||
* too slow */
|
||||
for (iteration = 0; iteration < 10; iteration++) {
|
||||
if (!Null(output = condition(the_env,o)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* 3) Unlike the sigsuspend() implementation, this
|
||||
* implementation does not block signals and the
|
||||
* wakeup event might be lost before the sleep
|
||||
* function is invoked. We must thus spin over short
|
||||
* intervals of time to ensure that we check the
|
||||
* condition periodically. */
|
||||
while (Null(output = condition(the_env, o))) {
|
||||
while (Null(output)) {
|
||||
ecl_musleep(waiting_time(iteration++, &start), 1);
|
||||
output = condition(the_env, o);
|
||||
}
|
||||
ecl_bds_unwind1(the_env);
|
||||
} ECL_UNWIND_PROTECT_EXIT {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue