Skip to content

Commit 15ea01c

Browse files
authored
Merge pull request #573 from Shopify/try_acquire
Attempt acquiring semaphore before releasing GVL
2 parents ce06f30 + fc34e47 commit 15ea01c

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

ext/semian/sysv_semaphores.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
#include "sysv_semaphores.h"
22
#include <time.h>
3+
#include <stdbool.h>
34

45
static key_t
56
generate_key(const char *name);
67

7-
static void *
8-
acquire_semaphore(void *p);
9-
108
static int
119
wait_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

Comments
 (0)