--- linux-kdb/kdb/kdbmain.c	Sat Mar 29 10:16:06 2003
+++ linux-kdb-kill/kdb/kdbmain.c	Mon Mar 31 16:31:19 2003
@@ -2947,6 +2947,114 @@
 	return 0;
 }
 
+extern int kdb_wake_up_process(struct task_struct * p);
+
+/*
+ * kdb_kill
+ *
+ *	This function implements the 'kill' commands.
+ *
+ * Inputs:
+ *	argc	argument count
+ *	argv	argument vector
+ *	envp	environment vector
+ *	regs	registers at time kdb was entered.
+ * Outputs:
+ *	None.
+ * Returns:
+ *	zero for success, a kdb diagnostic if error
+ * Locking:
+ *	none.
+ * Remarks:
+ */
+int
+kdb_kill(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	long sig, pid;
+	char *endp;
+	struct task_struct *p, *tg;
+	int find;
+
+	sig = simple_strtol(argv[1], &endp, 0);
+	if (endp == argv[1])
+		return KDB_BADINT;
+	if (sig >= 0 ) {
+		kdb_printf("Invalid signal parameter.<-signal>\n");
+		return 0;
+	}
+	sig=-sig;
+
+	pid = simple_strtol(argv[2], &endp, 0);
+	if (endp == argv[2])
+		return KDB_BADINT;
+	if (pid <=0 ) {
+		kdb_printf("Process ID must be large than 0.\n");
+		return 0;
+	}
+
+	/* Find the process. */
+	find = 0;
+	for_each_task(p) {
+		if(p->pid == pid) {
+			find = 1;
+			break;
+		}
+	}
+	if (find) {
+		/* In case the process is not a thread group leader, find the leader. */
+		if ( p->tgid != p->pid) {
+			for_each_task(tg) {
+				if(tg->pid == p->tgid) {
+					p = tg;
+					break;
+				}
+			}
+		}
+		if (sig >0 && sig <= _NSIG) {
+			int sigismember;
+			sigset_t *set;
+
+			/* Handle TASK_STOPPED cases. */
+			if (sig == SIGKILL || sig == SIGCONT) {
+				/* Wake up the process if it is stopped. */
+				if (p->state & TASK_STOPPED) {
+					kdb_wake_up_process(p);
+				}
+				p->exit_code = 0;
+			}
+
+			sig--;
+
+			/* Set the signal to the specified process's task structure. */
+			set=&(p->pending.signal);
+			if (_NSIG_WORDS == 1)
+				set->sig[0] |= 1UL << sig;
+			else
+				set->sig[sig / _NSIG_BPW] |= 1UL << (sig % _NSIG_BPW);
+
+			/* Check if specified process is blocked by the given signal. */
+			set=&(p->blocked);
+			if (_NSIG_WORDS == 1)
+				sigismember = 1 & (set->sig[0] >> sig);
+			else
+				sigismember = 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
+
+			if (!sigismember) {
+				/* Wake up the process if it is interruptable. */
+				p->sigpending=1;
+				if(p->state & TASK_INTERRUPTIBLE)
+					kdb_wake_up_process(p);
+				kdb_printf("Signal %d is sent to process %d.\n", ++sig, pid);
+			}
+		}
+	}
+	else {
+		kdb_printf("The specified process isn't found.\n");
+	}
+
+	return 0;
+}
+
 /*
  * kdb_register_repeat
  *
@@ -3162,6 +3270,7 @@
 #endif
 	kdb_register_repeat("dmesg", kdb_dmesg, "[lines]",	"Display syslog buffer", 0, KDB_REPEAT_NONE);
 	kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE);
+	kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", "Send a signal to a process", 0, KDB_REPEAT_NONE);
 
 	/* Any kdb commands that are not in the base code but are required
 	 * earlier than normal initcall processing.


--- linux-kdb/kernel/sched.c	Mon Mar 31 16:23:58 2003
+++ linux-kdb-kill/kernel/sched.c	Mon Mar 31 16:21:50 2003
@@ -338,6 +338,19 @@
 	list_add_tail(&p->run_list, &runqueue_head);
 }
 
+#ifdef CONFIG_KDB
+int kdb_wake_up_process(struct task_struct * p)
+{
+	p->state = TASK_RUNNING;
+	if (!task_on_runqueue(p)) {
+		add_to_runqueue(p);
+		reschedule_idle(p);
+		return 1;
+	}
+	return 0;
+}
+#endif /* CONFIG_KDB */
+
 /*
  * Wake up a process. Put it on the run-queue if it's not
  * already there.  The "current" process is always on the
