From 0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 12 Feb 2011 00:22:29 -0500 Subject: initial check-in, version 0.5.0 --- src/signal/bsd_signal.c | 6 ++++++ src/signal/getitimer.c | 12 ++++++++++++ src/signal/i386/sigsetjmp.s | 13 ++++++++++++ src/signal/kill.c | 7 +++++++ src/signal/killpg.c | 11 +++++++++++ src/signal/raise.c | 7 +++++++ src/signal/setitimer.c | 15 ++++++++++++++ src/signal/sigaction.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ src/signal/sigaddset.c | 13 ++++++++++++ src/signal/sigaltstack.c | 8 ++++++++ src/signal/sigdelset.c | 13 ++++++++++++ src/signal/sigemptyset.c | 8 ++++++++ src/signal/sigfillset.c | 8 ++++++++ src/signal/sighold.c | 11 +++++++++++ src/signal/sigignore.c | 12 ++++++++++++ src/signal/siginterrupt.c | 13 ++++++++++++ src/signal/sigismember.c | 12 ++++++++++++ src/signal/siglongjmp.c | 12 ++++++++++++ src/signal/signal.c | 13 ++++++++++++ src/signal/sigpause.c | 11 +++++++++++ src/signal/sigpending.c | 7 +++++++ src/signal/sigprocmask.c | 23 ++++++++++++++++++++++ src/signal/sigqueue.c | 14 +++++++++++++ src/signal/sigrelse.c | 11 +++++++++++ src/signal/sigrtmax.c | 4 ++++ src/signal/sigrtmin.c | 4 ++++ src/signal/sigset.c | 28 ++++++++++++++++++++++++++ src/signal/sigsetjmp.c | 17 ++++++++++++++++ src/signal/sigsuspend.c | 7 +++++++ src/signal/sigtimedwait.c | 12 ++++++++++++ src/signal/sigwait.c | 11 +++++++++++ src/signal/sigwaitinfo.c | 7 +++++++ 32 files changed, 398 insertions(+) create mode 100644 src/signal/bsd_signal.c create mode 100644 src/signal/getitimer.c create mode 100644 src/signal/i386/sigsetjmp.s create mode 100644 src/signal/kill.c create mode 100644 src/signal/killpg.c create mode 100644 src/signal/raise.c create mode 100644 src/signal/setitimer.c create mode 100644 src/signal/sigaction.c create mode 100644 src/signal/sigaddset.c create mode 100644 src/signal/sigaltstack.c create mode 100644 src/signal/sigdelset.c create mode 100644 src/signal/sigemptyset.c create mode 100644 src/signal/sigfillset.c create mode 100644 src/signal/sighold.c create mode 100644 src/signal/sigignore.c create mode 100644 src/signal/siginterrupt.c create mode 100644 src/signal/sigismember.c create mode 100644 src/signal/siglongjmp.c create mode 100644 src/signal/signal.c create mode 100644 src/signal/sigpause.c create mode 100644 src/signal/sigpending.c create mode 100644 src/signal/sigprocmask.c create mode 100644 src/signal/sigqueue.c create mode 100644 src/signal/sigrelse.c create mode 100644 src/signal/sigrtmax.c create mode 100644 src/signal/sigrtmin.c create mode 100644 src/signal/sigset.c create mode 100644 src/signal/sigsetjmp.c create mode 100644 src/signal/sigsuspend.c create mode 100644 src/signal/sigtimedwait.c create mode 100644 src/signal/sigwait.c create mode 100644 src/signal/sigwaitinfo.c (limited to 'src/signal') 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 + +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 +#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 +#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 +#include + +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 +#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 +#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 +#include +#include +#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 +#include + +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 +#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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 +#include +#include + +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 +#include +#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 +#include + +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 +#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 +#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 +#include +#include +#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 +#include + +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 +#include + +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 +#include +#include + +/* !!! 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 +#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 +#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 +#include + +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 +#include + +int sigwaitinfo(const sigset_t *mask, siginfo_t *si) +{ + return sigtimedwait(mask, si, NULL); +} -- cgit v1.2.1