Re: [take26-resend1 7/8] kevent: Signal notifications.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Evgeniy,

I have used kobject_uevent() to notify userspace about some events.
For instance, when memory comsumption reaches a predefined watermark,
a signal is sent to userspace to allow applications to free resources.
But I am not sure if kobject_uevent() is the more appropriate way for
that since if I have many different levels of notifications (using
kobject_uevent()) from kernel space to user space, so how the
application could know or differentiate from which level of kernel
notification the signal was sent from?

The application should perform a specific task according to different
type of received notification. So I do not know if the current kernel
provides something like that. Do you know any current kernel (2.6.19)
implementation for that?

After reading about your Kevent implementation, I guess that your
patches are able to do what I need, right? Will it be included in the
mainline kernel? Do you have examples about how can I use your socket
and/or signal notifications to establish kernel and user space
communication?

BR,

Mauricio Lin.

On 12/11/06, Evgeniy Polyakov <[email protected]> wrote:

Signal notifications.

This type of notifications allows to deliver signals through kevent queue.
One can find example application signal.c on project homepage.

If KEVENT_SIGNAL_NOMASK bit is set in raw_u64 id then signal will be
delivered only through queue, otherwise both delivery types are used - old
through update of mask of pending signals and through queue.

If signal is delivered only through kevent queue mask of pending signals
is not updated at all, which is equal to putting signal into blocked mask,
but with delivery of that signal through kevent queue.

Signed-off-by: Evgeniy Polyakov <[email protected]>


diff --git a/include/linux/sched.h b/include/linux/sched.h
index fc4a987..ef38a3c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -80,6 +80,7 @@ struct sched_param {
 #include <linux/resource.h>
 #include <linux/timer.h>
 #include <linux/hrtimer.h>
+#include <linux/kevent_storage.h>

 #include <asm/processor.h>

@@ -1013,6 +1014,10 @@ struct task_struct {
 #ifdef CONFIG_TASK_DELAY_ACCT
        struct task_delay_info *delays;
 #endif
+#ifdef CONFIG_KEVENT_SIGNAL
+       struct kevent_storage st;
+       u32 kevent_signals;
+#endif
 };

 static inline pid_t process_group(struct task_struct *tsk)
diff --git a/kernel/fork.c b/kernel/fork.c
index 1c999f3..e5b5b14 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -46,6 +46,7 @@
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
 #include <linux/random.h>
+#include <linux/kevent.h>

 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -115,6 +116,9 @@ void __put_task_struct(struct task_struct *tsk)
        WARN_ON(atomic_read(&tsk->usage));
        WARN_ON(tsk == current);

+#ifdef CONFIG_KEVENT_SIGNAL
+       kevent_storage_fini(&tsk->st);
+#endif
        security_task_free(tsk);
        free_uid(tsk->user);
        put_group_info(tsk->group_info);
@@ -1121,6 +1125,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        if (retval)
                goto bad_fork_cleanup_namespace;

+#ifdef CONFIG_KEVENT_SIGNAL
+       kevent_storage_init(p, &p->st);
+#endif
+
        p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
        /*
         * Clear TID on mm_release()?
diff --git a/kernel/kevent/kevent_signal.c b/kernel/kevent/kevent_signal.c
new file mode 100644
index 0000000..0edd2e4
--- /dev/null
+++ b/kernel/kevent/kevent_signal.c
@@ -0,0 +1,92 @@
+/*
+ *     kevent_signal.c
+ *
+ * 2006 Copyright (c) Evgeniy Polyakov <[email protected]>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kevent.h>
+
+static int kevent_signal_callback(struct kevent *k)
+{
+       struct task_struct *tsk = k->st->origin;
+       int sig = k->event.id.raw[0];
+       int ret = 0;
+
+       if (sig == tsk->kevent_signals)
+               ret = 1;
+
+       if (ret && (k->event.id.raw_u64 & KEVENT_SIGNAL_NOMASK))
+               tsk->kevent_signals |= 0x80000000;
+
+       return ret;
+}
+
+int kevent_signal_enqueue(struct kevent *k)
+{
+       int err;
+
+       err = kevent_storage_enqueue(&current->st, k);
+       if (err)
+               goto err_out_exit;
+
+       if (k->event.req_flags & KEVENT_REQ_ALWAYS_QUEUE) {
+               kevent_requeue(k);
+               err = 0;
+       } else {
+               err = k->callbacks.callback(k);
+               if (err)
+                       goto err_out_dequeue;
+       }
+
+       return err;
+
+err_out_dequeue:
+       kevent_storage_dequeue(k->st, k);
+err_out_exit:
+       return err;
+}
+
+int kevent_signal_dequeue(struct kevent *k)
+{
+       kevent_storage_dequeue(k->st, k);
+       return 0;
+}
+
+int kevent_signal_notify(struct task_struct *tsk, int sig)
+{
+       tsk->kevent_signals = sig;
+       kevent_storage_ready(&tsk->st, NULL, KEVENT_SIGNAL_DELIVERY);
+       return (tsk->kevent_signals & 0x80000000);
+}
+
+static int __init kevent_init_signal(void)
+{
+       struct kevent_callbacks sc = {
+               .callback = &kevent_signal_callback,
+               .enqueue = &kevent_signal_enqueue,
+               .dequeue = &kevent_signal_dequeue};
+
+       return kevent_add_callbacks(&sc, KEVENT_SIGNAL);
+}
+module_init(kevent_init_signal);
diff --git a/kernel/signal.c b/kernel/signal.c
index fb5da6d..d3d3594 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -23,6 +23,7 @@
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <linux/capability.h>
+#include <linux/kevent.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -703,6 +704,9 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
 {
        struct sigqueue * q = NULL;
        int ret = 0;
+
+       if (kevent_signal_notify(t, sig))
+               return 1;

        /*
         * fast-pathed signals for kernel-internal things like SIGSTOP
@@ -782,6 +786,17 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
        ret = send_signal(sig, info, t, &t->pending);
        if (!ret && !sigismember(&t->blocked, sig))
                signal_wake_up(t, sig == SIGKILL);
+#ifdef CONFIG_KEVENT_SIGNAL
+       /*
+        * Kevent allows to deliver signals through kevent queue,
+        * it is possible to setup kevent to not deliver
+        * signal through the usual way, in that case send_signal()
+        * returns 1 and signal is delivered only through kevent queue.
+        * We simulate successfull delivery notification through this hack:
+        */
+       if (ret == 1)
+               ret = 0;
+#endif
 out:
        return ret;
 }
@@ -971,6 +986,17 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
         * to avoid several races.
         */
        ret = send_signal(sig, info, p, &p->signal->shared_pending);
+#ifdef CONFIG_KEVENT_SIGNAL
+       /*
+        * Kevent allows to deliver signals through kevent queue,
+        * it is possible to setup kevent to not deliver
+        * signal through the usual way, in that case send_signal()
+        * returns 1 and signal is delivered only through kevent queue.
+        * We simulate successfull delivery notification through this hack:
+        */
+       if (ret == 1)
+               ret = 0;
+#endif
        if (unlikely(ret))
                return ret;


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux