Annotation of linux/kernel/signal.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  *  linux/kernel/signal.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
                      7: #include <linux/sched.h>
                      8: #include <linux/kernel.h>
                      9: #include <asm/segment.h>
                     10: 
                     11: #include <signal.h>
1.1.1.3 ! root       12: #include <errno.h>
        !            13:   
1.1       root       14: int sys_sgetmask()
                     15: {
                     16:        return current->blocked;
                     17: }
                     18: 
                     19: int sys_ssetmask(int newmask)
                     20: {
                     21:        int old=current->blocked;
                     22: 
1.1.1.3 ! root       23:        current->blocked = newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));
1.1       root       24:        return old;
                     25: }
                     26: 
1.1.1.3 ! root       27: int sys_sigpending(sigset_t *set)
        !            28: {
        !            29:     /* fill in "set" with signals pending but blocked. */
        !            30:     verify_area(set,4);
        !            31:     put_fs_long(current->blocked & current->signal, (unsigned long *)set);
        !            32:     return 0;
        !            33: }
        !            34: 
        !            35: /* atomically swap in the new signal mask, and wait for a signal.
        !            36:  *
        !            37:  * we need to play some games with syscall restarting.  We get help
        !            38:  * from the syscall library interface.  Note that we need to coordinate
        !            39:  * the calling convention with the libc routine.
        !            40:  *
        !            41:  * "set" is just the sigmask as described in 1003.1-1988, 3.3.7.
        !            42:  *     It is assumed that sigset_t can be passed as a 32 bit quantity.
        !            43:  *
        !            44:  * "restart" holds a restart indication.  If it's non-zero, then we 
        !            45:  *     install the old mask, and return normally.  If it's zero, we store 
        !            46:  *     the current mask in old_mask and block until a signal comes in.
        !            47:  */
        !            48: int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)
        !            49: {
        !            50:     extern int sys_pause(void);
        !            51: 
        !            52:     if (restart) {
        !            53:        /* we're restarting */
        !            54:        current->blocked = old_mask;
        !            55:        return -EINTR;
        !            56:     }
        !            57:     /* we're not restarting.  do the work */
        !            58:     *(&restart) = 1;
        !            59:     *(&old_mask) = current->blocked;
        !            60:     current->blocked = set;
        !            61:     (void) sys_pause();                        /* return after a signal arrives */
        !            62:     return -ERESTARTNOINTR;            /* handle the signal, and come back */
        !            63: }
        !            64: 
1.1       root       65: static inline void save_old(char * from,char * to)
                     66: {
                     67:        int i;
                     68: 
                     69:        verify_area(to, sizeof(struct sigaction));
                     70:        for (i=0 ; i< sizeof(struct sigaction) ; i++) {
                     71:                put_fs_byte(*from,to);
                     72:                from++;
                     73:                to++;
                     74:        }
                     75: }
                     76: 
                     77: static inline void get_new(char * from,char * to)
                     78: {
                     79:        int i;
                     80: 
                     81:        for (i=0 ; i< sizeof(struct sigaction) ; i++)
                     82:                *(to++) = get_fs_byte(from++);
                     83: }
                     84: 
                     85: int sys_signal(int signum, long handler, long restorer)
                     86: {
                     87:        struct sigaction tmp;
                     88: 
1.1.1.3 ! root       89:        if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
        !            90:                return -EINVAL;
1.1       root       91:        tmp.sa_handler = (void (*)(int)) handler;
                     92:        tmp.sa_mask = 0;
                     93:        tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
                     94:        tmp.sa_restorer = (void (*)(void)) restorer;
                     95:        handler = (long) current->sigaction[signum-1].sa_handler;
                     96:        current->sigaction[signum-1] = tmp;
                     97:        return handler;
                     98: }
                     99: 
                    100: int sys_sigaction(int signum, const struct sigaction * action,
                    101:        struct sigaction * oldaction)
                    102: {
                    103:        struct sigaction tmp;
                    104: 
1.1.1.3 ! root      105:        if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
        !           106:                return -EINVAL;
1.1       root      107:        tmp = current->sigaction[signum-1];
                    108:        get_new((char *) action,
                    109:                (char *) (signum-1+current->sigaction));
                    110:        if (oldaction)
                    111:                save_old((char *) &tmp,(char *) oldaction);
                    112:        if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
                    113:                current->sigaction[signum-1].sa_mask = 0;
                    114:        else
                    115:                current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
                    116:        return 0;
                    117: }
                    118: 
1.1.1.3 ! root      119: /*
        !           120:  * Routine writes a core dump image in the current directory.
        !           121:  * Currently not implemented.
        !           122:  */
        !           123: int core_dump(long signr)
        !           124: {
        !           125:        return(0);      /* We didn't do a dump */
        !           126: }
        !           127: 
        !           128: int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax,
1.1       root      129:        long fs, long es, long ds,
                    130:        long eip, long cs, long eflags,
                    131:        unsigned long * esp, long ss)
                    132: {
1.1.1.2   root      133:        unsigned long sa_handler;
1.1       root      134:        long old_eip=eip;
                    135:        struct sigaction * sa = current->sigaction + signr - 1;
                    136:        int longs;
1.1.1.3 ! root      137: 
1.1       root      138:        unsigned long * tmp_esp;
                    139: 
1.1.1.3 ! root      140: #ifdef notdef
        !           141:        printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n", 
        !           142:                current->pid, signr, eax, orig_eax, 
        !           143:                sa->sa_flags & SA_INTERRUPT);
        !           144: #endif
        !           145:        if ((orig_eax != -1) &&
        !           146:            ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) {
        !           147:                if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
        !           148:                    signr < SIGCONT || signr > SIGTTOU))
        !           149:                        *(&eax) = -EINTR;
        !           150:                else {
        !           151:                        *(&eax) = orig_eax;
        !           152:                        *(&eip) = old_eip -= 2;
        !           153:                }
        !           154:        }
1.1.1.2   root      155:        sa_handler = (unsigned long) sa->sa_handler;
1.1       root      156:        if (sa_handler==1)
1.1.1.3 ! root      157:                return(1);   /* Ignore, see if there are more signals... */
1.1       root      158:        if (!sa_handler) {
1.1.1.3 ! root      159:                switch (signr) {
        !           160:                case SIGCONT:
        !           161:                case SIGCHLD:
        !           162:                        return(1);  /* Ignore, ... */
        !           163: 
        !           164:                case SIGSTOP:
        !           165:                case SIGTSTP:
        !           166:                case SIGTTIN:
        !           167:                case SIGTTOU:
        !           168:                        current->state = TASK_STOPPED;
        !           169:                        current->exit_code = signr;
        !           170:                        if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & 
        !           171:                                        SA_NOCLDSTOP))
        !           172:                                current->p_pptr->signal |= (1<<(SIGCHLD-1));
        !           173:                        return(1);  /* Reschedule another event */
        !           174: 
        !           175:                case SIGQUIT:
        !           176:                case SIGILL:
        !           177:                case SIGTRAP:
        !           178:                case SIGIOT:
        !           179:                case SIGFPE:
        !           180:                case SIGSEGV:
        !           181:                        if (core_dump(signr))
        !           182:                                do_exit(signr|0x80);
        !           183:                        /* fall through */
        !           184:                default:
        !           185:                        do_exit(signr);
        !           186:                }
1.1       root      187:        }
1.1.1.3 ! root      188:        /*
        !           189:         * OK, we're invoking a handler 
        !           190:         */
1.1       root      191:        if (sa->sa_flags & SA_ONESHOT)
                    192:                sa->sa_handler = NULL;
                    193:        *(&eip) = sa_handler;
                    194:        longs = (sa->sa_flags & SA_NOMASK)?7:8;
                    195:        *(&esp) -= longs;
                    196:        verify_area(esp,longs*4);
                    197:        tmp_esp=esp;
                    198:        put_fs_long((long) sa->sa_restorer,tmp_esp++);
                    199:        put_fs_long(signr,tmp_esp++);
                    200:        if (!(sa->sa_flags & SA_NOMASK))
                    201:                put_fs_long(current->blocked,tmp_esp++);
                    202:        put_fs_long(eax,tmp_esp++);
                    203:        put_fs_long(ecx,tmp_esp++);
                    204:        put_fs_long(edx,tmp_esp++);
                    205:        put_fs_long(eflags,tmp_esp++);
                    206:        put_fs_long(old_eip,tmp_esp++);
                    207:        current->blocked |= sa->sa_mask;
1.1.1.3 ! root      208:        return(0);              /* Continue, execute handler */
1.1       root      209: }

unix.superglobalmegacorp.com