[pypy-commit] pypy stm-thread-2: Split interp_signal in three. rlib/rsignal is like on trunk. sigaction.py is the non-stm action classes.
arigo
noreply at buildbot.pypy.org
Sat Jan 26 17:23:42 CET 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread-2
Changeset: r60506:ff1b216bf13d
Date: 2013-01-26 17:22 +0100
http://bitbucket.org/pypy/pypy/changeset/ff1b216bf13d/
Log: Split interp_signal in three. rlib/rsignal is like on trunk.
sigaction.py is the non-stm action classes.
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -351,6 +351,8 @@
assert isinstance(action, PeriodicAsyncAction)
self._periodic_actions.append(action)
if use_bytecode_counter:
+ assert not action.space.config.translation.stm, (
+ "Cannot use the bytecode counter with STM")
self.has_bytecode_counter = True
self._rebuild_action_dispatcher()
diff --git a/pypy/module/signal/__init__.py b/pypy/module/signal/__init__.py
--- a/pypy/module/signal/__init__.py
+++ b/pypy/module/signal/__init__.py
@@ -30,9 +30,9 @@
}
def buildloaders(cls):
- from pypy.module.signal import interp_signal
- for name in interp_signal.signal_names:
- signum = getattr(interp_signal, name)
+ from pypy.rlib import rsignal
+ for name in rsignal.signal_names:
+ signum = getattr(rsignal, name)
if signum is not None:
Module.interpleveldefs[name] = 'space.wrap(%d)' % (signum,)
super(Module, cls).buildloaders()
@@ -40,11 +40,11 @@
def __init__(self, space, *args):
"NOT_RPYTHON"
- from pypy.module.signal import interp_signal
+ from pypy.module.signal import sigaction
MixedModule.__init__(self, space, *args)
# add the signal-checking callback as an action on the space
- space.check_signal_action = interp_signal.CheckSignalAction(space)
+ space.check_signal_action = sigaction.CheckSignalAction(space)
space.actionflag.register_periodic_action(space.check_signal_action,
use_bytecode_counter=False)
- space.actionflag.__class__ = interp_signal.SignalActionFlag
+ space.actionflag.__class__ = sigaction.SignalActionFlag
# xxx yes I know the previous line is a hack
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -1,228 +1,10 @@
from __future__ import with_statement
from pypy.interpreter.error import OperationError, exception_from_errno
-from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
-from pypy.interpreter.executioncontext import PeriodicAsyncAction
from pypy.interpreter.gateway import unwrap_spec
-import signal as cpy_signal
from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rpython.tool import rffi_platform
-from pypy.translator.tool.cbuild import ExternalCompilationInfo
-import py
-import sys
-from pypy.tool import autopath
from pypy.rlib import jit, rposix
-from pypy.rlib.rarithmetic import intmask, is_valid_int
-
-def setup():
- for key, value in cpy_signal.__dict__.items():
- if (key.startswith('SIG') or key.startswith('CTRL_')) and \
- is_valid_int(value) and \
- key != 'SIG_DFL' and key != 'SIG_IGN':
- globals()[key] = value
- yield key
-
-NSIG = cpy_signal.NSIG
-SIG_DFL = cpy_signal.SIG_DFL
-SIG_IGN = cpy_signal.SIG_IGN
-signal_names = list(setup())
-signal_values = {}
-for key in signal_names:
- signal_values[globals()[key]] = None
-if sys.platform == 'win32' and not hasattr(cpy_signal,'CTRL_C_EVENT'):
- # XXX Hack to revive values that went missing,
- # Remove this once we are sure the host cpy module has them.
- signal_values[0] = None
- signal_values[1] = None
- signal_names.append('CTRL_C_EVENT')
- signal_names.append('CTRL_BREAK_EVENT')
- CTRL_C_EVENT = 0
- CTRL_BREAK_EVENT = 1
-includes = ['stdlib.h', 'src/signals.h']
-if sys.platform != 'win32':
- includes.append('sys/time.h')
-
-cdir = py.path.local(autopath.pypydir).join('translator', 'c')
-
-eci = ExternalCompilationInfo(
- includes = includes,
- separate_module_files = [cdir / 'src' / 'signals.c'],
- include_dirs = [str(cdir)],
- export_symbols = ['pypysig_poll', 'pypysig_default',
- 'pypysig_ignore', 'pypysig_setflag',
- 'pypysig_reinstall',
- 'pypysig_set_wakeup_fd',
- 'pypysig_getaddr_occurred'],
-)
-
-class CConfig:
- _compilation_info_ = eci
-
-if sys.platform != 'win32':
- for name in """ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF""".split():
- setattr(CConfig, name, rffi_platform.DefinedConstantInteger(name))
-
- CConfig.timeval = rffi_platform.Struct(
- 'struct timeval',
- [('tv_sec', rffi.LONG),
- ('tv_usec', rffi.LONG)])
-
- CConfig.itimerval = rffi_platform.Struct(
- 'struct itimerval',
- [('it_value', CConfig.timeval),
- ('it_interval', CConfig.timeval)])
-
-for k, v in rffi_platform.configure(CConfig).items():
- globals()[k] = v
-
-def external(name, args, result, **kwds):
- return rffi.llexternal(name, args, result, compilation_info=eci,
- sandboxsafe=True, **kwds)
-
-pypysig_ignore = external('pypysig_ignore', [rffi.INT], lltype.Void)
-pypysig_default = external('pypysig_default', [rffi.INT], lltype.Void)
-pypysig_setflag = external('pypysig_setflag', [rffi.INT], lltype.Void)
-pypysig_reinstall = external('pypysig_reinstall', [rffi.INT], lltype.Void)
-pypysig_set_wakeup_fd = external('pypysig_set_wakeup_fd', [rffi.INT], rffi.INT)
-pypysig_poll = external('pypysig_poll', [], rffi.INT, threadsafe=False)
-# don't bother releasing the GIL around a call to pypysig_poll: it's
-# pointless and a performance issue
-
-# don't use rffi.LONGP because the JIT doesn't support raw arrays so far
-struct_name = 'pypysig_long_struct'
-LONG_STRUCT = lltype.Struct(struct_name, ('c_value', lltype.Signed),
- hints={'c_name' : struct_name, 'external' : 'C'})
-del struct_name
-
-pypysig_getaddr_occurred = external('pypysig_getaddr_occurred', [],
- lltype.Ptr(LONG_STRUCT), _nowrapper=True,
- elidable_function=True)
-c_alarm = external('alarm', [rffi.INT], rffi.INT)
-c_pause = external('pause', [], rffi.INT, threadsafe=True)
-c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT)
-
-if sys.platform != 'win32':
- itimervalP = rffi.CArrayPtr(itimerval)
- c_setitimer = external('setitimer',
- [rffi.INT, itimervalP, itimervalP], rffi.INT)
- c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)
-
-
-class SignalActionFlag(AbstractActionFlag):
- # This class uses the C-level pypysig_counter variable as the tick
- # counter. The C-level signal handler will reset it to -1 whenever
- # a signal is received.
-
- def get_ticker(self):
- p = pypysig_getaddr_occurred()
- return p.c_value
-
- def reset_ticker(self, value):
- p = pypysig_getaddr_occurred()
- p.c_value = value
-
- def decrement_ticker(self, by):
- p = pypysig_getaddr_occurred()
- value = p.c_value
- if self.has_bytecode_counter: # this 'if' is constant-folded
- if jit.isconstant(by) and by == 0:
- pass # normally constant-folded too
- else:
- value -= by
- p.c_value = value
- return value
-
-
-class CheckSignalAction(PeriodicAsyncAction):
- """An action that is automatically invoked when a signal is received."""
-
- def __init__(self, space):
- AsyncAction.__init__(self, space)
- self.handlers_w = {}
- if space.config.objspace.usemodules.thread:
- # need a helper action in case signals arrive in a non-main thread
- self.pending_signals = {}
- self.reissue_signal_action = ReissueSignalAction(space)
- else:
- self.reissue_signal_action = None
-
- @jit.dont_look_inside
- def perform(self, executioncontext, frame):
- while True:
- n = pypysig_poll()
- if n < 0:
- break
- self.perform_signal(executioncontext, n)
-
- @jit.dont_look_inside
- def perform_signal(self, executioncontext, n):
- if self.reissue_signal_action is None:
- # no threads: we can report the signal immediately
- self.report_signal(n)
- else:
- main_ec = self.space.threadlocals.getmainthreadvalue()
- if executioncontext is main_ec:
- # running in the main thread: we can report the
- # signal immediately
- self.report_signal(n)
- else:
- # running in another thread: we need to hack a bit
- self.pending_signals[n] = None
- self.reissue_signal_action.fire_after_thread_switch()
-
- @jit.dont_look_inside
- def set_interrupt(self):
- "Simulates the effect of a SIGINT signal arriving"
- ec = self.space.getexecutioncontext()
- self.perform_signal(ec, cpy_signal.SIGINT)
-
- @jit.dont_look_inside
- def report_signal(self, n):
- try:
- w_handler = self.handlers_w[n]
- except KeyError:
- return # no handler, ignore signal
- space = self.space
- if not space.is_true(space.callable(w_handler)):
- return # w_handler is SIG_IGN or SIG_DFL?
- # re-install signal handler, for OSes that clear it
- pypysig_reinstall(n)
- # invoke the app-level handler
- ec = space.getexecutioncontext()
- w_frame = space.wrap(ec.gettopframe_nohidden())
- space.call_function(w_handler, space.wrap(n), w_frame)
-
- @jit.dont_look_inside
- def report_pending_signals(self):
- # XXX this logic isn't so complicated but I have no clue how
- # to test it :-(
- pending_signals = self.pending_signals.keys()
- self.pending_signals.clear()
- try:
- while pending_signals:
- self.report_signal(pending_signals.pop())
- finally:
- # in case of exception, put the undelivered signals back
- # into the dict instead of silently swallowing them
- if pending_signals:
- for n in pending_signals:
- self.pending_signals[n] = None
- self.reissue_signal_action.fire()
-
-
-class ReissueSignalAction(AsyncAction):
- """A special action to help deliver signals to the main thread. If
- a non-main thread caught a signal, this action fires after every
- thread switch until we land in the main thread.
- """
-
- def perform(self, executioncontext, frame):
- main_ec = self.space.threadlocals.getmainthreadvalue()
- if executioncontext is main_ec:
- # now running in the main thread: we can really report the signals
- self.space.check_signal_action.report_pending_signals()
- else:
- # still running in some other thread: try again later
- self.fire_after_thread_switch()
+from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rsignal import *
@unwrap_spec(signum=int)
diff --git a/pypy/module/signal/sigaction.py b/pypy/module/signal/sigaction.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/signal/sigaction.py
@@ -0,0 +1,123 @@
+from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
+from pypy.interpreter.executioncontext import PeriodicAsyncAction
+from pypy.rlib import jit
+from pypy.rlib.rsignal import pypysig_getaddr_occurred
+from pypy.rlib.rsignal import pypysig_poll, pypysig_reinstall
+
+
+class SignalActionFlag(AbstractActionFlag):
+ # This class uses the C-level pypysig_counter variable as the tick
+ # counter. The C-level signal handler will reset it to -1 whenever
+ # a signal is received.
+
+ def get_ticker(self):
+ p = pypysig_getaddr_occurred()
+ return p.c_value
+
+ def reset_ticker(self, value):
+ p = pypysig_getaddr_occurred()
+ p.c_value = value
+
+ def decrement_ticker(self, by):
+ p = pypysig_getaddr_occurred()
+ value = p.c_value
+ if self.has_bytecode_counter: # this 'if' is constant-folded
+ if jit.isconstant(by) and by == 0:
+ pass # normally constant-folded too
+ else:
+ value -= by
+ p.c_value = value
+ return value
+
+
+class CheckSignalAction(PeriodicAsyncAction):
+ """An action that is automatically invoked when a signal is received."""
+
+ def __init__(self, space):
+ AsyncAction.__init__(self, space)
+ self.handlers_w = {}
+ if space.config.objspace.usemodules.thread:
+ # need a helper action in case signals arrive in a non-main thread
+ self.pending_signals = {}
+ self.reissue_signal_action = ReissueSignalAction(space)
+ else:
+ self.reissue_signal_action = None
+
+ @jit.dont_look_inside
+ def perform(self, executioncontext, frame):
+ while True:
+ n = pypysig_poll()
+ if n < 0:
+ break
+ self.perform_signal(executioncontext, n)
+
+ @jit.dont_look_inside
+ def perform_signal(self, executioncontext, n):
+ if self.reissue_signal_action is None:
+ # no threads: we can report the signal immediately
+ self.report_signal(n)
+ else:
+ main_ec = self.space.threadlocals.getmainthreadvalue()
+ if executioncontext is main_ec:
+ # running in the main thread: we can report the
+ # signal immediately
+ self.report_signal(n)
+ else:
+ # running in another thread: we need to hack a bit
+ self.pending_signals[n] = None
+ self.reissue_signal_action.fire_after_thread_switch()
+
+ @jit.dont_look_inside
+ def set_interrupt(self):
+ "Simulates the effect of a SIGINT signal arriving"
+ ec = self.space.getexecutioncontext()
+ self.perform_signal(ec, cpy_signal.SIGINT)
+
+ @jit.dont_look_inside
+ def report_signal(self, n):
+ try:
+ w_handler = self.handlers_w[n]
+ except KeyError:
+ return # no handler, ignore signal
+ space = self.space
+ if not space.is_true(space.callable(w_handler)):
+ return # w_handler is SIG_IGN or SIG_DFL?
+ # re-install signal handler, for OSes that clear it
+ pypysig_reinstall(n)
+ # invoke the app-level handler
+ ec = space.getexecutioncontext()
+ w_frame = space.wrap(ec.gettopframe_nohidden())
+ space.call_function(w_handler, space.wrap(n), w_frame)
+
+ @jit.dont_look_inside
+ def report_pending_signals(self):
+ # XXX this logic isn't so complicated but I have no clue how
+ # to test it :-(
+ pending_signals = self.pending_signals.keys()
+ self.pending_signals.clear()
+ try:
+ while pending_signals:
+ self.report_signal(pending_signals.pop())
+ finally:
+ # in case of exception, put the undelivered signals back
+ # into the dict instead of silently swallowing them
+ if pending_signals:
+ for n in pending_signals:
+ self.pending_signals[n] = None
+ self.reissue_signal_action.fire()
+
+
+class ReissueSignalAction(AsyncAction):
+ """A special action to help deliver signals to the main thread. If
+ a non-main thread caught a signal, this action fires after every
+ thread switch until we land in the main thread.
+ """
+
+ def perform(self, executioncontext, frame):
+ main_ec = self.space.threadlocals.getmainthreadvalue()
+ if executioncontext is main_ec:
+ # now running in the main thread: we can really report the signals
+ self.space.check_signal_action.report_pending_signals()
+ else:
+ # still running in some other thread: try again later
+ self.fire_after_thread_switch()
diff --git a/pypy/rlib/rsignal.py b/pypy/rlib/rsignal.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/rsignal.py
@@ -0,0 +1,101 @@
+import signal as cpy_signal
+import sys
+import py
+from pypy.tool import autopath
+from pypy.rpython.tool import rffi_platform
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rlib.rarithmetic import is_valid_int
+
+def setup():
+ for key, value in cpy_signal.__dict__.items():
+ if (key.startswith('SIG') or key.startswith('CTRL_')) and \
+ is_valid_int(value) and \
+ key != 'SIG_DFL' and key != 'SIG_IGN':
+ globals()[key] = value
+ yield key
+
+NSIG = cpy_signal.NSIG
+SIG_DFL = cpy_signal.SIG_DFL
+SIG_IGN = cpy_signal.SIG_IGN
+signal_names = list(setup())
+signal_values = {}
+for key in signal_names:
+ signal_values[globals()[key]] = None
+if sys.platform == 'win32' and not hasattr(cpy_signal,'CTRL_C_EVENT'):
+ # XXX Hack to revive values that went missing,
+ # Remove this once we are sure the host cpy module has them.
+ signal_values[0] = None
+ signal_values[1] = None
+ signal_names.append('CTRL_C_EVENT')
+ signal_names.append('CTRL_BREAK_EVENT')
+ CTRL_C_EVENT = 0
+ CTRL_BREAK_EVENT = 1
+includes = ['stdlib.h', 'src/signals.h']
+if sys.platform != 'win32':
+ includes.append('sys/time.h')
+
+cdir = py.path.local(autopath.pypydir).join('translator', 'c')
+
+eci = ExternalCompilationInfo(
+ includes = includes,
+ separate_module_files = [cdir / 'src' / 'signals.c'],
+ include_dirs = [str(cdir)],
+ export_symbols = ['pypysig_poll', 'pypysig_default',
+ 'pypysig_ignore', 'pypysig_setflag',
+ 'pypysig_reinstall',
+ 'pypysig_set_wakeup_fd',
+ 'pypysig_getaddr_occurred'],
+)
+
+class CConfig:
+ _compilation_info_ = eci
+
+if sys.platform != 'win32':
+ for name in """ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF""".split():
+ setattr(CConfig, name, rffi_platform.DefinedConstantInteger(name))
+
+ CConfig.timeval = rffi_platform.Struct(
+ 'struct timeval',
+ [('tv_sec', rffi.LONG),
+ ('tv_usec', rffi.LONG)])
+
+ CConfig.itimerval = rffi_platform.Struct(
+ 'struct itimerval',
+ [('it_value', CConfig.timeval),
+ ('it_interval', CConfig.timeval)])
+
+for k, v in rffi_platform.configure(CConfig).items():
+ globals()[k] = v
+
+def external(name, args, result, **kwds):
+ return rffi.llexternal(name, args, result, compilation_info=eci,
+ sandboxsafe=True, **kwds)
+
+pypysig_ignore = external('pypysig_ignore', [rffi.INT], lltype.Void)
+pypysig_default = external('pypysig_default', [rffi.INT], lltype.Void)
+pypysig_setflag = external('pypysig_setflag', [rffi.INT], lltype.Void)
+pypysig_reinstall = external('pypysig_reinstall', [rffi.INT], lltype.Void)
+pypysig_set_wakeup_fd = external('pypysig_set_wakeup_fd', [rffi.INT], rffi.INT)
+pypysig_poll = external('pypysig_poll', [], rffi.INT, threadsafe=False)
+# don't bother releasing the GIL around a call to pypysig_poll: it's
+# pointless and a performance issue
+
+# don't use rffi.LONGP because the JIT doesn't support raw arrays so far
+struct_name = 'pypysig_long_struct'
+LONG_STRUCT = lltype.Struct(struct_name, ('c_value', lltype.Signed),
+ hints={'c_name' : struct_name, 'external' : 'C'})
+del struct_name
+
+pypysig_getaddr_occurred = external('pypysig_getaddr_occurred', [],
+ lltype.Ptr(LONG_STRUCT), _nowrapper=True,
+ elidable_function=True)
+c_alarm = external('alarm', [rffi.INT], rffi.INT)
+c_pause = external('pause', [], rffi.INT, threadsafe=True)
+c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT)
+
+if sys.platform != 'win32':
+ itimervalP = rffi.CArrayPtr(itimerval)
+ c_setitimer = external('setitimer',
+ [rffi.INT, itimervalP, itimervalP], rffi.INT)
+ c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)
More information about the pypy-commit
mailing list