From: Christoph Hellwig <hch@caldera.de>
To: Andi Kleen <ak@suse.de>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH][RFC] kthread abstraction
Date: Fri, 1 Feb 2002 18:17:41 +0100 [thread overview]
Message-ID: <20020201181741.A7268@caldera.de> (raw)
In-Reply-To: <20020201163818.A32551@caldera.de.suse.lists.linux.kernel> <p73d6zpno2u.fsf@oldwotan.suse.de>
In-Reply-To: <p73d6zpno2u.fsf@oldwotan.suse.de>; from ak@suse.de on Fri, Feb 01, 2002 at 05:50:33PM +0100
On Fri, Feb 01, 2002 at 05:50:33PM +0100, Andi Kleen wrote:
> I think it would be better to pass data as a separate argument.
> You can put the kthread and the data into a private structure on
> the stack, pass the address of it to kernel_thread and wait until the
> thread has read it using a completion.
Reworked version below.
diff -uNr -Xdontdiff ../master/linux-2.5.3/include/linux/kthread.h linux/include/linux/kthread.h
--- ../master/linux-2.5.3/include/linux/kthread.h Thu Jan 1 01:00:00 1970
+++ linux/include/linux/kthread.h Fri Feb 1 18:08:50 2002
@@ -0,0 +1,22 @@
+#ifndef _LINUX_KTHREAD_H
+#define _LINUX_KTHREAD_H
+
+struct task_struct;
+
+struct kthread {
+ const char *name;
+ struct task_struct *task;
+ struct completion done;
+#define KTH_RUNNING 1
+#define KTH_SHUTDOWN 2
+ long state;
+ int (*init)(struct kthread *, void *);
+ void (*cleanup)(struct kthread *, void *);
+ void (*main)(struct kthread *, void *);
+};
+
+extern int kthread_start(struct kthread *, void *);
+extern void kthread_stop(struct kthread *);
+extern int kthread_running(struct kthread *);
+
+#endif /* _LINUX_KTHREAD_H */
diff -uNr -Xdontdiff ../master/linux-2.5.3/kernel/Makefile linux/kernel/Makefile
--- ../master/linux-2.5.3/kernel/Makefile Fri Feb 1 16:27:04 2002
+++ linux/kernel/Makefile Fri Feb 1 16:29:19 2002
@@ -10,12 +10,12 @@
O_TARGET := kernel.o
export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
- printk.o
+ printk.o kthread.o
obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
module.o exit.o itimer.o info.o time.o softirq.o resource.o \
sysctl.o acct.o capability.o ptrace.o timer.o user.o \
- signal.o sys.o kmod.o context.o
+ signal.o sys.o kmod.o context.o kthread.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += ksyms.o
diff -uNr -Xdontdiff ../master/linux-2.5.3/kernel/kthread.c linux/kernel/kthread.c
--- ../master/linux-2.5.3/kernel/kthread.c Thu Jan 1 01:00:00 1970
+++ linux/kernel/kthread.c Fri Feb 1 18:15:46 2002
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2002 Christoph Hellwig.
+ * All rights resered.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <asm/bitops.h>
+
+#define KTHREAD_FLAGS \
+ (CLONE_FS|CLONE_FILES|CLONE_SIGHAND)
+
+struct kthread_args {
+ struct kthread *kth;
+ void *data;
+};
+
+
+static int kthread_stopped(struct kthread *kth)
+{
+ struct task_struct *task = kth->task;
+ unsigned long signr;
+ siginfo_t info;
+
+ spin_lock_irq(&task->sigmask_lock);
+ signr = dequeue_signal(&task->blocked, &info);
+ spin_unlock_irq(&task->sigmask_lock);
+
+ if (signr == SIGKILL && test_bit(KTH_SHUTDOWN, &kth->state))
+ return 1;
+ return 0;
+}
+
+static int kthread_main(void *p)
+{
+ struct kthread_args *args = p;
+ struct kthread *kth = args->kth;
+ void *data = args->data;
+
+ lock_kernel();
+ daemonize();
+ reparent_to_init();
+ strcpy(current->comm, kth->name);
+ unlock_kernel();
+
+ kth->task = current;
+
+ spin_lock_irq(¤t->sigmask_lock);
+ siginitsetinv(¤t->blocked,
+ sigmask(SIGHUP) | sigmask(SIGKILL) |
+ sigmask(SIGSTOP) | sigmask(SIGCONT));
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ if (kth->init)
+ kth->init(kth, data);
+ complete(&kth->done);
+
+ do {
+ kth->main(kth, data);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ } while (!kthread_stopped(kth));
+
+ if (kth->cleanup)
+ kth->cleanup(kth, data);
+ clear_bit(KTH_RUNNING, &kth->state);
+ complete(&kth->done);
+ return 0;
+}
+
+/**
+ * kthread_start - start a new kernel thread
+ * @kth: kernel thread description
+ * @data: opaque data for use with the methods
+ *
+ * For off a new kernel thread as described by @kth.
+ */
+int kthread_start(struct kthread *kth, void *data)
+{
+ struct kthread_args args;
+ pid_t pid;
+
+ if (!kth->name || !kth->main)
+ return -EINVAL;
+
+ args.kth = kth;
+ args.data = data;
+
+ init_completion(&kth->done);
+ if ((pid = kernel_thread(kthread_main, &args, KTHREAD_FLAGS)) < 0)
+ return pid;
+ set_bit(KTH_RUNNING, &kth->state);
+ wait_for_completion(&kth->done);
+ return 0;
+}
+
+/**
+ * kthread_stop - stop a kernel thread
+ * @kth: kernel thread description
+ *
+ * Stop the kernel thread described by @kth.
+ */
+void kthread_stop(struct kthread *kth)
+{
+ if (kth->task) {
+ init_completion(&kth->done);
+ set_bit(KTH_SHUTDOWN, &kth->state);
+ send_sig(SIGKILL, kth->task, 1);
+ wait_for_completion(&kth->done);
+ kth->task = NULL;
+ clear_bit(KTH_SHUTDOWN, &kth->state);
+ }
+}
+
+/**
+ * kthread_running - check whether a kernel thread is running
+ * @kth: kernel thread description
+ *
+ * Checks whether the kernel thread described by @kth is running.
+ */
+int kthread_running(struct kthread *kth)
+{
+ return test_bit(KTH_RUNNING, &kth->state);
+}
+
+EXPORT_SYMBOL(kthread_start);
+EXPORT_SYMBOL(kthread_stop);
+EXPORT_SYMBOL(kthread_running);
next prev parent reply other threads:[~2002-02-01 17:18 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20020201163818.A32551@caldera.de.suse.lists.linux.kernel>
2002-02-01 16:50 ` [PATCH][RFC] kthread abstraction Andi Kleen
2002-02-01 17:07 ` Christoph Hellwig
2002-02-01 17:17 ` Christoph Hellwig [this message]
2002-02-01 15:38 Christoph Hellwig
2002-02-01 16:32 ` Adam Keys
2002-02-01 16:40 ` Christoph Hellwig
2002-02-01 17:21 ` Dave Hansen
2002-02-01 17:23 ` Christoph Hellwig
2002-02-01 17:49 ` Dave Hansen
2002-02-01 17:50 ` Jeff Garzik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20020201181741.A7268@caldera.de \
--to=hch@caldera.de \
--cc=ak@suse.de \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.