]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/kthread.c
Minor repairs in sources
[lincan.git] / lincan / src / kthread.c
1 #include <linux/version.h>
2 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
3         #include <linux/config.h>
4 #endif
5
6 #if defined(MODVERSIONS)
7 #include <linux/modversions.h>
8 #endif
9 #include <linux/kernel.h>
10 #include <linux/sched.h>
11
12 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40))
13   #include <linux/tqueue.h>
14 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
15   #include <linux/devfs_fs_kernel.h>
16 #endif
17
18 #include <linux/wait.h>
19 #include <linux/signal.h>
20 #include <linux/interrupt.h>
21
22
23 #include <asm/semaphore.h>
24 #include <linux/smp_lock.h>
25
26 #include "../include/kthread.h"
27
28 /* private functions */
29 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40))
30 static void kthread_launcher(void *data)
31 #else
32 static void kthread_launcher(unsigned long data)
33 #endif
34 {
35   kthread_t *kthread = (kthread_t *)data;
36
37   kernel_thread((int (*)(void *))kthread->function, (void *)kthread, 0);
38 }
39
40 /* public functions */
41
42 /* create a new kernel thread. Called by the creator. */
43 void start_kthread(void (*func)(kthread_t *), kthread_t *kthread)
44 {
45     /* initialize the semaphore:
46        we start with the semaphore locked. The new kernel
47        thread will setup its stuff and unlock it. This
48        control flow (the one that creates the thread) blocks
49        in the down operation below until the thread has reached
50        the up() operation.
51     */
52     init_MUTEX_LOCKED(&kthread->startstop_sem);
53
54     /* store the function to be executed in the data passed to
55        the launcher */
56     kthread->function=func;
57
58     /* create the new thread my running a task through keventd */
59
60 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40))
61
62     /* initialize the task queue structure */
63     kthread->tq.sync = 0;
64     INIT_LIST_HEAD(&kthread->tq.list);
65     kthread->tq.routine = kthread_launcher;
66     kthread->tq.data = kthread;
67
68     /* and schedule it for execution */
69     schedule_task(&kthread->tq);
70 #else
71     /* initialize tasklet */
72     tasklet_init(&kthread->tq, kthread_launcher, (unsigned long)kthread);
73     /* and schedule it for execution */
74     tasklet_schedule(&kthread->tq);
75 #endif
76
77     /* wait till it has reached the setup_thread routine */
78     down(&kthread->startstop_sem);
79 }
80
81 /* stop a kernel thread. Called by the removing instance */
82 void stop_kthread(kthread_t *kthread)
83 {
84     if (kthread->thread == NULL)
85     {
86         printk("stop_kthread: killing non existing thread!\n");
87         return;
88     }
89
90     /* this function needs to be protected with the big
91     kernel lock (lock_kernel()). The lock must be
92        grabbed before changing the terminate
93     flag and released after the down() call. */
94     lock_kernel();
95
96     /* initialize the semaphore. We lock it here, the
97        leave_thread call of the thread to be terminated
98        will unlock it. As soon as we see the semaphore
99        unlocked, we know that the thread has exited.
100     */
101     init_MUTEX_LOCKED(&kthread->startstop_sem);
102
103     /* We need to do a memory barrier here to be sure that
104        the flags are visible on all CPUs.
105     */
106     mb();
107
108     /* set flag to request thread termination */
109     kthread->terminate = 1;
110
111     /* We need to do a memory barrier here to be sure that
112        the flags are visible on all CPUs.
113     */
114     mb();
115     kill_proc(kthread->thread->pid, SIGKILL, 1);
116
117     /* block till thread terminated */
118     down(&kthread->startstop_sem);
119
120     /* release the big kernel lock */
121     unlock_kernel();
122
123     /* now we are sure the thread is in zombie state. We
124        notify keventd to clean the process up.
125     */
126     kill_proc(2, SIGCHLD, 1);
127
128 }
129
130 /* initialize new created thread. Called by the new thread. */
131 void init_kthread(kthread_t *kthread, char *name)
132 {
133     /* fill in thread structure */
134     kthread->thread = current;
135
136     /* initialise termination flag */
137     kthread->terminate = 0;
138
139     /* initialise wait queue */
140     init_waitqueue_head(&kthread->queue);
141
142 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40))
143     /* lock the kernel. A new kernel thread starts without
144       the big kernel lock, regardless of the lock state
145       of the creator (the lock level is *not* inheritated)
146     */
147     lock_kernel();
148 /*    daemonize(); */
149
150     /* set signal mask to what we want to respond */
151     siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
152
153     /* set name of this process (max 15 chars + 0 !) */
154     sprintf(current->comm, name);
155
156     /* let others run */
157     unlock_kernel();
158 #else
159
160     daemonize(name);
161 #endif
162
163     /* tell the creator that we are ready and let him continue */
164     up(&kthread->startstop_sem);
165 }
166
167 /* cleanup of thread. Called by the exiting thread. */
168 void exit_kthread(kthread_t *kthread)
169 {
170     /* we are terminating */
171
172     /* lock the kernel, the exit will unlock it */
173     lock_kernel();
174     kthread->thread = NULL;
175     mb();
176
177     /* notify the stop_kthread() routine that we are terminating. */
178     up(&kthread->startstop_sem);
179     /* the kernel_thread that called clone() does a do_exit here. */
180
181     /* there is no race here between execution of the "killer" and real termination
182        of the thread (race window between up and do_exit), since both the
183        thread and the "killer" function are running with the kernel lock held.
184        The kernel lock will be freed after the thread exited, so the code
185        is really not executed anymore as soon as the unload functions gets
186        the kernel lock back.
187        The init process may not have made the cleanup of the process here,
188        but the cleanup can be done safely with the module unloaded.
189     */
190
191 }
192