summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/thread.h2
-rw-r--r--scheduler.c29
-rw-r--r--thread.c31
3 files changed, 49 insertions, 13 deletions
@@ -83,6 +83,8 @@ RUBY_SYMBOL_EXPORT_END
int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing);
bool rb_thread_mn_schedulable(VALUE thread);
// interrupt exec
typedef VALUE (rb_interrupt_exec_func_t)(void *data);
@@ -63,8 +63,10 @@ typedef enum {
struct rb_fiber_scheduler_blocking_operation {
void *(*function)(void *);
void *data;
rb_unblock_function_t *unblock_function;
void *data2;
int flags;
struct rb_fiber_scheduler_blocking_operation_state *state;
@@ -208,7 +210,10 @@ rb_fiber_scheduler_blocking_operation_execute(rb_fiber_scheduler_blocking_operat
return -1; // Invalid blocking operation
}
- // Atomically check if we can transition from QUEUED to EXECUTING
rb_atomic_t expected = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED;
if (RUBY_ATOMIC_CAS(blocking_operation->status, expected, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING) != expected) {
// Already cancelled or in wrong state
@@ -1124,25 +1129,33 @@ rb_fiber_scheduler_blocking_operation_cancel(rb_fiber_scheduler_blocking_operati
rb_atomic_t current_state = RUBY_ATOMIC_LOAD(blocking_operation->status);
- switch (current_state) {
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED:
- // Work hasn't started - just mark as cancelled
if (RUBY_ATOMIC_CAS(blocking_operation->status, current_state, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED) == current_state) {
- return 0; // Successfully cancelled before execution
}
// Fall through if state changed between load and CAS
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING:
// Work is running - mark cancelled AND call unblock function
- RUBY_ATOMIC_SET(blocking_operation->status, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED);
- if (blocking_operation->unblock_function) {
blocking_operation->unblock_function(blocking_operation->data2);
}
- return 1; // Cancelled during execution (unblock function called)
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED:
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED:
- // Already finished or cancelled
return 0;
}
@@ -1540,6 +1540,29 @@ blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
#endif
}
void *
rb_nogvl(void *(*func)(void *), void *data1,
rb_unblock_function_t *ubf, void *data2,
@@ -1566,11 +1589,9 @@ rb_nogvl(void *(*func)(void *), void *data1,
bool is_main_thread = vm->ractor.main_thread == th;
int saved_errno = 0;
- if ((ubf == RUBY_UBF_IO) || (ubf == RUBY_UBF_PROCESS)) {
- ubf = ubf_select;
- data2 = th;
- }
- else if (ubf && rb_ractor_living_thread_num(th->ractor) == 1 && is_main_thread) {
if (flags & RB_NOGVL_UBF_ASYNC_SAFE) {
vm->ubf_async_safe = 1;
}