Don't rely on being idle to do anything. Fixes JS job starvation on slow machines more.

This commit is contained in:
Cory McWilliams 2024-08-21 12:53:38 -04:00
parent 6f487100cd
commit a15bb8e994
3 changed files with 18 additions and 37 deletions

View File

@ -141,8 +141,6 @@ typedef struct _tf_task_t
float thread_percent; float thread_percent;
uv_async_t run_jobs_async; uv_async_t run_jobs_async;
uv_idle_t idle;
uv_prepare_t prepare;
uv_signal_t sig_term; uv_signal_t sig_term;
uv_signal_t sig_int; uv_signal_t sig_int;
@ -209,7 +207,6 @@ static void _tf_task_sendPromiseExportMessage(tf_task_t* from, tf_taskstub_t* to
static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const char* name); static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const char* name);
static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id); static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id);
static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId); static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId);
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare);
static void _timeout_unlink(tf_task_t* task, timeout_t* timeout); static void _timeout_unlink(tf_task_t* task, timeout_t* timeout);
static void _timeout_closed(uv_handle_t* handle); static void _timeout_closed(uv_handle_t* handle);
@ -1522,28 +1519,6 @@ static bool _tf_task_run_jobs(tf_task_t* task)
return 0; return 0;
} }
static void _tf_task_run_jobs_idle(uv_idle_t* idle)
{
tf_task_t* task = idle->data;
if (!_tf_task_run_jobs(task))
{
/* No more jobs. Don't try again as actively. */
uv_idle_stop(&task->idle);
uv_prepare_start(&task->prepare, _tf_task_run_jobs_prepare);
}
}
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare)
{
tf_task_t* task = prepare->data;
if (_tf_task_run_jobs(task))
{
/* More jobs. We can run again immediately. */
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
uv_prepare_stop(&task->prepare);
}
}
static void _tf_task_run_jobs_async(uv_async_t* async) static void _tf_task_run_jobs_async(uv_async_t* async)
{ {
tf_task_t* task = async->data; tf_task_t* task = async->data;
@ -1553,6 +1528,14 @@ static void _tf_task_run_jobs_async(uv_async_t* async)
} }
} }
void tf_task_check_jobs(tf_task_t* task)
{
if (JS_IsJobPending(task->_runtime))
{
uv_async_send(&task->run_jobs_async);
}
}
static JSModuleDef* _tf_task_module_loader(JSContext* context, const char* module_name, void* opaque) static JSModuleDef* _tf_task_module_loader(JSContext* context, const char* module_name, void* opaque)
{ {
tf_task_t* task = opaque; tf_task_t* task = opaque;
@ -1646,13 +1629,6 @@ tf_task_t* tf_task_create()
uv_timer_init(&task->_loop, &task->gc_timer); uv_timer_init(&task->_loop, &task->gc_timer);
uv_timer_start(&task->gc_timer, _tf_task_gc_timer, 1000, 1000); uv_timer_start(&task->gc_timer, _tf_task_gc_timer, 1000, 1000);
uv_unref((uv_handle_t*)&task->gc_timer); uv_unref((uv_handle_t*)&task->gc_timer);
task->idle.data = task;
uv_idle_init(&task->_loop, &task->idle);
uv_unref((uv_handle_t*)&task->idle);
task->prepare.data = task;
uv_prepare_init(&task->_loop, &task->prepare);
uv_unref((uv_handle_t*)&task->prepare);
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
task->run_jobs_async.data = task; task->run_jobs_async.data = task;
uv_async_init(&task->_loop, &task->run_jobs_async, _tf_task_run_jobs_async); uv_async_init(&task->_loop, &task->run_jobs_async, _tf_task_run_jobs_async);
uv_unref((uv_handle_t*)&task->run_jobs_async); uv_unref((uv_handle_t*)&task->run_jobs_async);
@ -1923,15 +1899,13 @@ void tf_task_destroy(tf_task_t* task)
{ {
uv_close((uv_handle_t*)&task->gc_timer, _tf_task_on_handle_close); uv_close((uv_handle_t*)&task->gc_timer, _tf_task_on_handle_close);
} }
uv_close((uv_handle_t*)&task->idle, _tf_task_on_handle_close);
uv_close((uv_handle_t*)&task->prepare, _tf_task_on_handle_close);
uv_close((uv_handle_t*)&task->run_jobs_async, _tf_task_on_handle_close); uv_close((uv_handle_t*)&task->run_jobs_async, _tf_task_on_handle_close);
uv_signal_stop(&task->sig_term); uv_signal_stop(&task->sig_term);
uv_close((uv_handle_t*)&task->sig_term, _tf_task_on_handle_close); uv_close((uv_handle_t*)&task->sig_term, _tf_task_on_handle_close);
uv_signal_stop(&task->sig_int); uv_signal_stop(&task->sig_int);
uv_close((uv_handle_t*)&task->sig_int, _tf_task_on_handle_close); uv_close((uv_handle_t*)&task->sig_int, _tf_task_on_handle_close);
while (task->trace_timer.data || task->gc_timer.data || task->idle.data || task->prepare.data || task->run_jobs_async.data || task->sig_term.data || task->sig_int.data) while (task->trace_timer.data || task->gc_timer.data || task->run_jobs_async.data || task->sig_term.data || task->sig_int.data)
{ {
uv_run(&task->_loop, UV_RUN_ONCE); uv_run(&task->_loop, UV_RUN_ONCE);
} }

View File

@ -364,4 +364,11 @@ tf_android_start_service_t* tf_task_get_android_start_service();
*/ */
tf_android_stop_service_t* tf_task_get_android_stop_service(); tf_android_stop_service_t* tf_task_get_android_stop_service();
/**
** Check for JS jobs that need to be run. Generally to be called post-JS_Call
** in tf_util_report_error.
** @param task The task.
*/
void tf_task_check_jobs(tf_task_t* task);
/** @} */ /** @} */

View File

@ -211,6 +211,7 @@ static JSValue _util_print(JSContext* context, JSValueConst this_val, int argc,
bool tf_util_report_error(JSContext* context, JSValue value) bool tf_util_report_error(JSContext* context, JSValue value)
{ {
bool is_error = false; bool is_error = false;
tf_task_t* task = tf_task_get(context);
if (JS_IsError(context, value)) if (JS_IsError(context, value))
{ {
const char* string = JS_ToCString(context, value); const char* string = JS_ToCString(context, value);
@ -226,13 +227,11 @@ bool tf_util_report_error(JSContext* context, JSValue value)
} }
JS_FreeValue(context, stack); JS_FreeValue(context, stack);
tf_task_t* task = tf_task_get(context);
tf_task_send_error_to_parent(task, value); tf_task_send_error_to_parent(task, value);
is_error = true; is_error = true;
} }
else if (JS_IsException(value)) else if (JS_IsException(value))
{ {
tf_task_t* task = tf_task_get(context);
if (!tf_task_send_error_to_parent(task, value)) if (!tf_task_send_error_to_parent(task, value))
{ {
JSValue exception = JS_GetException(context); JSValue exception = JS_GetException(context);
@ -241,6 +240,7 @@ bool tf_util_report_error(JSContext* context, JSValue value)
} }
is_error = true; is_error = true;
} }
tf_task_check_jobs(task);
return is_error; return is_error;
} }