aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-09-27 04:50:40 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 11:26:16 -0400
commit3c9173509985b957bea692ea887a8a0e5055cfe8 (patch)
tree9406fb650d6085f992b6d2a0a3fd8763b045cc35 /arch/um/kernel
parent0915ee38c7db57ff41a7a68bcc02d0dd3b7b849b (diff)
[PATCH] uml: thread creation tidying
fork on UML has always somewhat subtle. The underlying cause has been the need to initialize a stack for the new process. The only portable way to initialize a new stack is to set it as the alternate signal stack and take a signal. The signal handler does whatever initialization is needed and jumps back to the original stack, where the fork processing is finished. The basic context switching mechanism is a jmp_buf for each process. You switch to a new process by longjmping to its jmp_buf. Now that UML has its own implementation of setjmp and longjmp, and I can poke around inside a jmp_buf without fear that libc will change the structure, a much simpler mechanism is possible. The jmpbuf can simply be initialized by hand. This eliminates - the need to set up and remove the alternate signal stack sending and handling a signal the signal blocking needed around the stack switching, since there is no stack switching setting up the jmp_buf needed to jump back to the original stack after the new one is set up In addition, since jmp_buf is now defined by UML, and not by libc, it can be embedded in the thread struct. This makes it unnecessary to have it exist on the stack, where it used to be. It also simplifies interfaces, since the switch jmp_buf used to be a void * inside the thread struct, and functions which took it as an argument needed to define a jmp_buf variable and assign it from the void *. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/skas/process_kern.c36
1 files changed, 13 insertions, 23 deletions
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 55caeec8b257..c73d47c57abe 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -33,7 +33,7 @@ void switch_to_skas(void *prev, void *next)
33 switch_timers(0); 33 switch_timers(0);
34 34
35 switch_threads(&from->thread.mode.skas.switch_buf, 35 switch_threads(&from->thread.mode.skas.switch_buf,
36 to->thread.mode.skas.switch_buf); 36 &to->thread.mode.skas.switch_buf);
37 37
38 arch_switch_to_skas(current->thread.prev_sched, current); 38 arch_switch_to_skas(current->thread.prev_sched, current);
39 39
@@ -43,21 +43,21 @@ void switch_to_skas(void *prev, void *next)
43 43
44extern void schedule_tail(struct task_struct *prev); 44extern void schedule_tail(struct task_struct *prev);
45 45
46void new_thread_handler(int sig) 46/* This is called magically, by its address being stuffed in a jmp_buf
47 * and being longjmp-d to.
48 */
49void new_thread_handler(void)
47{ 50{
48 int (*fn)(void *), n; 51 int (*fn)(void *), n;
49 void *arg; 52 void *arg;
50 53
51 fn = current->thread.request.u.thread.proc;
52 arg = current->thread.request.u.thread.arg;
53 os_usr1_signal(1);
54 thread_wait(&current->thread.mode.skas.switch_buf,
55 current->thread.mode.skas.fork_buf);
56
57 if(current->thread.prev_sched != NULL) 54 if(current->thread.prev_sched != NULL)
58 schedule_tail(current->thread.prev_sched); 55 schedule_tail(current->thread.prev_sched);
59 current->thread.prev_sched = NULL; 56 current->thread.prev_sched = NULL;
60 57
58 fn = current->thread.request.u.thread.proc;
59 arg = current->thread.request.u.thread.arg;
60
61 /* The return value is 1 if the kernel thread execs a process, 61 /* The return value is 1 if the kernel thread execs a process,
62 * 0 if it just exits 62 * 0 if it just exits
63 */ 63 */
@@ -70,22 +70,13 @@ void new_thread_handler(int sig)
70 else do_exit(0); 70 else do_exit(0);
71} 71}
72 72
73void new_thread_proc(void *stack, void (*handler)(int sig))
74{
75 init_new_thread_stack(stack, handler);
76 os_usr1_process(os_getpid());
77}
78
79void release_thread_skas(struct task_struct *task) 73void release_thread_skas(struct task_struct *task)
80{ 74{
81} 75}
82 76
83void fork_handler(int sig) 77/* Called magically, see new_thread_handler above */
78void fork_handler(void)
84{ 79{
85 os_usr1_signal(1);
86 thread_wait(&current->thread.mode.skas.switch_buf,
87 current->thread.mode.skas.fork_buf);
88
89 force_flush_all(); 80 force_flush_all();
90 if(current->thread.prev_sched == NULL) 81 if(current->thread.prev_sched == NULL)
91 panic("blech"); 82 panic("blech");
@@ -109,7 +100,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
109 unsigned long stack_top, struct task_struct * p, 100 unsigned long stack_top, struct task_struct * p,
110 struct pt_regs *regs) 101 struct pt_regs *regs)
111{ 102{
112 void (*handler)(int); 103 void (*handler)(void);
113 104
114 if(current->thread.forking){ 105 if(current->thread.forking){
115 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas, 106 memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
@@ -128,7 +119,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
128 } 119 }
129 120
130 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, 121 new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
131 &p->thread.mode.skas.fork_buf, handler); 122 handler);
132 return(0); 123 return(0);
133} 124}
134 125
@@ -182,8 +173,7 @@ int start_uml_skas(void)
182 init_task.thread.request.u.thread.proc = start_kernel_proc; 173 init_task.thread.request.u.thread.proc = start_kernel_proc;
183 init_task.thread.request.u.thread.arg = NULL; 174 init_task.thread.request.u.thread.arg = NULL;
184 return(start_idle_thread(task_stack_page(&init_task), 175 return(start_idle_thread(task_stack_page(&init_task),
185 &init_task.thread.mode.skas.switch_buf, 176 &init_task.thread.mode.skas.switch_buf));
186 &init_task.thread.mode.skas.fork_buf));
187} 177}
188 178
189int external_pid_skas(struct task_struct *task) 179int external_pid_skas(struct task_struct *task)