00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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 }