11#include "sysv_semaphores.h"
22#include <time.h>
3+ #include <stdbool.h>
34
45static key_t
56generate_key (const char * name );
67
7- static void *
8- acquire_semaphore (void * p );
9-
108static int
119wait_for_new_semaphore_set (key_t key , long permissions );
1210
@@ -108,6 +106,9 @@ perform_semop(int sem_id, short index, short op, short flags, struct timespec *t
108106 buf .sem_flg = flags ;
109107
110108 int num_retries = 3 ;
109+ if (flags & IPC_NOWAIT ) {
110+ num_retries = 0 ;
111+ }
111112
112113 do {
113114 result = semtimedop (sem_id , & buf , 1 , ts );
@@ -151,17 +152,9 @@ get_semaphore(int key)
151152 return semget (key , SI_NUM_SEMAPHORES , 0 );
152153}
153154
154- void *
155- acquire_semaphore_without_gvl (void * p )
156- {
157- WITHOUT_GVL (acquire_semaphore , p , RUBY_UBF_IO , NULL );
158- return NULL ;
159- }
160-
161- static void *
162- acquire_semaphore (void * p )
155+ static void
156+ acquire_semaphore_internal (semian_resource_t * res , short flags )
163157{
164- semian_resource_t * res = (semian_resource_t * ) p ;
165158 res -> error = 0 ;
166159 res -> wait_time = -1 ;
167160#ifdef DEBUG
@@ -170,14 +163,39 @@ acquire_semaphore(void *p)
170163
171164 struct timespec begin , end ;
172165 int benchmark_result = clock_gettime (CLOCK_MONOTONIC , & begin );
173- if (perform_semop (res -> sem_id , SI_SEM_TICKETS , -1 , SEM_UNDO , & res -> timeout ) == -1 ) {
166+ if (perform_semop (res -> sem_id , SI_SEM_TICKETS , -1 , SEM_UNDO | flags , & res -> timeout ) == -1 ) {
174167 res -> error = errno ;
175168 }
176169 if (benchmark_result == 0 ) {
177170 if (clock_gettime (CLOCK_MONOTONIC , & end ) == 0 ) {
178171 res -> wait_time = diff_timespec_ms (& end , & begin );
179172 }
180173 }
174+ }
175+
176+ static void *
177+ acquire_semaphore (void * p )
178+ {
179+ semian_resource_t * res = (semian_resource_t * ) p ;
180+ acquire_semaphore_internal (res , 0 );
181+ return NULL ;
182+ }
183+
184+ // Eagerly attempt to acquire the semaphore
185+ static bool
186+ try_acquire_semaphore (void * p )
187+ {
188+ semian_resource_t * res = (semian_resource_t * ) p ;
189+ acquire_semaphore_internal (res , IPC_NOWAIT );
190+ return !res -> error ;
191+ }
192+
193+ void *
194+ acquire_semaphore_without_gvl (void * p )
195+ {
196+ if (!try_acquire_semaphore (p )) {
197+ WITHOUT_GVL (acquire_semaphore , p , RUBY_UBF_IO , NULL );
198+ }
181199 return NULL ;
182200}
183201
0 commit comments