OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [kernel/] [kthread.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* Kernel thread helper functions.
2
 *   Copyright (C) 2004 IBM Corporation, Rusty Russell.
3
 *
4
 * Creation is done via kthreadd, so that we get a clean environment
5
 * even if we're invoked from userspace (think modprobe, hotplug cpu,
6
 * etc.).
7
 */
8
#include <linux/sched.h>
9
#include <linux/kthread.h>
10
#include <linux/completion.h>
11
#include <linux/err.h>
12
#include <linux/unistd.h>
13
#include <linux/file.h>
14
#include <linux/module.h>
15
#include <linux/mutex.h>
16
#include <asm/semaphore.h>
17
 
18
static DEFINE_SPINLOCK(kthread_create_lock);
19
static LIST_HEAD(kthread_create_list);
20
struct task_struct *kthreadd_task;
21
 
22
struct kthread_create_info
23
{
24
        /* Information passed to kthread() from kthreadd. */
25
        int (*threadfn)(void *data);
26
        void *data;
27
        struct completion started;
28
 
29
        /* Result passed back to kthread_create() from kthreadd. */
30
        struct task_struct *result;
31
        struct completion done;
32
 
33
        struct list_head list;
34
};
35
 
36
struct kthread_stop_info
37
{
38
        struct task_struct *k;
39
        int err;
40
        struct completion done;
41
};
42
 
43
/* Thread stopping is done by setthing this var: lock serializes
44
 * multiple kthread_stop calls. */
45
static DEFINE_MUTEX(kthread_stop_lock);
46
static struct kthread_stop_info kthread_stop_info;
47
 
48
/**
49
 * kthread_should_stop - should this kthread return now?
50
 *
51
 * When someone calls kthread_stop() on your kthread, it will be woken
52
 * and this will return true.  You should then return, and your return
53
 * value will be passed through to kthread_stop().
54
 */
55
int kthread_should_stop(void)
56
{
57
        return (kthread_stop_info.k == current);
58
}
59
EXPORT_SYMBOL(kthread_should_stop);
60
 
61
static int kthread(void *_create)
62
{
63
        struct kthread_create_info *create = _create;
64
        int (*threadfn)(void *data);
65
        void *data;
66
        int ret = -EINTR;
67
 
68
        /* Copy data: it's on kthread's stack */
69
        threadfn = create->threadfn;
70
        data = create->data;
71
 
72
        /* OK, tell user we're spawned, wait for stop or wakeup */
73
        __set_current_state(TASK_UNINTERRUPTIBLE);
74
        complete(&create->started);
75
        schedule();
76
 
77
        if (!kthread_should_stop())
78
                ret = threadfn(data);
79
 
80
        /* It might have exited on its own, w/o kthread_stop.  Check. */
81
        if (kthread_should_stop()) {
82
                kthread_stop_info.err = ret;
83
                complete(&kthread_stop_info.done);
84
        }
85
        return 0;
86
}
87
 
88
static void create_kthread(struct kthread_create_info *create)
89
{
90
        int pid;
91
 
92
        /* We want our own signal handler (we take no signals by default). */
93
        pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
94
        if (pid < 0) {
95
                create->result = ERR_PTR(pid);
96
        } else {
97
                wait_for_completion(&create->started);
98
                read_lock(&tasklist_lock);
99
                create->result = find_task_by_pid(pid);
100
                read_unlock(&tasklist_lock);
101
        }
102
        complete(&create->done);
103
}
104
 
105
/**
106
 * kthread_create - create a kthread.
107
 * @threadfn: the function to run until signal_pending(current).
108
 * @data: data ptr for @threadfn.
109
 * @namefmt: printf-style name for the thread.
110
 *
111
 * Description: This helper function creates and names a kernel
112
 * thread.  The thread will be stopped: use wake_up_process() to start
113
 * it.  See also kthread_run(), kthread_create_on_cpu().
114
 *
115
 * When woken, the thread will run @threadfn() with @data as its
116
 * argument. @threadfn() can either call do_exit() directly if it is a
117
 * standalone thread for which noone will call kthread_stop(), or
118
 * return when 'kthread_should_stop()' is true (which means
119
 * kthread_stop() has been called).  The return value should be zero
120
 * or a negative error number; it will be passed to kthread_stop().
121
 *
122
 * Returns a task_struct or ERR_PTR(-ENOMEM).
123
 */
124
struct task_struct *kthread_create(int (*threadfn)(void *data),
125
                                   void *data,
126
                                   const char namefmt[],
127
                                   ...)
128
{
129
        struct kthread_create_info create;
130
 
131
        create.threadfn = threadfn;
132
        create.data = data;
133
        init_completion(&create.started);
134
        init_completion(&create.done);
135
 
136
        spin_lock(&kthread_create_lock);
137
        list_add_tail(&create.list, &kthread_create_list);
138
        wake_up_process(kthreadd_task);
139
        spin_unlock(&kthread_create_lock);
140
 
141
        wait_for_completion(&create.done);
142
 
143
        if (!IS_ERR(create.result)) {
144
                va_list args;
145
                va_start(args, namefmt);
146
                vsnprintf(create.result->comm, sizeof(create.result->comm),
147
                          namefmt, args);
148
                va_end(args);
149
        }
150
        return create.result;
151
}
152
EXPORT_SYMBOL(kthread_create);
153
 
154
/**
155
 * kthread_bind - bind a just-created kthread to a cpu.
156
 * @k: thread created by kthread_create().
157
 * @cpu: cpu (might not be online, must be possible) for @k to run on.
158
 *
159
 * Description: This function is equivalent to set_cpus_allowed(),
160
 * except that @cpu doesn't need to be online, and the thread must be
161
 * stopped (i.e., just returned from kthread_create()).
162
 */
163
void kthread_bind(struct task_struct *k, unsigned int cpu)
164
{
165
        if (k->state != TASK_UNINTERRUPTIBLE) {
166
                WARN_ON(1);
167
                return;
168
        }
169
        /* Must have done schedule() in kthread() before we set_task_cpu */
170
        wait_task_inactive(k);
171
        set_task_cpu(k, cpu);
172
        k->cpus_allowed = cpumask_of_cpu(cpu);
173
}
174
EXPORT_SYMBOL(kthread_bind);
175
 
176
/**
177
 * kthread_stop - stop a thread created by kthread_create().
178
 * @k: thread created by kthread_create().
179
 *
180
 * Sets kthread_should_stop() for @k to return true, wakes it, and
181
 * waits for it to exit.  Your threadfn() must not call do_exit()
182
 * itself if you use this function!  This can also be called after
183
 * kthread_create() instead of calling wake_up_process(): the thread
184
 * will exit without calling threadfn().
185
 *
186
 * Returns the result of threadfn(), or %-EINTR if wake_up_process()
187
 * was never called.
188
 */
189
int kthread_stop(struct task_struct *k)
190
{
191
        int ret;
192
 
193
        mutex_lock(&kthread_stop_lock);
194
 
195
        /* It could exit after stop_info.k set, but before wake_up_process. */
196
        get_task_struct(k);
197
 
198
        /* Must init completion *before* thread sees kthread_stop_info.k */
199
        init_completion(&kthread_stop_info.done);
200
        smp_wmb();
201
 
202
        /* Now set kthread_should_stop() to true, and wake it up. */
203
        kthread_stop_info.k = k;
204
        wake_up_process(k);
205
        put_task_struct(k);
206
 
207
        /* Once it dies, reset stop ptr, gather result and we're done. */
208
        wait_for_completion(&kthread_stop_info.done);
209
        kthread_stop_info.k = NULL;
210
        ret = kthread_stop_info.err;
211
        mutex_unlock(&kthread_stop_lock);
212
 
213
        return ret;
214
}
215
EXPORT_SYMBOL(kthread_stop);
216
 
217
int kthreadd(void *unused)
218
{
219
        struct task_struct *tsk = current;
220
 
221
        /* Setup a clean context for our children to inherit. */
222
        set_task_comm(tsk, "kthreadd");
223
        ignore_signals(tsk);
224
        set_user_nice(tsk, -5);
225
        set_cpus_allowed(tsk, CPU_MASK_ALL);
226
 
227
        current->flags |= PF_NOFREEZE;
228
 
229
        for (;;) {
230
                set_current_state(TASK_INTERRUPTIBLE);
231
                if (list_empty(&kthread_create_list))
232
                        schedule();
233
                __set_current_state(TASK_RUNNING);
234
 
235
                spin_lock(&kthread_create_lock);
236
                while (!list_empty(&kthread_create_list)) {
237
                        struct kthread_create_info *create;
238
 
239
                        create = list_entry(kthread_create_list.next,
240
                                            struct kthread_create_info, list);
241
                        list_del_init(&create->list);
242
                        spin_unlock(&kthread_create_lock);
243
 
244
                        create_kthread(create);
245
 
246
                        spin_lock(&kthread_create_lock);
247
                }
248
                spin_unlock(&kthread_create_lock);
249
        }
250
 
251
        return 0;
252
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.