summaryrefslogtreecommitdiffstats
path: root/signal.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-10-27 06:45:56 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-10-27 06:45:56 -0700
commit0faa7cf4c73cc7c95488ed3055dd3c693dd341bc (patch)
treeb640255b695ead0854653f68add9a16d1506566a /signal.c
parent9d02ab722536227d488a31f5d580bc41501a7f68 (diff)
downloadtxr-0faa7cf4c73cc7c95488ed3055dd3c693dd341bc.tar.gz
txr-0faa7cf4c73cc7c95488ed3055dd3c693dd341bc.tar.bz2
txr-0faa7cf4c73cc7c95488ed3055dd3c693dd341bc.zip
Reduce size of saved/restored signal masks.
On glibc, sigset_t has a ridiculous size: one kilobyte! The kernel doesn't access most of it in the sigprocmask call. Yet it blows up the size of our dynamic frames quite a lot. In this commit, we define a small_sigset_t type and use that instead. We convert to the bloated one when calling the library. * signal.c (sig_blocked_cache): Type changes to small_sigset_t. (sig_reload_cache): Retrieve signal mask with sigprocmask into a local variable, then copy a small portion from that to sig_blocked_cache. (small_sigfillset): New static function. (set_sig_handler): Local variables of sigset_t changed to small_sigset_t. (sig_mask): Arguments are pointers to small_sigset_t. Conversion to sigset_t done around the call to sigprocmask. * signal.h (copy_sigset): Inline funtion removed. (small_sigset_t): New struct type. (extended_jmp_buf): Member blocked changed to small_sigset_t. (extended_setjmp): Cast expression updated with small_sigset_t *. (extended_longjmp): Use assignment instead of copy_sigset. (sig_blocked_cache, sig_mask): Declarations updated.
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/signal.c b/signal.c
index c3b9a351..16928ab5 100644
--- a/signal.c
+++ b/signal.c
@@ -50,7 +50,7 @@
volatile sig_atomic_t async_sig_enabled = 0;
static volatile sig_atomic_t interrupt_count = 0;
-sigset_t sig_blocked_cache;
+small_sigset_t sig_blocked_cache;
static val sig_lambda[MAX_SIG];
volatile unsigned long sig_deferred;
@@ -69,7 +69,9 @@ static int is_cpu_exception(int sig)
static int sig_reload_cache(void)
{
- return sigprocmask(SIG_BLOCK, 0, &sig_blocked_cache);
+ sigset_t set;
+ return sigprocmask(SIG_BLOCK, 0, &set);
+ memcpy(&sig_blocked_cache, &set, sizeof sig_blocked_cache);
}
static void sig_handler(int sig)
@@ -246,14 +248,19 @@ static void teardown_alt_stack(void)
#endif
+static void small_sigfillset(small_sigset_t *ss)
+{
+ ss->set = (uint_ptr_t) -1;
+}
+
val set_sig_handler(val signo, val lambda)
{
static struct sigaction blank;
cnum sig = c_num(signo);
val old_lambda;
- sigset_t block, saved;
+ small_sigset_t block, saved;
- sigfillset(&block);
+ small_sigfillset(&block);
sig_mask(SIG_BLOCK, &block, &saved);
if (sig < 0 || sig >= MAX_SIG)
@@ -342,10 +349,10 @@ static void mem_clr_bits(mem_t *target, const mem_t *bits, size_t size)
*target++ &= ~*bits++;
}
-int sig_mask(int how, const sigset_t *set, sigset_t *oldset)
+int sig_mask(int how, const small_sigset_t *set, small_sigset_t *oldset)
{
- sigset_t newset;
- const sigset_t *pnew;
+ small_sigset_t newset;
+ const small_sigset_t *pnew;
switch (how) {
case SIG_SETMASK:
@@ -367,11 +374,18 @@ int sig_mask(int how, const sigset_t *set, sigset_t *oldset)
}
if (memcmp(&sig_blocked_cache, pnew, sizeof *pnew) != 0) {
+ static sigset_t blank;
+ sigset_t real_newset = blank, real_oldset;
sig_blocked_cache = *pnew;
+ int ret;
#if HAVE_VALGRIND
- VALGRIND_MAKE_MEM_DEFINED(oldset, sizeof *oldset);
+ VALGRIND_MAKE_MEM_DEFINED(real_oldset, sizeof real_oldset);
#endif
- return sigprocmask(SIG_SETMASK, &sig_blocked_cache, oldset);
+ memcpy(&real_newset, &sig_blocked_cache, sizeof sig_blocked_cache);
+ ret = sigprocmask(SIG_SETMASK, &real_newset, &real_oldset);
+ if (ret == 0 && oldset != 0)
+ memcpy(oldset, &real_oldset, sizeof *oldset);
+ return ret;
}
if (oldset != 0)