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

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

unix.superglobalmegacorp.com