Main Page | Directories | File List | Globals

signals.c

Go to the documentation of this file.
00001 /*
00002  * kernel_super/signals/signals.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/01
00008  * Author:      Lukasz Dembinski
00009  * Info:        signals.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
00011  *
00012  */
00013 
00014 #include <agnix/agnix.h>
00015 #include <agnix/console.h>
00016 #include <agnix/tasks.h>
00017 #include <agnix/signals.h>
00018 #include <agnix/memory.h>
00019 #include <agnix/errno.h>
00020 #include <agnix/list.h>
00021 #include <asm/bitops.h>
00022 #include <agnix/console.h>
00023 
00024 #define MOD_NAME        "SIG: "
00025 
00026 void signals_init(struct task_s *parent, struct task_s *task)
00027 {
00028     int i;
00029     
00030     for (i = 0; i < NSIG; i++) {
00031         INIT_LIST_HEAD(&task->signals.list[i]);
00032     }
00033     
00034     task->signals.pending = 0;
00035     memset(task->signals.sigset.sig, 0, sizeof(sigset_t));
00036     memcpy(task->signals.sigmask.sig, parent->signals.sigmask.sig, sizeof(sigset_t));
00037 }
00038 
00039 int signals_sigaction_copy(struct task_s *parent, struct task_s *task)
00040 {
00041     return 0;
00042 }
00043 
00044 int signals_fork(struct task_s *parent, struct task_s *task)
00045 {
00046     signals_init(parent, task);    
00047     signals_sigaction_copy(parent, task);
00048 
00049     return 0;
00050 }
00051 
00052 void signal_remove(struct task_s *task, int sig)
00053 {
00054     struct signals_s *signals;
00055     struct signal_s *signal;
00056     struct list_head *tmp;
00057 
00058     signals = &task->signals;
00059 
00060     spin_lock(&signals->lock);
00061     
00062     if (list_empty(&signals->list[sig]))
00063         return;
00064     
00065     list_for_each(tmp, &signals->list[sig]) {
00066         signal = list_entry(tmp, struct signal_s, list);
00067         
00068         put_free_pages((u32)signal, 0);
00069     }
00070     
00071     INIT_LIST_HEAD(&signals->list[sig]);
00072     
00073     spin_unlock(&signals->lock);
00074 }
00075 
00076 int signal_exclude(struct task_s *task, struct signals_s *signals, int sig)
00077 {
00078     switch(sig) {
00079         case SIGCONT: 
00080             signal_remove(task, SIGSTOP);
00081             break;
00082         case SIGSTOP:
00083             signal_remove(task, SIGCONT);
00084             break;
00085     }
00086     
00087     return 0;
00088 }
00089 
00090 int signal_check(struct signals_s *signals, int sig)
00091 {
00092     if (sig < 0 || sig > NSIG)
00093         return -1;
00094 
00095     /* sanity check */
00096     if (signals == NULL)
00097         return -1;
00098 
00099     return 0;
00100 }
00101 
00102 int signal_queue_lock(struct signals_s *signals, int sig, struct signal_s *signal, 
00103                  siginfo_t *siginfo)
00104 {
00105     signal->signal_nr = sig;
00106     memcpy(&signal->siginfo, siginfo, sizeof(siginfo_t));
00107     
00108     list_add(&signal->list, &signals->list[sig]);
00109     set_bit(sig, &signals->sigset.sig[0]);
00110     
00111     if (!test_bit(sig, &signals->sigmask.sig[0]))
00112         signals->pending++;
00113 
00114     return 0;
00115 }
00116 
00117 struct signal_s *signal_dequeue(struct task_s *task)
00118 {
00119     struct signals_s *signals;
00120     struct signal_s *signal;
00121     sigset_t mask;
00122     int sig;
00123     u32 flags;
00124 
00125     signals = &task->signals;
00126 
00127     spin_lock_irqsave(&signals->lock, flags);
00128 
00129     mask.sig[0] = signals->sigset.sig[0] & ~signals->sigmask.sig[0];
00130     mask.sig[1] = signals->sigset.sig[1] & ~signals->sigmask.sig[1];
00131 
00132     if (mask.sig[0] == 0 && mask.sig[1] == 0)
00133         return NULL;
00134 
00135     sig = ffz(~mask.sig[0]);
00136 
00137     if (sig < 0 || sig >= 32)
00138         return NULL;
00139 
00140     if (list_empty(&signals->list[sig])) {
00141         printk(MOD_NAME "There is something wrong!\n");
00142         return NULL;
00143     }
00144 
00145     signal = list_entry(signals->list[sig].next, struct signal_s, list);
00146     list_del(&signal->list);
00147 
00148     signals->pending--;
00149     spin_unlock_irqrestore(&signals->lock, flags);
00150 
00151     return signal;
00152 }
00153 
00154 int send_signal_to_task(struct task_s *task, int sig, siginfo_t *siginfo)
00155 {
00156     struct signals_s *signals;
00157     struct signal_s *signal;
00158     int ret;
00159     u32 flags;
00160 
00161     /* yghhhh, we haven't slab allocator yet */
00162     signal = (struct signal_s *)get_free_pages(0);
00163     
00164     if (signal == NULL)
00165         return -ENOMEM;
00166 
00167     memset(signal, 0, sizeof(struct signal_s));
00168     spin_lock_irqsave(&signals->lock, flags);
00169 
00170     signals = &task->signals;
00171 
00172     if (siginfo)
00173         memcpy(&(signal->siginfo), siginfo, sizeof(siginfo_t));
00174     
00175     ret = signal_check(signals, sig);
00176     if (ret < 0)
00177         goto signal_out;
00178     
00179     ret = signal_exclude(task, signals, sig);
00180     if (ret < 0)
00181         goto signal_out;
00182     
00183     ret = 0;
00184     signal_queue_lock(signals, sig, signal, siginfo);
00185 
00186 signal_out:
00187     spin_unlock_irqrestore(&signals->lock, flags);
00188 
00189     return ret;
00190 }
00191 
00192 int send_signal_to_pid(int pid, int sig, siginfo_t *siginfo)
00193 {
00194     struct task_s *task;
00195     
00196     if ((task = fork_find_hash_entry(pid)) == 0) {
00197         printk("Can not find a task (pid=%d) in the hashing table\n", pid);
00198         return -1;
00199     }
00200 
00201     return send_signal_to_task(task, sig, siginfo);
00202 }
00203 
00204 int do_sys_kill(int pid, int sig)
00205 {
00206     siginfo_t siginfo;
00207 
00208     siginfo.si_signo = sig;
00209     siginfo.si_errno = 0;
00210     siginfo.si_code  = SI_USER;
00211     siginfo.si_pid   = current_task->t_pid;
00212     siginfo.si_uid   = current_task->t_uid;
00213     
00214     return send_signal_to_pid(pid, sig, &siginfo);
00215 }
00216 
00217 int signal_send(int pid, int sig, siginfo_t *siginfo)
00218 {
00219     siginfo_t siginfo_local;
00220 
00221     switch((u32)siginfo) {
00222         case 0:
00223             siginfo_local.si_signo = sig;
00224             siginfo_local.si_errno = 0;
00225             siginfo_local.si_code  = SI_USER;
00226             siginfo_local.si_pid   = current_task->t_pid;
00227             siginfo_local.si_uid   = current_task->t_uid;
00228             break;
00229 
00230         case 1:
00231             siginfo_local.si_signo = sig;
00232             siginfo_local.si_errno = 0;
00233             siginfo_local.si_code  = SI_KERNEL;
00234             siginfo_local.si_pid   = 0;
00235             siginfo_local.si_uid   = 0;
00236             break;
00237     
00238         default:
00239             return send_signal_to_pid(pid, sig, siginfo);
00240     }
00241     
00242     return send_signal_to_pid(pid, sig, &siginfo_local);
00243 }
00244 
00245 int do_sys_sigreturn(unsigned long __unused)
00246 {
00247     printk("sigreturn!!!\n");
00248 
00249     return 0;
00250 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix