1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
/* ia32-cmain.c - Startup code for the ia32.
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Written by Marcus Brinkmann.
This file is part of the GNU Hurd.
The GNU Hurd 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, or (at
your option) any later version.
The GNU Hurd 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, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <alloca.h>
#include <stdint.h>
#include <l4/globals.h>
#include <l4/init.h>
#include <l4/stubs.h>
#include <l4/stubs-init.h>
#include "deva.h"
#include <hurd/wortel.h>
#include <hurd/startup.h>
#include <hurd/mm.h>
/* Initialized by the machine-specific startup-code. */
extern struct hurd_startup_data *__hurd_startup_data;
/* Initialized in cmain. */
l4_thread_id_t wortel_thread_id;
wortel_cap_id_t wortel_cap_id;
/* Pager thread. */
l4_thread_id_t pager_tid;
/* Initialize libl4, setup the argument vector, and pass control over
to the main function. */
void
cmain (void)
{
error_t err;
int argc = 0;
char **argv = 0;
l4_init ();
l4_init_stubs ();
err = task_thread_alloc (__hurd_startup_data->task.server,
__hurd_startup_data->task.cap_handle,
/* We are the second thread. */
(void *)
(l4_address (__hurd_startup_data->utcb_area)
+ l4_utcb_size ()),
&pager_tid);
if (err)
{
printf ("Unable to allocate a thread for the pager thread.\n");
return;
}
hurd_mm_init (pager_tid);
l4_set_pager (pager_tid);
wortel_thread_id = __hurd_startup_data->wortel.server;
wortel_cap_id = __hurd_startup_data->wortel.cap_handle;
argc = 1;
argv = alloca (sizeof (char *) * 2);
argv[0] = program_name;
argv[1] = 0;
/* Now invoke the main function. */
main (argc, argv);
/* Never reached. */
}
#define __thread_stack_pointer() ({ \
void *__sp__; \
__asm__ ("movl %%esp, %0" : "=r" (__sp__)); \
__sp__; \
})
#define __thread_set_stack_pointer(sp) ({ \
__asm__ ("movl %0, %%esp" : : "r" (sp)); \
})
/* Switch execution transparently to thread TO. The thread FROM,
which must be the current thread, will be halted. */
void
switch_thread (l4_thread_id_t from, l4_thread_id_t to)
{
void *current_stack;
/* FIXME: Figure out how much we need. Probably only one return
address. */
char small_sub_stack[16];
unsigned int i;
/* FIXME: FROM is an argument to force gcc to evaluate it before the
thread switch. Maybe this can be done better, but it's
magical, so be careful. */
/* Save the machine context. */
__asm__ __volatile__ ("pusha");
__asm__ __volatile__ ("pushf");
/* Start the TO thread. It will be eventually become a clone of our
thread. */
current_stack = __thread_stack_pointer ();
l4_start_sp_ip (to, (l4_word_t) current_stack,
(l4_word_t) &&thread_switch_entry);
/* We need a bit of extra space on the stack for
l4_thread_switch. */
__thread_set_stack_pointer (small_sub_stack + sizeof (small_sub_stack));
/* We can't use while(1), because then gcc will become clever and
optimize away everything after thread_switch_entry. */
for (i = 1; i; i++)
l4_thread_switch (to);
thread_switch_entry:
/* Restore the machine context. */
__asm__ __volatile__ ("popf");
__asm__ __volatile__ ("popa");
/* The thread TO continues here. */
l4_stop (from);
}
|