aboutsummaryrefslogtreecommitdiffstats
path: root/src/signal.c
blob: bfe18b9b8d93c21a6339f5ec8c6ef2b0b82e175d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <stdio.h>
#include <string.h>

#include "litmus.h"
#include "internal.h"

/* setjmp calls are stored on a singlely link list,
 * one stack per thread.
 */
static __thread litmus_sigjmp_t *g_sigjmp_tail = 0;

void push_sigjmp(litmus_sigjmp_t *buf)
{
	buf->prev = g_sigjmp_tail;
	g_sigjmp_tail = buf;
}

litmus_sigjmp_t* pop_sigjmp(void)
{
	litmus_sigjmp_t* ret;
	ret = g_sigjmp_tail;
	g_sigjmp_tail = (ret) ? ret->prev : NULL;
	return ret;
}

static void reg_litmus_signals(unsigned long litmus_sig_mask,
		struct sigaction *pAction)
{
	int ret;

	if (litmus_sig_mask | SIG_BUDGET_MASK) { 
		ret = sigaction(SIG_BUDGET, pAction, NULL);
		check("SIG_BUDGET");
	}
	/* more signals ... */
}

void ignore_litmus_signals(unsigned long litmus_sig_mask)
{
	activate_litmus_signals(litmus_sig_mask, SIG_IGN);
}

void activate_litmus_signals(unsigned long litmus_sig_mask,
	litmus_sig_handler_t handle)
{
	struct sigaction action;
	memset(&action, 0, sizeof(action));
	action.sa_handler = handle;

	reg_litmus_signals(litmus_sig_mask, &action);
}

void activate_litmus_signal_actions(unsigned long litmus_sig_mask,
		litmus_sig_actions_t handle)
{
	struct sigaction action;
	memset(&action, 0, sizeof(action));
	action.sa_sigaction = handle;
	action.sa_flags = SA_SIGINFO;

	reg_litmus_signals(litmus_sig_mask, &action);
}

void block_litmus_signals(unsigned long litmus_sig_mask)
{
	int ret;
	sigset_t sigs;
	sigemptyset(&sigs);

	if (litmus_sig_mask | SIG_BUDGET_MASK) {
		sigaddset(&sigs, SIG_BUDGET);
	}
	/* more signals ... */

	ret = sigprocmask(SIG_BLOCK, &sigs, NULL);
	check("SIG_BLOCK litmus signals");
}

void unblock_litmus_signals(unsigned long litmus_sig_mask)
{
	int ret;
	sigset_t sigs;
	sigemptyset(&sigs);

	if (litmus_sig_mask | SIG_BUDGET_MASK) {
		sigaddset(&sigs, SIG_BUDGET);
	}
	/* more ... */

	ret = sigprocmask(SIG_UNBLOCK, &sigs, NULL);
	check("SIG_UNBLOCK litmus signals");
}


void longjmp_on_litmus_signal(int signum)
{
	/* We get signal!  Main screen turn on! */
	litmus_sigjmp_t *lit_env;
	lit_env = pop_sigjmp();
	if (lit_env) {
		/* What you say?! */
		siglongjmp(lit_env->env, signum); /* restores signal mask */
	}
	else {
		/* silently ignore the signal */
	}
}