8000 Expose `rb_thread_resolve_unblock_function` internally. · ruby/ruby@39af420 · GitHub
[go: up one dir, main page]

Skip to content

Commit 39af420

Browse files
committed
Expose rb_thread_resolve_unblock_function internally.
1 parent c45c600 commit 39af420

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

internal/thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ RUBY_SYMBOL_EXPORT_END
8383
int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing);
8484
bool rb_thread_mn_schedulable(VALUE thread);
8585

86+
bool rb_thread_resolve_unblock_function(rb_unblock_function_t **unblock_function, void **data2, struct rb_thread_struct *thread);
87+
8688
// interrupt exec
8789

8890
typedef VALUE (rb_interrupt_exec_func_t)(void *data);

scheduler.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ typedef enum {
6363
struct rb_fiber_scheduler_blocking_operation {
6464
void *(*function)(void *);
6565
void *data;
66+
6667
rb_unblock_function_t *unblock_function;
6768
void *data2;
69+
6870
int flags;
6971
struct rb_fiber_scheduler_blocking_operation_state *state;
7072

@@ -208,7 +210,10 @@ rb_fiber_scheduler_blocking_operation_execute(rb_fiber_scheduler_blocking_operat
208210
return -1; // Invalid blocking operation
209211
}
210212

211-
// Atomically check if we can transition from QUEUED to EXECUTING
213+
// Resolve sentinel values for unblock_function and data2:
214+
rb_thread_resolve_unblock_function(&blocking_operation->unblock_function, &blocking_operation->data2, GET_THREAD());
215+
216+
// Atomically check if we can transition from QUEUED to EXECUTING
212217
rb_atomic_t expected = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED;
213218
if (RUBY_ATOMIC_CAS(blocking_operation->status, expected, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING) != expected) {
214219
// Already cancelled or in wrong state
@@ -1124,25 +1129,33 @@ rb_fiber_scheduler_blocking_operation_cancel(rb_fiber_scheduler_blocking_operati
11241129

11251130
rb_atomic_t current_state = RUBY_ATOMIC_LOAD(blocking_operation->status);
11261131

1127-
switch (current_state) {
1132+
switch (current_state) {
11281133
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED:
1129-
// Work hasn't started - just mark as cancelled
1134+
// Work hasn't started - just mark as cancelled:
11301135
if (RUBY_ATOMIC_CAS(blocking_operation->status, current_state, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED) == current_state) {
1131-
return 0; // Successfully cancelled before execution
1136+
// Successfully cancelled before execution:
1137+
return 0;
11321138
}
11331139
// Fall through if state changed between load and CAS
11341140

11351141
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING:
11361142
// Work is running - mark cancelled AND call unblock function
1137-
RUBY_ATOMIC_SET(blocking_operation->status, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED);
1138-
if (blocking_operation->unblock_function) {
1143+
if (RUBY_ATOMIC_CAS(blocking_operation->status, current_state, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED) != current_state) {
1144+
// State changed between load and CAS - operation may have completed:
1145+
return 0;
1146+
}
1147+
// Otherwise, we successfully marked it as cancelled, so we can call the unblock function:
1148+
rb_unblock_function_t *unblock_function = blocking_operation->unblock_function;
1149+
if (unblock_function) {
1150+
RUBY_ASSERT(unblock_function != (rb_unblock_function_t *)-1 && "unblock_function is still sentinel value -1, should have been resolved earlier");
11391151
blocking_operation->unblock_function(blocking_operation->data2);
11401152
}
1141-
return 1; // Cancelled during execution (unblock function called)
1153+
// Cancelled during execution (unblock function called):
1154+
return 1;
11421155

11431156
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED:
11441157
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED:
1145-
// Already finished or cancelled
1158+
// Already finished or cancelled:
11461159
return 0;
11471160
}
11481161

thread.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,29 @@ blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
15401540
#endif
15411541
}
15421542

1543+
/*
1544+
* Resolve sentinel unblock function values to their actual function pointers
1545+
* and appropriate data2 values. This centralizes the logic for handling
1546+
* RUBY_UBF_IO and RUBY_UBF_PROCESS sentinel values.
1547+
*
1548+
* @param unblock_function Pointer to unblock function pointer (modified in place)
1549+
* @param data2 Pointer to data2 pointer (modified in place)
1550+
* @param thread Thread context for resolving data2 when needed
1551+
* @return true if sentinel values were resolved, false otherwise
1552+
*/
1553+
bool
1554+
rb_thread_resolve_unblock_function(rb_unblock_function_t **unblock_function, void **data2, struct rb_thread_struct *thread)
1555+
{
1556+
rb_unblock_function_t *ubf = *unblock_function;
1557+
1558+
if ((ubf == RUBY_UBF_IO) || (ubf == RUBY_UBF_PROCESS)) {
1559+
*unblock_function = ubf_select;
1560+
*data2 = thread;
1561+
return true;
1562+
}
1563+
return false;
1564+
}
1565+
15431566
void *
15441567
rb_nogvl(void *(*func)(void *), void *data1,
15451568
rb_unblock_function_t *ubf, void *data2,
@@ -1566,11 +1589,9 @@ rb_nogvl(void *(*func)(void *), void *data1,
15661589
bool is_main_thread = vm->ractor.main_thread == th;
15671590
int saved_errno = 0;
15681591

1569-
if ((ubf == RUBY_UBF_IO) || (ubf == RUBY_UBF_PROCESS)) {
1570-
ubf = ubf_select;
1571-
data2 = th;
1572-
}
1573-
else if (ubf && rb_ractor_living_thread_num(th->ractor) == 1 && is_main_thread) {
1592+
rb_thread_resolve_unblock_function(&ubf, &data2, th);
1593+
1594+
if (ubf && rb_ractor_living_thread_num(th->ractor) == 1 && is_main_thread) {
15741595
if (flags & RB_NOGVL_UBF_ASYNC_SAFE) {
15751596
vm->ubf_async_safe = 1;
15761597
}

0 commit comments

Comments
 (0)
0