Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r92085:2d3c081aa72d Date: 2017-08-05 08:58 +0200 http://bitbucket.org/pypy/pypy/changeset/2d3c081aa72d/
Log: Issue #2623 Tweak the signals logic to avoid the possibly-harmful optimization of pypysig_occurred. diff --git a/rpython/translator/c/src/signals.c b/rpython/translator/c/src/signals.c --- a/rpython/translator/c/src/signals.c +++ b/rpython/translator/c/src/signals.c @@ -31,11 +31,11 @@ # endif #endif +#define N_LONGBITS (8 * sizeof(long)) +#define N_LONGSIG ((NSIG - 1) / N_LONGBITS + 1) + struct pypysig_long_struct pypysig_counter = {0}; -static char volatile pypysig_flags[NSIG] = {0}; -static int volatile pypysig_occurred = 0; -/* pypysig_occurred is only an optimization: it tells if any - pypysig_flags could be set. */ +static long volatile pypysig_flags_bits[N_LONGSIG]; static int wakeup_fd = -1; static int wakeup_with_nul_byte = 1; @@ -73,12 +73,28 @@ #endif } +#ifdef _WIN32 +#define atomic_cas(ptr, oldv, newv) (InterlockedCompareExchange(ptr, \ + newv, oldv) == (oldv)) +#else +#define atomic_cas(ptr, oldv, newv) __sync_bool_compare_and_swap(ptr, \ + oldv, newv) +#endif + void pypysig_pushback(int signum) { if (0 <= signum && signum < NSIG) { - pypysig_flags[signum] = 1; - pypysig_occurred = 1; + int ok, index = signum / N_LONGBITS; + unsigned long bitmask = 1UL << (signum % N_LONGBITS); + do + { + long value = pypysig_flags_bits[index]; + if (value & bitmask) + break; /* already set */ + ok = atomic_cas(&pypysig_flags_bits[index], value, value | bitmask); + } while (!ok); + pypysig_counter.value = -1; } } @@ -161,19 +177,22 @@ int pypysig_poll(void) { - if (pypysig_occurred) - { - int i; - pypysig_occurred = 0; - for (i=0; i<NSIG; i++) - if (pypysig_flags[i]) - { - pypysig_flags[i] = 0; - pypysig_occurred = 1; /* maybe another signal is pending */ - return i; - } + int index; + for (index = 0; index < N_LONGSIG; index++) { + long value; + retry: + value = pypysig_flags_bits[index]; + if (value != 0L) { + int j = 0; + while ((value & (1UL << j)) == 0) + j++; + if (!atomic_cas(&pypysig_flags_bits[index], value, + value & ~(1UL << j))) + goto retry; + return index * N_LONGBITS + j; + } } - return -1; /* no pending signal */ + return -1; /* no pending signal */ } int pypysig_set_wakeup_fd(int fd, int with_nul_byte) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit