about summary refs log tree commit diff
path: root/src/signal
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-02-12 00:22:29 -0500
committerRich Felker <dalias@aerifal.cx>2011-02-12 00:22:29 -0500
commit0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 (patch)
tree6eaef0d8a720fa3da580de87b647fff796fe80b3 /src/signal
downloadmusl-0b44a0315b47dd8eced9f3b7f31580cf14bbfc01.tar.gz
musl-0b44a0315b47dd8eced9f3b7f31580cf14bbfc01.tar.xz
musl-0b44a0315b47dd8eced9f3b7f31580cf14bbfc01.zip
initial check-in, version 0.5.0 v0.5.0
Diffstat (limited to 'src/signal')
-rw-r--r--src/signal/bsd_signal.c6
-rw-r--r--src/signal/getitimer.c12
-rw-r--r--src/signal/i386/sigsetjmp.s13
-rw-r--r--src/signal/kill.c7
-rw-r--r--src/signal/killpg.c11
-rw-r--r--src/signal/raise.c7
-rw-r--r--src/signal/setitimer.c15
-rw-r--r--src/signal/sigaction.c48
-rw-r--r--src/signal/sigaddset.c13
-rw-r--r--src/signal/sigaltstack.c8
-rw-r--r--src/signal/sigdelset.c13
-rw-r--r--src/signal/sigemptyset.c8
-rw-r--r--src/signal/sigfillset.c8
-rw-r--r--src/signal/sighold.c11
-rw-r--r--src/signal/sigignore.c12
-rw-r--r--src/signal/siginterrupt.c13
-rw-r--r--src/signal/sigismember.c12
-rw-r--r--src/signal/siglongjmp.c12
-rw-r--r--src/signal/signal.c13
-rw-r--r--src/signal/sigpause.c11
-rw-r--r--src/signal/sigpending.c7
-rw-r--r--src/signal/sigprocmask.c23
-rw-r--r--src/signal/sigqueue.c14
-rw-r--r--src/signal/sigrelse.c11
-rw-r--r--src/signal/sigrtmax.c4
-rw-r--r--src/signal/sigrtmin.c4
-rw-r--r--src/signal/sigset.c28
-rw-r--r--src/signal/sigsetjmp.c17
-rw-r--r--src/signal/sigsuspend.c7
-rw-r--r--src/signal/sigtimedwait.c12
-rw-r--r--src/signal/sigwait.c11
-rw-r--r--src/signal/sigwaitinfo.c7
32 files changed, 398 insertions, 0 deletions
diff --git a/src/signal/bsd_signal.c b/src/signal/bsd_signal.c
new file mode 100644
index 00000000..0b9a6855
--- /dev/null
+++ b/src/signal/bsd_signal.c
@@ -0,0 +1,6 @@
+#include <signal.h>
+
+void (*bsd_signal(int sig, void (*func)(int)))(int)
+{
+	return signal(sig, func);
+}
diff --git a/src/signal/getitimer.c b/src/signal/getitimer.c
new file mode 100644
index 00000000..222d113e
--- /dev/null
+++ b/src/signal/getitimer.c
@@ -0,0 +1,12 @@
+#include <sys/time.h>
+#include "syscall.h"
+
+int getitimer(int which, struct itimerval *old)
+{
+	int ret;
+	long kold[4];
+
+	if (!(ret = syscall2(__NR_getitimer, which, (long)&kold)))
+		*old = (struct itimerval){ { kold[0], kold[1] }, { kold[2], kold[3] } };
+	return ret;
+}
diff --git a/src/signal/i386/sigsetjmp.s b/src/signal/i386/sigsetjmp.s
new file mode 100644
index 00000000..0e7eefb0
--- /dev/null
+++ b/src/signal/i386/sigsetjmp.s
@@ -0,0 +1,13 @@
+.global sigsetjmp
+sigsetjmp:
+	mov 4(%esp),%eax
+	mov 8(%esp),%ecx
+	mov %ecx,24(%eax)
+	jecxz 1f
+	add $28,%eax
+	push %eax
+	push $0
+	push $2
+	call sigprocmask
+	add $12,%esp
+1:	jmp setjmp
diff --git a/src/signal/kill.c b/src/signal/kill.c
new file mode 100644
index 00000000..cc4b51e1
--- /dev/null
+++ b/src/signal/kill.c
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int kill(pid_t pid, int sig)
+{
+	return syscall2(__NR_kill, pid, sig);
+}
diff --git a/src/signal/killpg.c b/src/signal/killpg.c
new file mode 100644
index 00000000..315ed447
--- /dev/null
+++ b/src/signal/killpg.c
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <errno.h>
+
+int killpg(pid_t pgid, int sig)
+{
+	if (pgid < 0) {
+		errno = EINVAL;
+		return -1;
+	}
+	return kill(-pgid, sig);
+}
diff --git a/src/signal/raise.c b/src/signal/raise.c
new file mode 100644
index 00000000..52f8b428
--- /dev/null
+++ b/src/signal/raise.c
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int raise(int sig)
+{
+	return __syscall_kill(__syscall_getpid(), sig);
+}
diff --git a/src/signal/setitimer.c b/src/signal/setitimer.c
new file mode 100644
index 00000000..cacab036
--- /dev/null
+++ b/src/signal/setitimer.c
@@ -0,0 +1,15 @@
+#include <sys/time.h>
+#include "syscall.h"
+
+int setitimer(int which, const struct itimerval *new, struct itimerval *old)
+{
+	int ret;
+	long knew[4] = {
+		new->it_interval.tv_sec, new->it_interval.tv_usec,
+		new->it_value.tv_sec, new->it_value.tv_usec
+	}, kold[4];
+
+	if (!(ret = syscall3(__NR_setitimer, which, (long)&knew, old ? (long)&kold : 0)) && old)
+		*old = (struct itimerval){ { kold[0], kold[1] }, { kold[2], kold[3] } };
+	return ret;
+}
diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c
new file mode 100644
index 00000000..4acd1730
--- /dev/null
+++ b/src/signal/sigaction.c
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include "syscall.h"
+#include "pthread_impl.h"
+
+static void restorer()
+{
+	syscall0(__NR_rt_sigreturn);
+}
+
+int __libc_sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
+{
+	struct {
+		void *handler;
+		unsigned long flags;
+		void (*restorer)(void);
+		sigset_t mask;
+	} ksa, kold;
+	long pksa=0, pkold=0;
+	if (sa) {
+		ksa.handler = sa->sa_handler;
+		ksa.flags = sa->sa_flags;
+		ksa.restorer = restorer;
+		ksa.mask = sa->sa_mask;
+		pksa = (long)&ksa;
+	}
+	if (old) pkold = (long)&kold;
+	if (syscall4(__NR_rt_sigaction, sig, pksa, pkold, 8))
+		return -1;
+	if (old) {
+		old->sa_handler = kold.handler;
+		old->sa_flags = kold.flags;
+		old->sa_mask = kold.mask;
+	}
+	return 0;
+}
+
+int __sigaction(int sig, const struct sigaction *sa, struct sigaction *old)
+{
+	if (sig == SIGCANCEL || sig == SIGSYSCALL) {
+		errno = EINVAL;
+		return -1;
+	}
+	return __libc_sigaction(sig, sa, old);
+}
+
+weak_alias(__sigaction, sigaction);
diff --git a/src/signal/sigaddset.c b/src/signal/sigaddset.c
new file mode 100644
index 00000000..23e655db
--- /dev/null
+++ b/src/signal/sigaddset.c
@@ -0,0 +1,13 @@
+#include <signal.h>
+#include <errno.h>
+
+int sigaddset(sigset_t *set, int sig)
+{
+	unsigned s = sig-1;
+	if (s >= 8*sizeof(sigset_t)) {
+		errno = EINVAL;
+		return -1;
+	}
+	set->__bits[s/8/sizeof *set->__bits] |= 1UL<<(s&8*sizeof *set->__bits-1);
+	return 0;
+}
diff --git a/src/signal/sigaltstack.c b/src/signal/sigaltstack.c
new file mode 100644
index 00000000..3cc2d456
--- /dev/null
+++ b/src/signal/sigaltstack.c
@@ -0,0 +1,8 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigaltstack(const stack_t *ss, stack_t *old)
+{
+	/* depends on kernel struct matching */
+	return syscall2(__NR_sigaltstack, (long)ss, (long)old);
+}
diff --git a/src/signal/sigdelset.c b/src/signal/sigdelset.c
new file mode 100644
index 00000000..14042fb8
--- /dev/null
+++ b/src/signal/sigdelset.c
@@ -0,0 +1,13 @@
+#include <signal.h>
+#include <errno.h>
+
+int sigdelset(sigset_t *set, int sig)
+{
+	unsigned s = sig-1;
+	if (s >= 8*sizeof(sigset_t)) {
+		errno = EINVAL;
+		return -1;
+	}
+	set->__bits[s/8/sizeof *set->__bits] &=~(1UL<<(s&8*sizeof *set->__bits-1));
+	return 0;
+}
diff --git a/src/signal/sigemptyset.c b/src/signal/sigemptyset.c
new file mode 100644
index 00000000..91f77adf
--- /dev/null
+++ b/src/signal/sigemptyset.c
@@ -0,0 +1,8 @@
+#include <signal.h>
+#include <string.h>
+
+int sigemptyset(sigset_t *set)
+{
+	memset(set, 0, sizeof *set);
+	return 0;
+}
diff --git a/src/signal/sigfillset.c b/src/signal/sigfillset.c
new file mode 100644
index 00000000..fab50a52
--- /dev/null
+++ b/src/signal/sigfillset.c
@@ -0,0 +1,8 @@
+#include <signal.h>
+#include <string.h>
+
+int sigfillset(sigset_t *set)
+{
+	memset(set, -1, sizeof *set);
+	return 0;
+}
diff --git a/src/signal/sighold.c b/src/signal/sighold.c
new file mode 100644
index 00000000..5b0f6b18
--- /dev/null
+++ b/src/signal/sighold.c
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sighold(int sig)
+{
+	sigset_t mask;
+
+	sigemptyset(&mask);
+	if (sigaddset(&mask, sig) < 0) return -1;
+	return sigprocmask(SIG_BLOCK, &mask, NULL);
+}
diff --git a/src/signal/sigignore.c b/src/signal/sigignore.c
new file mode 100644
index 00000000..98dff61e
--- /dev/null
+++ b/src/signal/sigignore.c
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sigignore(int sig)
+{
+	struct sigaction sa;
+
+	sigemptyset(&sa.sa_mask);
+	sa.sa_handler = SIG_IGN;
+	sa.sa_flags = 0;
+	return sigaction(sig, &sa, NULL);
+}
diff --git a/src/signal/siginterrupt.c b/src/signal/siginterrupt.c
new file mode 100644
index 00000000..60b34054
--- /dev/null
+++ b/src/signal/siginterrupt.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include <signal.h>
+
+int siginterrupt(int sig, int flag)
+{
+	struct sigaction sa;
+
+	sigaction(sig, NULL, &sa);
+	if (flag) sa.sa_flags &= ~SA_RESTART;
+	else sa.sa_flags |= SA_RESTART;
+
+	return sigaction(sig, &sa, NULL);
+}
diff --git a/src/signal/sigismember.c b/src/signal/sigismember.c
new file mode 100644
index 00000000..afd29e52
--- /dev/null
+++ b/src/signal/sigismember.c
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include <errno.h>
+
+int sigismember(const sigset_t *set, int sig)
+{
+	unsigned s = sig-1;
+	if (s >= 8*sizeof(sigset_t)) {
+		errno = EINVAL;
+		return -1;
+	}
+	return !!(set->__bits[s/8/sizeof *set->__bits] & 1UL<<(s&8*sizeof *set->__bits-1));
+}
diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c
new file mode 100644
index 00000000..33ac30ea
--- /dev/null
+++ b/src/signal/siglongjmp.c
@@ -0,0 +1,12 @@
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+
+void siglongjmp(sigjmp_buf buf, int ret)
+{
+	long *flag = buf + sizeof(jmp_buf)/sizeof(long);
+	sigset_t *mask = (void *)(flag + 1);
+	if (*flag)
+		sigprocmask (SIG_SETMASK, mask, NULL);
+	longjmp((void *)buf, ret);
+}
diff --git a/src/signal/signal.c b/src/signal/signal.c
new file mode 100644
index 00000000..08902760
--- /dev/null
+++ b/src/signal/signal.c
@@ -0,0 +1,13 @@
+#include <signal.h>
+#include <stddef.h>
+#include "syscall.h"
+
+int __sigaction(int, const struct sigaction *, struct sigaction *);
+
+void (*signal(int sig, void (*func)(int)))(int)
+{
+	struct sigaction sa = { .sa_handler = func, .sa_flags = SA_RESTART };
+	if (__sigaction(sig, &sa, &sa) < 0)
+		return SIG_ERR;
+	return sa.sa_handler;
+}
diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c
new file mode 100644
index 00000000..263c00f5
--- /dev/null
+++ b/src/signal/sigpause.c
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sigpause(int sig)
+{
+	sigset_t mask;
+
+	if (sigprocmask(0, NULL, &mask) < 0 || sigdelset(&mask, sig) < 0)
+		return -1;
+	return sigsuspend(&mask);
+}
diff --git a/src/signal/sigpending.c b/src/signal/sigpending.c
new file mode 100644
index 00000000..7deda256
--- /dev/null
+++ b/src/signal/sigpending.c
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigpending(sigset_t *set)
+{
+	return syscall2(__NR_rt_sigpending, (long)set, SYSCALL_SIGSET_SIZE);
+}
diff --git a/src/signal/sigprocmask.c b/src/signal/sigprocmask.c
new file mode 100644
index 00000000..e89f8765
--- /dev/null
+++ b/src/signal/sigprocmask.c
@@ -0,0 +1,23 @@
+#include <signal.h>
+#include "syscall.h"
+#include "libc.h"
+
+int __libc_sigprocmask(int how, const sigset_t *set, sigset_t *old)
+{
+	return syscall4(__NR_rt_sigprocmask, how, (long)set, (long)old, 8);
+}
+
+int __sigprocmask(int how, const sigset_t *set, sigset_t *old)
+{
+	sigset_t tmp;
+	/* Quickly mask out bits 32 and 33 (thread control signals) */
+	if (0 && how != SIG_UNBLOCK && (set->__bits[4/sizeof *set->__bits] & 3UL<<(32&8*sizeof *set->__bits-1))) {
+		tmp = *set;
+		set = &tmp;
+		tmp.__bits[4/sizeof *set->__bits] &= ~(3UL<<(32&8*sizeof *set->__bits-1));
+	}
+	return __libc_sigprocmask(how, set, old);
+}
+
+weak_alias(__sigprocmask, sigprocmask);
+weak_alias(__sigprocmask, pthread_sigmask);
diff --git a/src/signal/sigqueue.c b/src/signal/sigqueue.c
new file mode 100644
index 00000000..ce3abf6c
--- /dev/null
+++ b/src/signal/sigqueue.c
@@ -0,0 +1,14 @@
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include "syscall.h"
+
+int sigqueue(pid_t pid, int sig, const union sigval value)
+{
+	siginfo_t si = {
+		.si_signo = sig,
+		.si_code = -1,
+		.si_value = value,
+	};
+	return syscall3(__NR_rt_sigqueueinfo, pid, sig, (long)&si);
+}
diff --git a/src/signal/sigrelse.c b/src/signal/sigrelse.c
new file mode 100644
index 00000000..b0b3024b
--- /dev/null
+++ b/src/signal/sigrelse.c
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int sigrelse(int sig)
+{
+	sigset_t mask;
+
+	sigemptyset(&mask);
+	if (sigaddset(&mask, sig) < 0) return -1;
+	return sigprocmask(SIG_UNBLOCK, &mask, NULL);
+}
diff --git a/src/signal/sigrtmax.c b/src/signal/sigrtmax.c
new file mode 100644
index 00000000..0ef29873
--- /dev/null
+++ b/src/signal/sigrtmax.c
@@ -0,0 +1,4 @@
+int __libc_current_sigrtmax()
+{
+	return 64;
+}
diff --git a/src/signal/sigrtmin.c b/src/signal/sigrtmin.c
new file mode 100644
index 00000000..7ad06d22
--- /dev/null
+++ b/src/signal/sigrtmin.c
@@ -0,0 +1,4 @@
+int __libc_current_sigrtmin()
+{
+	return 34;
+}
diff --git a/src/signal/sigset.c b/src/signal/sigset.c
new file mode 100644
index 00000000..1b6b38fd
--- /dev/null
+++ b/src/signal/sigset.c
@@ -0,0 +1,28 @@
+#include <signal.h>
+#include <stdlib.h>
+
+void (*sigset(int sig, void (*handler)(int)))(int)
+{
+	struct sigaction sa, sa_old;
+	sigset_t mask;
+
+	sigemptyset(&mask);
+	if (sigaddset(&mask, sig) < 0)
+		return SIG_ERR;
+	
+	if (handler == SIG_HOLD) {
+		if (sigaction(sig, NULL, &sa_old) < 0)
+			return SIG_ERR;
+		if (sigprocmask(SIG_BLOCK, &mask, &mask) < 0)
+			return SIG_ERR;
+	} else {
+		sa.sa_handler = handler;
+		sa.sa_flags = 0;
+		sigemptyset(&sa.sa_mask);
+		if (sigaction(sig, &sa, &sa_old) < 0)
+			return SIG_ERR;
+		if (sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
+			return SIG_ERR;
+	}
+	return sigismember(&mask, sig) ? SIG_HOLD : sa_old.sa_handler;
+}
diff --git a/src/signal/sigsetjmp.c b/src/signal/sigsetjmp.c
new file mode 100644
index 00000000..a6667a27
--- /dev/null
+++ b/src/signal/sigsetjmp.c
@@ -0,0 +1,17 @@
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+
+/* !!! This function will not work unless the compiler performs
+ * tail call optimization. Machine-specific asm versions should
+ * be created instead even though the workaround (tail call)
+ * is entirely non-machine-specific... */
+
+int sigsetjmp(sigjmp_buf buf, int save)
+{
+	long *flag = buf + sizeof(jmp_buf)/sizeof(long);
+	sigset_t *mask = (void *)(flag + 1);
+	if ((*flag = save))
+		sigprocmask (SIG_SETMASK, NULL, mask);
+	return setjmp((void *)buf);
+}
diff --git a/src/signal/sigsuspend.c b/src/signal/sigsuspend.c
new file mode 100644
index 00000000..1acdab06
--- /dev/null
+++ b/src/signal/sigsuspend.c
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigsuspend(const sigset_t *mask)
+{
+	return syscall2(__NR_rt_sigsuspend, (long)mask, sizeof(sigset_t));
+}
diff --git a/src/signal/sigtimedwait.c b/src/signal/sigtimedwait.c
new file mode 100644
index 00000000..155185de
--- /dev/null
+++ b/src/signal/sigtimedwait.c
@@ -0,0 +1,12 @@
+#include <signal.h>
+#include "syscall.h"
+
+int sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *timeout)
+{
+	long k_timeout[2];
+	if (timeout) {
+		k_timeout[0] = timeout->tv_sec;
+		k_timeout[1] = timeout->tv_nsec;
+	}
+	return syscall4(__NR_rt_sigtimedwait, (long)mask, (long)si, timeout ? (long)k_timeout : 0, SYSCALL_SIGSET_SIZE);
+}
diff --git a/src/signal/sigwait.c b/src/signal/sigwait.c
new file mode 100644
index 00000000..9569d6b0
--- /dev/null
+++ b/src/signal/sigwait.c
@@ -0,0 +1,11 @@
+#include <signal.h>
+#include <stddef.h>
+
+int sigwait(const sigset_t *mask, int *sig)
+{
+	siginfo_t si;
+	if (sigtimedwait(mask, &si, NULL) < 0)
+		return -1;
+	*sig = si.si_signo;
+	return 0;
+}
diff --git a/src/signal/sigwaitinfo.c b/src/signal/sigwaitinfo.c
new file mode 100644
index 00000000..e79feb91
--- /dev/null
+++ b/src/signal/sigwaitinfo.c
@@ -0,0 +1,7 @@
+#include <signal.h>
+#include <stddef.h>
+
+int sigwaitinfo(const sigset_t *mask, siginfo_t *si)
+{
+	return sigtimedwait(mask, si, NULL);
+}