SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /sos/thread.c (Article 9.5) and /sos/thread.c (Article 7)


001 /* Copyright (C) 2004,2005 David Decotigny        001 /* Copyright (C) 2004,2005 David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <sos/physmem.h>                          019 #include <sos/physmem.h>
020 #include <sos/kmem_slab.h>                        020 #include <sos/kmem_slab.h>
021 #include <sos/kmalloc.h>                          021 #include <sos/kmalloc.h>
022 #include <sos/klibc.h>                            022 #include <sos/klibc.h>
023 #include <sos/list.h>                             023 #include <sos/list.h>
024 #include <sos/assert.h>                           024 #include <sos/assert.h>
025 #include <hwcore/mm_context.h>                    025 #include <hwcore/mm_context.h>
026 #include <sos/process.h>                          026 #include <sos/process.h>
027                                                   027 
028 #include <drivers/bochs.h>                        028 #include <drivers/bochs.h>
029 #include <drivers/x86_videomem.h>                 029 #include <drivers/x86_videomem.h>
030                                                   030 
031 #include <hwcore/irq.h>                           031 #include <hwcore/irq.h>
032                                                   032 
033 #include "thread.h"                               033 #include "thread.h"
034                                                   034 
035                                                   035 
036 /**                                               036 /**
037  * The size of the stack of a kernel thread       037  * The size of the stack of a kernel thread
038  */                                               038  */
039 #define SOS_THREAD_KERNEL_STACK_SIZE (1*SOS_PA    039 #define SOS_THREAD_KERNEL_STACK_SIZE (1*SOS_PAGE_SIZE)
040                                                   040 
041                                                   041 
042 /**                                               042 /**
043  * The identifier of the thread currently runn    043  * The identifier of the thread currently running on CPU.
044  *                                                044  *
045  * We only support a SINGLE processor, ie a SI    045  * We only support a SINGLE processor, ie a SINGLE thread
046  * running at any time in the system. This gre    046  * running at any time in the system. This greatly simplifies the
047  * implementation of the system, since we don'    047  * implementation of the system, since we don't have to complicate
048  * things in order to retrieve the identifier     048  * things in order to retrieve the identifier of the threads running
049  * on the CPU. On multiprocessor systems the c    049  * on the CPU. On multiprocessor systems the current_thread below is
050  * an array indexed by the id of the CPU, so t    050  * an array indexed by the id of the CPU, so that the challenge is to
051  * retrieve the identifier of the CPU. This is    051  * retrieve the identifier of the CPU. This is usually done based on
052  * the stack address (Linux implementation) or    052  * the stack address (Linux implementation) or on some form of TLS
053  * ("Thread Local Storage": can be implemented    053  * ("Thread Local Storage": can be implemented by way of LDTs for the
054  * processes, accessed through the fs or gs re    054  * processes, accessed through the fs or gs registers).
055  */                                               055  */
056 static volatile struct sos_thread *current_thr    056 static volatile struct sos_thread *current_thread = NULL;
057                                                   057 
058                                                   058 
059 /*                                                059 /*
060  * The list of threads currently in the system    060  * The list of threads currently in the system.
061  *                                                061  *
062  * @note We could have used current_thread for    062  * @note We could have used current_thread for that...
063  */                                               063  */
064 static struct sos_thread *thread_list = NULL;     064 static struct sos_thread *thread_list = NULL;
065                                                   065 
066                                                   066 
067 /**                                               067 /**
068  * The Cache of thread structures                 068  * The Cache of thread structures
069  */                                               069  */
070 static struct sos_kslab_cache *cache_thread;      070 static struct sos_kslab_cache *cache_thread;
071                                                   071 
072                                                   072 
073 /**                                            << 
074  * (Forwad declaration) Helper function to cha << 
075  * the current executing thread. Analogous to  << 
076  * sos_thread_change_current_mm_context() of a << 
077  */                                            << 
078 static sos_ret_t change_current_mm_context(str << 
079                                                << 
080                                                << 
081 struct sos_thread *sos_thread_get_current()       073 struct sos_thread *sos_thread_get_current()
082 {                                                 074 {
083   SOS_ASSERT_FATAL(current_thread->state == SO    075   SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
084   return (struct sos_thread*)current_thread;      076   return (struct sos_thread*)current_thread;
085 }                                                 077 }
086                                                   078 
087                                                   079 
088 inline static sos_ret_t _set_current(struct so    080 inline static sos_ret_t _set_current(struct sos_thread *thr)
089 {                                                 081 {
090   SOS_ASSERT_FATAL(thr->state == SOS_THR_READY    082   SOS_ASSERT_FATAL(thr->state == SOS_THR_READY);
091   current_thread = thr;                           083   current_thread = thr;
092   current_thread->state = SOS_THR_RUNNING;        084   current_thread->state = SOS_THR_RUNNING;
093   return SOS_OK;                                  085   return SOS_OK;
094 }                                                 086 }
095                                                   087 
096                                                   088 
097 sos_ret_t sos_thread_subsystem_setup(sos_vaddr    089 sos_ret_t sos_thread_subsystem_setup(sos_vaddr_t init_thread_stack_base_addr,
098                                      sos_size_    090                                      sos_size_t init_thread_stack_size)
099 {                                                 091 {
100   struct sos_thread *myself;                      092   struct sos_thread *myself;
101                                                   093 
102   /* Allocate the cache of threads */             094   /* Allocate the cache of threads */
103   cache_thread = sos_kmem_cache_create("thread    095   cache_thread = sos_kmem_cache_create("thread",
104                                        sizeof(    096                                        sizeof(struct sos_thread),
105                                        2,         097                                        2,
106                                        0,         098                                        0,
107                                        SOS_KSL    099                                        SOS_KSLAB_CREATE_MAP
108                                        | SOS_K    100                                        | SOS_KSLAB_CREATE_ZERO);
109   if (! cache_thread)                             101   if (! cache_thread)
110     return -SOS_ENOMEM;                           102     return -SOS_ENOMEM;
111                                                   103 
112   /* Allocate a new thread structure for the c    104   /* Allocate a new thread structure for the current running thread */
113   myself = (struct sos_thread*) sos_kmem_cache    105   myself = (struct sos_thread*) sos_kmem_cache_alloc(cache_thread,
114                                                   106                                                      SOS_KSLAB_ALLOC_ATOMIC);
115   if (! myself)                                   107   if (! myself)
116     return -SOS_ENOMEM;                           108     return -SOS_ENOMEM;
117                                                   109 
118   /* Initialize the thread attributes */          110   /* Initialize the thread attributes */
119   strzcpy(myself->name, "[kinit]", SOS_THR_MAX    111   strzcpy(myself->name, "[kinit]", SOS_THR_MAX_NAMELEN);
120   myself->state           = SOS_THR_CREATED;      112   myself->state           = SOS_THR_CREATED;
121   myself->priority        = SOS_SCHED_PRIO_LOW    113   myself->priority        = SOS_SCHED_PRIO_LOWEST;
122   myself->kernel_stack_base_addr = init_thread    114   myself->kernel_stack_base_addr = init_thread_stack_base_addr;
123   myself->kernel_stack_size      = init_thread    115   myself->kernel_stack_size      = init_thread_stack_size;
124                                                   116 
125   /* Do some stack poisoning on the bottom of     117   /* Do some stack poisoning on the bottom of the stack, if needed */
126   sos_cpu_state_prepare_detect_kernel_stack_ov    118   sos_cpu_state_prepare_detect_kernel_stack_overflow(myself->cpu_state,
127                                                   119                                                      myself->kernel_stack_base_addr,
128                                                   120                                                      myself->kernel_stack_size);
129                                                   121 
130   /* Add the thread in the global list */         122   /* Add the thread in the global list */
131   list_singleton_named(thread_list, myself, gb    123   list_singleton_named(thread_list, myself, gbl_prev, gbl_next);
132                                                   124 
133   /* Ok, now pretend that the running thread i    125   /* Ok, now pretend that the running thread is ourselves */
134   myself->state = SOS_THR_READY;                  126   myself->state = SOS_THR_READY;
135   _set_current(myself);                           127   _set_current(myself);
136                                                   128 
137   return SOS_OK;                                  129   return SOS_OK;
138 }                                                 130 }
139                                                   131 
140                                                   132 
141 struct sos_thread *                               133 struct sos_thread *
142 sos_create_kernel_thread(const char *name,        134 sos_create_kernel_thread(const char *name,
143                          sos_kernel_thread_sta    135                          sos_kernel_thread_start_routine_t start_func,
144                          void *start_arg,         136                          void *start_arg,
145                          sos_sched_priority_t     137                          sos_sched_priority_t priority)
146 {                                                 138 {
147   __label__ undo_creation;                        139   __label__ undo_creation;
148   sos_ui32_t flags;                               140   sos_ui32_t flags;
149   struct sos_thread *new_thread;                  141   struct sos_thread *new_thread;
150                                                   142 
151   if (! start_func)                               143   if (! start_func)
152     return NULL;                                  144     return NULL;
153   if (! SOS_SCHED_PRIO_IS_VALID(priority))        145   if (! SOS_SCHED_PRIO_IS_VALID(priority))
154     return NULL;                                  146     return NULL;
155                                                   147 
156   /* Allocate a new thread structure for the c    148   /* Allocate a new thread structure for the current running thread */
157   new_thread                                      149   new_thread
158     = (struct sos_thread*) sos_kmem_cache_allo    150     = (struct sos_thread*) sos_kmem_cache_alloc(cache_thread,
159                                                   151                                                 SOS_KSLAB_ALLOC_ATOMIC);
160   if (! new_thread)                               152   if (! new_thread)
161     return NULL;                                  153     return NULL;
162                                                   154 
163   /* Initialize the thread attributes */          155   /* Initialize the thread attributes */
164   strzcpy(new_thread->name, ((name)?name:"[NON    156   strzcpy(new_thread->name, ((name)?name:"[NONAME]"), SOS_THR_MAX_NAMELEN);
165   new_thread->state    = SOS_THR_CREATED;         157   new_thread->state    = SOS_THR_CREATED;
166   new_thread->priority = priority;                158   new_thread->priority = priority;
167                                                   159 
168   /* Allocate the stack for the new thread */     160   /* Allocate the stack for the new thread */
169   new_thread->kernel_stack_base_addr = sos_kma    161   new_thread->kernel_stack_base_addr = sos_kmalloc(SOS_THREAD_KERNEL_STACK_SIZE, 0);
170   new_thread->kernel_stack_size      = SOS_THR    162   new_thread->kernel_stack_size      = SOS_THREAD_KERNEL_STACK_SIZE;
171   if (! new_thread->kernel_stack_base_addr)       163   if (! new_thread->kernel_stack_base_addr)
172     goto undo_creation;                           164     goto undo_creation;
173                                                   165 
174   /* Initialize the CPU context of the new thr    166   /* Initialize the CPU context of the new thread */
175   if (SOS_OK                                      167   if (SOS_OK
176       != sos_cpu_kstate_init(& new_thread->cpu    168       != sos_cpu_kstate_init(& new_thread->cpu_state,
177                              (sos_cpu_kstate_f    169                              (sos_cpu_kstate_function_arg1_t*) start_func,
178                              (sos_ui32_t) star    170                              (sos_ui32_t) start_arg,
179                              new_thread->kerne    171                              new_thread->kernel_stack_base_addr,
180                              new_thread->kerne    172                              new_thread->kernel_stack_size,
181                              (sos_cpu_kstate_f    173                              (sos_cpu_kstate_function_arg1_t*) sos_thread_exit,
182                              (sos_ui32_t) NULL    174                              (sos_ui32_t) NULL))
183     goto undo_creation;                           175     goto undo_creation;
184                                                   176 
185   /* Add the thread in the global list */         177   /* Add the thread in the global list */
186   sos_disable_IRQs(flags);                        178   sos_disable_IRQs(flags);
187   list_add_tail_named(thread_list, new_thread,    179   list_add_tail_named(thread_list, new_thread, gbl_prev, gbl_next);
188   sos_restore_IRQs(flags);                        180   sos_restore_IRQs(flags);
189                                                   181 
190   /* Mark the thread ready */                     182   /* Mark the thread ready */
191   if (SOS_OK != sos_sched_set_ready(new_thread    183   if (SOS_OK != sos_sched_set_ready(new_thread))
192     goto undo_creation;                           184     goto undo_creation;
193                                                   185 
194   /* Normal non-erroneous end of function */      186   /* Normal non-erroneous end of function */
195   return new_thread;                              187   return new_thread;
196                                                   188 
197  undo_creation:                                   189  undo_creation:
198   if (new_thread->kernel_stack_base_addr)         190   if (new_thread->kernel_stack_base_addr)
199     sos_kfree((sos_vaddr_t) new_thread->kernel    191     sos_kfree((sos_vaddr_t) new_thread->kernel_stack_base_addr);
200   sos_kmem_cache_free((sos_vaddr_t) new_thread    192   sos_kmem_cache_free((sos_vaddr_t) new_thread);
201   return NULL;                                    193   return NULL;
202 }                                                 194 }
203                                                   195 
204                                                   196 
205 /**                                            !! 197 struct sos_thread *
206  * Helper function to create a new user thread !! 198 sos_create_user_thread(const char *name,
207  * given, then the new thread will be the copy !! 199                        struct sos_process *process,
208  * thread. Otherwise the thread will have its  !! 200                        sos_uaddr_t user_initial_PC,
209  * initialized with the user_initial_PC/SP arg !! 201                        sos_ui32_t  user_start_arg1,
210  */                                            !! 202                        sos_ui32_t  user_start_arg2,
211 static struct sos_thread *                     !! 203                        sos_uaddr_t user_initial_SP,
212 create_user_thread(const char *name,           !! 204                        sos_sched_priority_t priority)
213                    struct sos_process *process << 
214                    const struct sos_thread * m << 
215                    const struct sos_cpu_state  << 
216                    sos_uaddr_t user_initial_PC << 
217                    sos_ui32_t  user_start_arg1 << 
218                    sos_ui32_t  user_start_arg2 << 
219                    sos_uaddr_t user_initial_SP << 
220                    sos_sched_priority_t priori << 
221 {                                                 205 {
222   __label__ undo_creation;                        206   __label__ undo_creation;
223   sos_ui32_t flags;                               207   sos_ui32_t flags;
224   struct sos_thread *new_thread;                  208   struct sos_thread *new_thread;
225                                                   209 
226   if (model_thread)                            !! 210   if (! SOS_SCHED_PRIO_IS_VALID(priority))
227     {                                          !! 211     return NULL;
228       SOS_ASSERT_FATAL(model_uctxt);           << 
229     }                                          << 
230   else                                         << 
231     {                                          << 
232       if (! SOS_SCHED_PRIO_IS_VALID(priority)) << 
233         return NULL;                           << 
234     }                                          << 
235                                                   212 
236   /* For a user thread, the process must be gi    213   /* For a user thread, the process must be given */
237   if (! process)                                  214   if (! process)
238     return NULL;                                  215     return NULL;
239                                                   216 
240   /* Allocate a new thread structure for the c    217   /* Allocate a new thread structure for the current running thread */
241   new_thread                                      218   new_thread
242     = (struct sos_thread*) sos_kmem_cache_allo    219     = (struct sos_thread*) sos_kmem_cache_alloc(cache_thread,
243                                                   220                                                 SOS_KSLAB_ALLOC_ATOMIC);
244   if (! new_thread)                               221   if (! new_thread)
245     return NULL;                                  222     return NULL;
246                                                   223 
247   /* Initialize the thread attributes */          224   /* Initialize the thread attributes */
248   strzcpy(new_thread->name, ((name)?name:"[NON    225   strzcpy(new_thread->name, ((name)?name:"[NONAME]"), SOS_THR_MAX_NAMELEN);
249   new_thread->state    = SOS_THR_CREATED;         226   new_thread->state    = SOS_THR_CREATED;
250   if (model_thread)                            !! 227   new_thread->priority = priority;
251     new_thread->priority = model_thread->prior << 
252   else                                         << 
253     new_thread->priority = priority;           << 
254                                                   228 
255   /* Allocate the stack for the new thread */     229   /* Allocate the stack for the new thread */
256   new_thread->kernel_stack_base_addr = sos_kma    230   new_thread->kernel_stack_base_addr = sos_kmalloc(SOS_THREAD_KERNEL_STACK_SIZE, 0);
257   new_thread->kernel_stack_size      = SOS_THR    231   new_thread->kernel_stack_size      = SOS_THREAD_KERNEL_STACK_SIZE;
258   if (! new_thread->kernel_stack_base_addr)       232   if (! new_thread->kernel_stack_base_addr)
259     goto undo_creation;                           233     goto undo_creation;
260                                                   234 
261   /* Initialize the CPU context of the new thr !! 235   if (SOS_OK
262   if (model_thread)                            !! 236       != sos_cpu_ustate_init(& new_thread->cpu_state,
263     {                                          !! 237                              user_initial_PC,
264       if (SOS_OK                               !! 238                              user_start_arg1,
265           != sos_cpu_ustate_duplicate(& new_th !! 239                              user_start_arg2,
266                                       model_uc !! 240                              user_initial_SP,
267                                       user_sta !! 241                              new_thread->kernel_stack_base_addr,
268                                       new_thre !! 242                              new_thread->kernel_stack_size))
269                                       new_thre !! 243     goto undo_creation;
270         goto undo_creation;                    << 
271     }                                          << 
272   else                                         << 
273     {                                          << 
274       if (SOS_OK                               << 
275           != sos_cpu_ustate_init(& new_thread- << 
276                                  user_initial_ << 
277                                  user_start_ar << 
278                                  user_start_ar << 
279                                  user_initial_ << 
280                                  new_thread->k << 
281                                  new_thread->k << 
282         goto undo_creation;                    << 
283     }                                          << 
284                                                   244 
285   /* Attach the new thread to the process */      245   /* Attach the new thread to the process */
286   if (SOS_OK != sos_process_register_thread(pr    246   if (SOS_OK != sos_process_register_thread(process, new_thread))
287     goto undo_creation;                           247     goto undo_creation;
288                                                   248 
289   /* Add the thread in the global list */         249   /* Add the thread in the global list */
290   sos_disable_IRQs(flags);                        250   sos_disable_IRQs(flags);
291   list_add_tail_named(thread_list, new_thread,    251   list_add_tail_named(thread_list, new_thread, gbl_prev, gbl_next);
292   sos_restore_IRQs(flags);                        252   sos_restore_IRQs(flags);
293                                                   253 
294   /* Mark the thread ready */                     254   /* Mark the thread ready */
295   if (SOS_OK != sos_sched_set_ready(new_thread    255   if (SOS_OK != sos_sched_set_ready(new_thread))
296     goto undo_creation;                           256     goto undo_creation;
297                                                   257 
298   /* Normal non-erroneous end of function */      258   /* Normal non-erroneous end of function */
299   return new_thread;                              259   return new_thread;
300                                                   260 
301  undo_creation:                                   261  undo_creation:
302   if (new_thread->kernel_stack_base_addr)         262   if (new_thread->kernel_stack_base_addr)
303     sos_kfree((sos_vaddr_t) new_thread->kernel    263     sos_kfree((sos_vaddr_t) new_thread->kernel_stack_base_addr);
304   sos_kmem_cache_free((sos_vaddr_t) new_thread    264   sos_kmem_cache_free((sos_vaddr_t) new_thread);
305   return NULL;                                    265   return NULL;
306 }                                                 266 }
307                                                   267 
308                                                   268 
309 struct sos_thread *                            << 
310 sos_create_user_thread(const char *name,       << 
311                        struct sos_process *pro << 
312                        sos_uaddr_t user_initia << 
313                        sos_ui32_t  user_start_ << 
314                        sos_ui32_t  user_start_ << 
315                        sos_uaddr_t user_initia << 
316                        sos_sched_priority_t pr << 
317 {                                              << 
318   return create_user_thread(name, process, NUL << 
319                             user_initial_PC,   << 
320                             user_start_arg1,   << 
321                             user_start_arg2,   << 
322                             user_initial_SP,   << 
323                             priority);         << 
324 }                                              << 
325                                                << 
326                                                << 
327 /**                                            << 
328  * Create a new user thread, copy of the given << 
329  * given user context                          << 
330  */                                            << 
331 struct sos_thread *                            << 
332 sos_duplicate_user_thread(const char *name,    << 
333                           struct sos_process * << 
334                           const struct sos_thr << 
335                           const struct sos_cpu << 
336                           sos_ui32_t retval)   << 
337 {                                              << 
338   return create_user_thread(name, process, mod << 
339                             0, retval, 0, 0, 0 << 
340 }                                              << 
341                                                << 
342                                                << 
343 /**                                               269 /**
344  * Helper function to switch to the correct MM    270  * Helper function to switch to the correct MMU configuration to suit
345  * the_thread's needs.                            271  * the_thread's needs.
346  *   - When switching to a user-mode thread, f    272  *   - When switching to a user-mode thread, force the reconfiguration
347  *     of the MMU                                 273  *     of the MMU
348  *   - When switching to a kernel-mode thread,    274  *   - When switching to a kernel-mode thread, only change the MMU
349  *     configuration if the thread was squatti    275  *     configuration if the thread was squatting someone else's space
350  */                                               276  */
351 static void _prepare_mm_context(struct sos_thr    277 static void _prepare_mm_context(struct sos_thread *the_thread)
352 {                                                 278 {
353   /* Going to restore a thread in user mode ?     279   /* Going to restore a thread in user mode ? */
354   if (sos_cpu_context_is_in_user_mode(the_thre    280   if (sos_cpu_context_is_in_user_mode(the_thread->cpu_state)
355       == TRUE)                                    281       == TRUE)
356     {                                             282     {
357       /* Yes: force the MMU to be correctly se    283       /* Yes: force the MMU to be correctly setup with the correct
358          user's address space */                  284          user's address space */
359                                                   285 
360       /* The thread should be a user thread */    286       /* The thread should be a user thread */
361       SOS_ASSERT_FATAL(the_thread->process !=     287       SOS_ASSERT_FATAL(the_thread->process != NULL);
362                                                   288 
363       /* It should not squat any other's addre    289       /* It should not squat any other's address space */
364       SOS_ASSERT_FATAL(the_thread->squatted_mm    290       SOS_ASSERT_FATAL(the_thread->squatted_mm_context == NULL);
365                                                   291 
366       /* Perform an MMU context switch if need    292       /* Perform an MMU context switch if needed */
367       sos_mm_context_switch_to(sos_process_get    293       sos_mm_context_switch_to(sos_process_get_mm_context(the_thread->process));
368     }                                             294     }
369                                                   295 
370   /* the_thread is a kernel thread squatting a    296   /* the_thread is a kernel thread squatting a precise address
371      space ? */                                   297      space ? */
372   else if (the_thread->squatted_mm_context !=     298   else if (the_thread->squatted_mm_context != NULL)
373     sos_mm_context_switch_to(the_thread->squat    299     sos_mm_context_switch_to(the_thread->squatted_mm_context);
374 }                                                 300 }
375                                                   301 
376                                                   302 
377 /** Function called after thr has terminated.     303 /** Function called after thr has terminated. Called from inside the context
378     of another thread, interrupts disabled */     304     of another thread, interrupts disabled */
379 static void delete_thread(struct sos_thread *t    305 static void delete_thread(struct sos_thread *thr)
380 {                                                 306 {
381   sos_ui32_t flags;                               307   sos_ui32_t flags;
382                                                   308 
383   sos_disable_IRQs(flags);                        309   sos_disable_IRQs(flags);
384   list_delete_named(thread_list, thr, gbl_prev    310   list_delete_named(thread_list, thr, gbl_prev, gbl_next);
385   sos_restore_IRQs(flags);                        311   sos_restore_IRQs(flags);
386                                                   312 
387   sos_kfree((sos_vaddr_t) thr->kernel_stack_ba    313   sos_kfree((sos_vaddr_t) thr->kernel_stack_base_addr);
388                                                   314 
389   /* If the thread squats an address space, re    315   /* If the thread squats an address space, release it */
390   if (thr->squatted_mm_context)                   316   if (thr->squatted_mm_context)
391     SOS_ASSERT_FATAL(SOS_OK == change_current_ !! 317     SOS_ASSERT_FATAL(SOS_OK == sos_thread_change_current_mm_context(NULL));
392                                                   318 
393   /* For a user thread: remove the thread from    319   /* For a user thread: remove the thread from the process threads' list */
394   if (thr->process)                               320   if (thr->process)
395     SOS_ASSERT_FATAL(SOS_OK == sos_process_unr    321     SOS_ASSERT_FATAL(SOS_OK == sos_process_unregister_thread(thr));
396                                                   322 
397   memset(thr, 0x0, sizeof(struct sos_thread));    323   memset(thr, 0x0, sizeof(struct sos_thread));
398   sos_kmem_cache_free((sos_vaddr_t) thr);         324   sos_kmem_cache_free((sos_vaddr_t) thr);
399 }                                                 325 }
400                                                   326 
401                                                   327 
402 void sos_thread_exit()                            328 void sos_thread_exit()
403 {                                                 329 {
404   sos_ui32_t flags;                               330   sos_ui32_t flags;
405   struct sos_thread *myself, *next_thread;        331   struct sos_thread *myself, *next_thread;
406                                                   332 
407   /* Interrupt handlers are NOT allowed to exi    333   /* Interrupt handlers are NOT allowed to exit the current thread ! */
408   SOS_ASSERT_FATAL(! sos_servicing_irq());        334   SOS_ASSERT_FATAL(! sos_servicing_irq());
409                                                   335 
410   myself = sos_thread_get_current();              336   myself = sos_thread_get_current();
411                                                   337 
412   /* Refuse to end the current executing threa    338   /* Refuse to end the current executing thread if it still holds a
413      resource ! */                                339      resource ! */
414   SOS_ASSERT_FATAL(list_is_empty_named(myself-    340   SOS_ASSERT_FATAL(list_is_empty_named(myself->kwaitq_list,
415                                        prev_en    341                                        prev_entry_for_thread,
416                                        next_en    342                                        next_entry_for_thread));
417                                                   343 
418   /* Prepare to run the next thread */            344   /* Prepare to run the next thread */
419   sos_disable_IRQs(flags);                        345   sos_disable_IRQs(flags);
420   myself->state = SOS_THR_ZOMBIE;                 346   myself->state = SOS_THR_ZOMBIE;
421   next_thread = sos_reschedule(myself, FALSE);    347   next_thread = sos_reschedule(myself, FALSE);
422                                                   348 
423   /* Make sure that the next_thread is valid *    349   /* Make sure that the next_thread is valid */
424   sos_cpu_state_detect_kernel_stack_overflow(n    350   sos_cpu_state_detect_kernel_stack_overflow(next_thread->cpu_state,
425                                              n    351                                              next_thread->kernel_stack_base_addr,
426                                              n    352                                              next_thread->kernel_stack_size);
427                                                   353 
428   /*                                              354   /*
429    * Perform an MMU context switch if needed      355    * Perform an MMU context switch if needed
430    */                                             356    */
431   _prepare_mm_context(next_thread);               357   _prepare_mm_context(next_thread);
432                                                   358 
433   /* No need for sos_restore_IRQs() here becau    359   /* No need for sos_restore_IRQs() here because the IRQ flag will be
434      restored to that of the next thread upon     360      restored to that of the next thread upon context switch */
435                                                   361 
436   /* Immediate switch to next thread */           362   /* Immediate switch to next thread */
437   _set_current(next_thread);                      363   _set_current(next_thread);
438   sos_cpu_context_exit_to(next_thread->cpu_sta    364   sos_cpu_context_exit_to(next_thread->cpu_state,
439                           (sos_cpu_kstate_func    365                           (sos_cpu_kstate_function_arg1_t*) delete_thread,
440                           (sos_ui32_t) myself)    366                           (sos_ui32_t) myself);
441 }                                                 367 }
442                                                   368 
443                                                   369 
444 sos_sched_priority_t sos_thread_get_priority(s    370 sos_sched_priority_t sos_thread_get_priority(struct sos_thread *thr)
445 {                                                 371 {
446   if (! thr)                                      372   if (! thr)
447     thr = (struct sos_thread*)current_thread;     373     thr = (struct sos_thread*)current_thread;
448                                                   374 
449   return thr->priority;                           375   return thr->priority;
450 }                                                 376 }
451                                                   377 
452                                                   378 
453 sos_thread_state_t sos_thread_get_state(struct    379 sos_thread_state_t sos_thread_get_state(struct sos_thread *thr)
454 {                                                 380 {
455   if (! thr)                                      381   if (! thr)
456     thr = (struct sos_thread*)current_thread;     382     thr = (struct sos_thread*)current_thread;
457                                                   383 
458   return thr->state;                              384   return thr->state;
459 }                                                 385 }
460                                                   386 
461                                                   387 
462 typedef enum { YIELD_MYSELF, BLOCK_MYSELF } sw    388 typedef enum { YIELD_MYSELF, BLOCK_MYSELF } switch_type_t;
463 /**                                               389 /**
464  * Helper function to initiate a context switc    390  * Helper function to initiate a context switch in case the current
465  * thread becomes blocked, waiting for a timeo    391  * thread becomes blocked, waiting for a timeout, or calls yield.
466  */                                               392  */
467 static sos_ret_t _switch_to_next_thread(switch    393 static sos_ret_t _switch_to_next_thread(switch_type_t operation)
468 {                                                 394 {
469   struct sos_thread *myself, *next_thread;        395   struct sos_thread *myself, *next_thread;
470                                                   396 
471   SOS_ASSERT_FATAL(current_thread->state == SO    397   SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
472                                                   398 
473   /* Interrupt handlers are NOT allowed to blo    399   /* Interrupt handlers are NOT allowed to block ! */
474   SOS_ASSERT_FATAL(! sos_servicing_irq());        400   SOS_ASSERT_FATAL(! sos_servicing_irq());
475                                                   401 
476   myself = (struct sos_thread*)current_thread;    402   myself = (struct sos_thread*)current_thread;
477                                                   403 
478   /* Make sure that if we are to be marked "BL    404   /* Make sure that if we are to be marked "BLOCKED", we have any
479      reason of effectively being blocked */       405      reason of effectively being blocked */
480   if (BLOCK_MYSELF == operation)                  406   if (BLOCK_MYSELF == operation)
481     {                                             407     {
482       myself->state = SOS_THR_BLOCKED;            408       myself->state = SOS_THR_BLOCKED;
483     }                                             409     }
484                                                   410 
485   /* Identify the next thread */                  411   /* Identify the next thread */
486   next_thread = sos_reschedule(myself, YIELD_M    412   next_thread = sos_reschedule(myself, YIELD_MYSELF == operation);
487                                                   413 
488   /* Avoid context switch if the context does     414   /* Avoid context switch if the context does not change */
489   if (myself != next_thread)                      415   if (myself != next_thread)
490     {                                             416     {
491       /* Sanity checks for the next thread */     417       /* Sanity checks for the next thread */
492       sos_cpu_state_detect_kernel_stack_overfl    418       sos_cpu_state_detect_kernel_stack_overflow(next_thread->cpu_state,
493                                                   419                                                  next_thread->kernel_stack_base_addr,
494                                                   420                                                  next_thread->kernel_stack_size);
495                                                   421 
496       /*                                          422       /*
497        * Perform an MMU context switch if need    423        * Perform an MMU context switch if needed
498        */                                         424        */
499       _prepare_mm_context(next_thread);           425       _prepare_mm_context(next_thread);
500                                                   426 
501       /*                                          427       /*
502        * Actual CPU context switch                428        * Actual CPU context switch
503        */                                         429        */
504       _set_current(next_thread);                  430       _set_current(next_thread);
505       sos_cpu_context_switch(& myself->cpu_sta    431       sos_cpu_context_switch(& myself->cpu_state, next_thread->cpu_state);
506                                                   432       
507       /* Back here ! */                           433       /* Back here ! */
508       SOS_ASSERT_FATAL(current_thread == mysel    434       SOS_ASSERT_FATAL(current_thread == myself);
509       SOS_ASSERT_FATAL(current_thread->state =    435       SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
510     }                                             436     }
511   else                                            437   else
512     {                                             438     {
513       /* No context switch but still update ID    439       /* No context switch but still update ID of current thread */
514       _set_current(next_thread);                  440       _set_current(next_thread);
515     }                                             441     }
516                                                   442 
517   return SOS_OK;                                  443   return SOS_OK;
518 }                                                 444 }
519                                                   445 
520                                                   446 
521 /**                                               447 /**
522  * Helper function to change the thread's prio    448  * Helper function to change the thread's priority in all the
523  * waitqueues associated with the thread.         449  * waitqueues associated with the thread.
524  */                                               450  */
525 static sos_ret_t _change_waitq_priorities(stru    451 static sos_ret_t _change_waitq_priorities(struct sos_thread *thr,
526                                           sos_    452                                           sos_sched_priority_t priority)
527 {                                                 453 {
528   struct sos_kwaitq_entry *kwq_entry;             454   struct sos_kwaitq_entry *kwq_entry;
529   int nb_waitqs;                                  455   int nb_waitqs;
530                                                   456 
531   list_foreach_forward_named(thr->kwaitq_list,    457   list_foreach_forward_named(thr->kwaitq_list, kwq_entry, nb_waitqs,
532                              prev_entry_for_th    458                              prev_entry_for_thread, next_entry_for_thread)
533     {                                             459     {
534       SOS_ASSERT_FATAL(SOS_OK == sos_kwaitq_ch    460       SOS_ASSERT_FATAL(SOS_OK == sos_kwaitq_change_priority(kwq_entry->kwaitq,
535                                                   461                                                             kwq_entry,
536                                                   462                                                             priority));
537     }                                             463     }
538                                                   464 
539   return SOS_OK;                                  465   return SOS_OK;
540 }                                                 466 }
541                                                   467 
542                                                   468 
543 sos_ret_t sos_thread_set_priority(struct sos_t    469 sos_ret_t sos_thread_set_priority(struct sos_thread *thr,
544                                    sos_sched_p    470                                    sos_sched_priority_t priority)
545 {                                                 471 {
546   __label__ exit_set_prio;                        472   __label__ exit_set_prio;
547   sos_ui32_t flags;                               473   sos_ui32_t flags;
548   sos_ret_t retval;                               474   sos_ret_t retval;
549                                                   475 
550                                                   476 
551   if (! SOS_SCHED_PRIO_IS_VALID(priority))        477   if (! SOS_SCHED_PRIO_IS_VALID(priority))
552     return -SOS_EINVAL;                           478     return -SOS_EINVAL;
553                                                   479 
554   if (! thr)                                      480   if (! thr)
555     thr = (struct sos_thread*)current_thread;     481     thr = (struct sos_thread*)current_thread;
556                                                   482 
557   sos_disable_IRQs(flags);                        483   sos_disable_IRQs(flags);
558                                                   484 
559   /* Signal kwaitq subsystem that the priority    485   /* Signal kwaitq subsystem that the priority of the thread in all
560      the waitq it is waiting in should be upda    486      the waitq it is waiting in should be updated */
561   retval = _change_waitq_priorities(thr, prior    487   retval = _change_waitq_priorities(thr, priority);
562   if (SOS_OK != retval)                           488   if (SOS_OK != retval)
563     goto exit_set_prio;                           489     goto exit_set_prio;
564                                                   490 
565   /* Signal scheduler that the thread, current    491   /* Signal scheduler that the thread, currently in a waiting list,
566      should take into account the change of pr    492      should take into account the change of priority */
567   if (SOS_THR_READY == thr->state)                493   if (SOS_THR_READY == thr->state)
568     retval = sos_sched_change_priority(thr, pr    494     retval = sos_sched_change_priority(thr, priority);
569                                                   495 
570   /* Update priority */                           496   /* Update priority */
571   thr->priority = priority;                       497   thr->priority = priority;
572                                                   498 
573  exit_set_prio:                                   499  exit_set_prio:
574   sos_restore_IRQs(flags);                        500   sos_restore_IRQs(flags);
575   return retval;                                  501   return retval;
576 }                                                 502 }
577                                                   503 
578                                                   504 
579 sos_ret_t sos_thread_yield()                      505 sos_ret_t sos_thread_yield()
580 {                                                 506 {
581   sos_ui32_t flags;                               507   sos_ui32_t flags;
582   sos_ret_t retval;                               508   sos_ret_t retval;
583                                                   509 
584   sos_disable_IRQs(flags);                        510   sos_disable_IRQs(flags);
585                                                   511 
586   retval = _switch_to_next_thread(YIELD_MYSELF    512   retval = _switch_to_next_thread(YIELD_MYSELF);
587                                                   513 
588   sos_restore_IRQs(flags);                        514   sos_restore_IRQs(flags);
589   return retval;                                  515   return retval;
590 }                                                 516 }
591                                                   517 
592                                                   518 
593 /**                                               519 /**
594  * Internal sleep timeout management              520  * Internal sleep timeout management
595  */                                               521  */
596 struct sleep_timeout_params                       522 struct sleep_timeout_params
597 {                                                 523 {
598   struct sos_thread *thread_to_wakeup;            524   struct sos_thread *thread_to_wakeup;
599   sos_bool_t timeout_triggered;                   525   sos_bool_t timeout_triggered;
600 };                                                526 };
601                                                   527 
602                                                   528 
603 /**                                               529 /**
604  * Callback called when a timeout happened        530  * Callback called when a timeout happened
605  */                                               531  */
606 static void sleep_timeout(struct sos_timeout_a    532 static void sleep_timeout(struct sos_timeout_action *act)
607 {                                                 533 {
608   struct sleep_timeout_params *sleep_timeout_p    534   struct sleep_timeout_params *sleep_timeout_params
609     = (struct sleep_timeout_params*) act->rout    535     = (struct sleep_timeout_params*) act->routine_data;
610                                                   536 
611   /* Signal that we have been woken up by the     537   /* Signal that we have been woken up by the timeout */
612   sleep_timeout_params->timeout_triggered = TR    538   sleep_timeout_params->timeout_triggered = TRUE;
613                                                   539 
614   /* Mark the thread ready */                     540   /* Mark the thread ready */
615   SOS_ASSERT_FATAL(SOS_OK ==                      541   SOS_ASSERT_FATAL(SOS_OK ==
616                    sos_thread_force_unblock(sl    542                    sos_thread_force_unblock(sleep_timeout_params
617                                              -    543                                              ->thread_to_wakeup));
618 }                                                 544 }
619                                                   545 
620                                                   546 
621 sos_ret_t sos_thread_sleep(struct sos_time *ti    547 sos_ret_t sos_thread_sleep(struct sos_time *timeout)
622 {                                                 548 {
623   sos_ui32_t flags;                               549   sos_ui32_t flags;
624   struct sleep_timeout_params sleep_timeout_pa    550   struct sleep_timeout_params sleep_timeout_params;
625   struct sos_timeout_action timeout_action;       551   struct sos_timeout_action timeout_action;
626   sos_ret_t retval;                               552   sos_ret_t retval;
627                                                   553 
628   /* Block forever if no timeout is given */      554   /* Block forever if no timeout is given */
629   if (NULL == timeout)                            555   if (NULL == timeout)
630     {                                             556     {
631       sos_disable_IRQs(flags);                    557       sos_disable_IRQs(flags);
632       retval = _switch_to_next_thread(BLOCK_MY    558       retval = _switch_to_next_thread(BLOCK_MYSELF);
633       sos_restore_IRQs(flags);                    559       sos_restore_IRQs(flags);
634                                                   560 
635       return retval;                              561       return retval;
636     }                                             562     }
637                                                   563 
638   /* Initialize the timeout action */             564   /* Initialize the timeout action */
639   sos_time_init_action(& timeout_action);         565   sos_time_init_action(& timeout_action);
640                                                   566 
641   /* Prepare parameters used by the sleep time    567   /* Prepare parameters used by the sleep timeout callback */
642   sleep_timeout_params.thread_to_wakeup           568   sleep_timeout_params.thread_to_wakeup 
643     = (struct sos_thread*)current_thread;         569     = (struct sos_thread*)current_thread;
644   sleep_timeout_params.timeout_triggered = FAL    570   sleep_timeout_params.timeout_triggered = FALSE;
645                                                   571 
646   sos_disable_IRQs(flags);                        572   sos_disable_IRQs(flags);
647                                                   573 
648   /* Now program the timeout ! */                 574   /* Now program the timeout ! */
649   SOS_ASSERT_FATAL(SOS_OK ==                      575   SOS_ASSERT_FATAL(SOS_OK ==
650                    sos_time_register_action_re    576                    sos_time_register_action_relative(& timeout_action,
651                                                   577                                                      timeout,
652                                                   578                                                      sleep_timeout,
653                                                   579                                                      & sleep_timeout_params));
654                                                   580 
655   /* Prepare to block: wait for sleep_timeout(    581   /* Prepare to block: wait for sleep_timeout() to wakeup us in the
656      timeout kwaitq, or for someone to wake us    582      timeout kwaitq, or for someone to wake us up in any other
657      waitq */                                     583      waitq */
658   retval = _switch_to_next_thread(BLOCK_MYSELF    584   retval = _switch_to_next_thread(BLOCK_MYSELF);
659   /* Unblocked by something ! */                  585   /* Unblocked by something ! */
660                                                   586 
661   /* Unblocked by timeout ? */                    587   /* Unblocked by timeout ? */
662   if (sleep_timeout_params.timeout_triggered)     588   if (sleep_timeout_params.timeout_triggered)
663     {                                             589     {
664       /* Yes */                                   590       /* Yes */
665       SOS_ASSERT_FATAL(sos_time_is_zero(& time    591       SOS_ASSERT_FATAL(sos_time_is_zero(& timeout_action.timeout));
666       retval = SOS_OK;                            592       retval = SOS_OK;
667     }                                             593     }
668   else                                            594   else
669     {                                             595     {
670       /* No: We have probably been woken up wh    596       /* No: We have probably been woken up while in some other
671          kwaitq */                                597          kwaitq */
672       SOS_ASSERT_FATAL(SOS_OK == sos_time_unre    598       SOS_ASSERT_FATAL(SOS_OK == sos_time_unregister_action(& timeout_action));
673       retval = -SOS_EINTR;                        599       retval = -SOS_EINTR;
674     }                                             600     }
675                                                   601 
676   sos_restore_IRQs(flags);                        602   sos_restore_IRQs(flags);
677                                                   603 
678   /* Update the remaining timeout */              604   /* Update the remaining timeout */
679   memcpy(timeout, & timeout_action.timeout, si    605   memcpy(timeout, & timeout_action.timeout, sizeof(struct sos_time));
680                                                   606 
681   return retval;                                  607   return retval;
682 }                                                 608 }
683                                                   609 
684                                                   610 
685 sos_ret_t sos_thread_force_unblock(struct sos_    611 sos_ret_t sos_thread_force_unblock(struct sos_thread *thread)
686 {                                                 612 {
687   sos_ret_t retval;                               613   sos_ret_t retval;
688   sos_ui32_t flags;                               614   sos_ui32_t flags;
689                                                   615 
690   if (! thread)                                   616   if (! thread)
691     return -SOS_EINVAL;                           617     return -SOS_EINVAL;
692                                                   618   
693   sos_disable_IRQs(flags);                        619   sos_disable_IRQs(flags);
694                                                   620 
695   /* Thread already woken up ? */                 621   /* Thread already woken up ? */
696   retval = SOS_OK;                                622   retval = SOS_OK;
697   switch(sos_thread_get_state(thread))            623   switch(sos_thread_get_state(thread))
698     {                                             624     {
699     case SOS_THR_RUNNING:                         625     case SOS_THR_RUNNING:
700     case SOS_THR_READY:                           626     case SOS_THR_READY:
701       /* Do nothing */                            627       /* Do nothing */
702       break;                                      628       break;
703                                                   629 
704     case SOS_THR_ZOMBIE:                          630     case SOS_THR_ZOMBIE:
705       retval = -SOS_EFATAL;                       631       retval = -SOS_EFATAL;
706       break;                                      632       break;
707                                                   633 
708     default:                                      634     default:
709       retval = sos_sched_set_ready(thread);       635       retval = sos_sched_set_ready(thread);
710       break;                                      636       break;
711     }                                             637     }
712                                                   638 
713   sos_restore_IRQs(flags);                        639   sos_restore_IRQs(flags);
714                                                   640 
715   return retval;                                  641   return retval;
716 }                                                 642 }
717                                                   643 
718                                                   644 
719 void sos_thread_dump_backtrace(sos_bool_t on_c    645 void sos_thread_dump_backtrace(sos_bool_t on_console,
720                                sos_bool_t on_b    646                                sos_bool_t on_bochs)
721 {                                                 647 {
722   sos_vaddr_t stack_bottom = current_thread->k    648   sos_vaddr_t stack_bottom = current_thread->kernel_stack_base_addr;
723   sos_size_t stack_size    = current_thread->k    649   sos_size_t stack_size    = current_thread->kernel_stack_size;
724                                                   650 
725   void backtracer(sos_vaddr_t PC,              !! 651   static void backtracer(sos_vaddr_t PC,
726                   sos_vaddr_t params,          !! 652                          sos_vaddr_t params,
727                   sos_ui32_t depth,            !! 653                          sos_ui32_t depth,
728                   void *custom_arg)            !! 654                          void *custom_arg)
729     {                                             655     {
730       sos_ui32_t invalid = 0xffffffff, *arg1,     656       sos_ui32_t invalid = 0xffffffff, *arg1, *arg2, *arg3, *arg4;
731                                                   657 
732       /* Get the address of the first 3 argume    658       /* Get the address of the first 3 arguments from the
733          frame. Among these arguments, 0, 1, 2    659          frame. Among these arguments, 0, 1, 2, 3 arguments might be
734          meaningful (depending on how many arg    660          meaningful (depending on how many arguments the function may
735          take). */                                661          take). */
736       arg1 = (sos_ui32_t*)params;                 662       arg1 = (sos_ui32_t*)params;
737       arg2 = (sos_ui32_t*)(params+4);             663       arg2 = (sos_ui32_t*)(params+4);
738       arg3 = (sos_ui32_t*)(params+8);             664       arg3 = (sos_ui32_t*)(params+8);
739       arg4 = (sos_ui32_t*)(params+12);            665       arg4 = (sos_ui32_t*)(params+12);
740                                                   666 
741       /* Make sure the addresses of these argu    667       /* Make sure the addresses of these arguments fit inside the
742          stack boundaries */                      668          stack boundaries */
743 #define INTERVAL_OK(b,v,u) ( ((b) <= (sos_vadd    669 #define INTERVAL_OK(b,v,u) ( ((b) <= (sos_vaddr_t)(v)) \
744                              && ((sos_vaddr_t)    670                              && ((sos_vaddr_t)(v) < (u)) )
745       if (!INTERVAL_OK(stack_bottom, arg1, sta    671       if (!INTERVAL_OK(stack_bottom, arg1, stack_bottom + stack_size))
746         arg1 = &invalid;                          672         arg1 = &invalid;
747       if (!INTERVAL_OK(stack_bottom, arg2, sta    673       if (!INTERVAL_OK(stack_bottom, arg2, stack_bottom + stack_size))
748         arg2 = &invalid;                          674         arg2 = &invalid;
749       if (!INTERVAL_OK(stack_bottom, arg3, sta    675       if (!INTERVAL_OK(stack_bottom, arg3, stack_bottom + stack_size))
750         arg3 = &invalid;                          676         arg3 = &invalid;
751       if (!INTERVAL_OK(stack_bottom, arg4, sta    677       if (!INTERVAL_OK(stack_bottom, arg4, stack_bottom + stack_size))
752         arg4 = &invalid;                          678         arg4 = &invalid;
753                                                   679 
754       /* Print the function context for this f    680       /* Print the function context for this frame */
755       if (on_bochs)                               681       if (on_bochs)
756         sos_bochs_printf("[%d] PC=0x%x arg1=0x    682         sos_bochs_printf("[%d] PC=0x%x arg1=0x%x arg2=0x%x arg3=0x%x\n",
757                          (unsigned)depth, (uns    683                          (unsigned)depth, (unsigned)PC,
758                          (unsigned)*arg1, (uns    684                          (unsigned)*arg1, (unsigned)*arg2,
759                          (unsigned)*arg3);        685                          (unsigned)*arg3);
760                                                   686 
761       if (on_console)                             687       if (on_console)
762         sos_x86_videomem_printf(23-depth, 3,      688         sos_x86_videomem_printf(23-depth, 3,
763                                 SOS_X86_VIDEO_    689                                 SOS_X86_VIDEO_BG_BLUE
764                                   | SOS_X86_VI    690                                   | SOS_X86_VIDEO_FG_LTGREEN,
765                                 "[%d] PC=0x%x     691                                 "[%d] PC=0x%x arg1=0x%x arg2=0x%x arg3=0x%x arg4=0x%x",
766                                 (unsigned)dept    692                                 (unsigned)depth, PC,
767                                 (unsigned)*arg    693                                 (unsigned)*arg1, (unsigned)*arg2,
768                                 (unsigned)*arg    694                                 (unsigned)*arg3, (unsigned)*arg4);
769                                                   695       
770     }                                             696     }
771                                                   697 
772   sos_backtrace(NULL, 15, stack_bottom, stack_    698   sos_backtrace(NULL, 15, stack_bottom, stack_size,
773                 backtracer, NULL);                699                 backtracer, NULL);
774 }                                                 700 }
775                                                   701 
776                                                   702 
777                                                   703 
778 /* *******************************************    704 /* **********************************************
779  * Restricted functions                           705  * Restricted functions
780  */                                               706  */
781                                                   707 
782                                                   708 
783 static sos_ret_t                               !! 709 sos_ret_t
784 change_current_mm_context(struct sos_mm_contex !! 710 sos_thread_change_current_mm_context(struct sos_mm_context *mm_ctxt)
785 {                                                 711 {
                                                   >> 712   sos_ui32_t flags;
                                                   >> 713 
786   /* Retrieve the previous mm context */          714   /* Retrieve the previous mm context */
787   struct sos_mm_context * prev_mm_ctxt            715   struct sos_mm_context * prev_mm_ctxt
788     = current_thread->squatted_mm_context;        716     = current_thread->squatted_mm_context;
789                                                   717 
                                                   >> 718   /* We should either select a new squatted_mm_context or revert to
                                                   >> 719      the default */
                                                   >> 720   if (mm_ctxt != NULL)
                                                   >> 721     SOS_ASSERT_FATAL(prev_mm_ctxt == NULL);
                                                   >> 722   else
                                                   >> 723     SOS_ASSERT_FATAL(prev_mm_ctxt != NULL);
                                                   >> 724 
                                                   >> 725   sos_disable_IRQs(flags);
                                                   >> 726 
790   /* Update current thread's squatted mm conte    727   /* Update current thread's squatted mm context */
791   current_thread->squatted_mm_context = mm_ctx    728   current_thread->squatted_mm_context = mm_ctxt;
792                                                   729 
793   /* Update the reference counts and switch th    730   /* Update the reference counts and switch the MMU configuration if
794      needed */                                    731      needed */
795   if (mm_ctxt != NULL)                            732   if (mm_ctxt != NULL)
796     {                                             733     {
797       sos_mm_context_ref(mm_ctxt); /* Because     734       sos_mm_context_ref(mm_ctxt); /* Because it is now referenced as
798                                       the squa    735                                       the squatted_mm_context field of
799                                       the thre    736                                       the thread */
800       sos_mm_context_switch_to(mm_ctxt);          737       sos_mm_context_switch_to(mm_ctxt);
801     }                                             738     }
802   else                                            739   else
803     sos_mm_context_unref(prev_mm_ctxt); /* Bec    740     sos_mm_context_unref(prev_mm_ctxt); /* Because it is not referenced as
804                                            the    741                                            the squatted_mm_context field of
805                                            the    742                                            the thread any more */
806                                                   743 
807   return SOS_OK;                               << 
808 }                                              << 
809                                                << 
810                                                << 
811 sos_ret_t                                      << 
812 sos_thread_prepare_user_space_access(struct so << 
813                                      sos_vaddr << 
814 {                                              << 
815   sos_ret_t  retval;                           << 
816   sos_ui32_t flags;                            << 
817                                                << 
818   if (! dest_as)                               << 
819     {                                          << 
820       /* Thread is not a user thread: do nothi << 
821       if (! current_thread->process)           << 
822         return -SOS_EINVAL;                    << 
823                                                << 
824       dest_as = sos_process_get_address_space( << 
825     }                                          << 
826   else                                         << 
827     /* Don't allow to access to an address spa << 
828        of the current thread if the page fault << 
829     SOS_ASSERT_FATAL(! fixup_retvaddr);        << 
830                                                << 
831   sos_disable_IRQs(flags);                     << 
832   SOS_ASSERT_FATAL(NULL == current_thread->squ << 
833   SOS_ASSERT_FATAL(0 == current_thread->fixup_ << 
834                                                << 
835   /* Change the MMU configuration and init the << 
836   retval = change_current_mm_context(sos_umem_ << 
837   if (SOS_OK == retval)                        << 
838     {                                          << 
839       current_thread->fixup_uaccess.return_vad << 
840       current_thread->fixup_uaccess.faulted_ua << 
841     }                                          << 
842                                                << 
843   sos_restore_IRQs(flags);                        744   sos_restore_IRQs(flags);
844   return retval;                               << 
845 }                                              << 
846                                                   745 
847                                                !! 746   return SOS_OK;
848 sos_ret_t                                      << 
849 sos_thread_end_user_space_access(void)         << 
850 {                                              << 
851   sos_ret_t  retval;                           << 
852   sos_ui32_t flags;                            << 
853                                                << 
854   sos_disable_IRQs(flags);                     << 
855   SOS_ASSERT_FATAL(NULL != current_thread->squ << 
856                                                << 
857   /* Don't impose anything regarding the curre << 
858   retval = change_current_mm_context(NULL);    << 
859   current_thread->fixup_uaccess.return_vaddr   << 
860   current_thread->fixup_uaccess.faulted_uaddr  << 
861                                                << 
862   sos_restore_IRQs(flags);                     << 
863   return retval;                               << 
864 }                                                 747 }
865                                                   748 
866                                                   749 
867 void sos_thread_prepare_syscall_switch_back(st    750 void sos_thread_prepare_syscall_switch_back(struct sos_cpu_state *cpu_state)
868 {                                                 751 {
869   /* Don't preempt the current thread */          752   /* Don't preempt the current thread */
870                                                   753 
871   /*                                              754   /*
872    * Save the state of the interrupted context    755    * Save the state of the interrupted context to make sure that:
873    *   - The list of threads correctly reflect    756    *   - The list of threads correctly reflects that the thread is back
874    *     in user mode                             757    *     in user mode
875    *   - _prepare_mm_context() deals with the     758    *   - _prepare_mm_context() deals with the correct mm_context
876    */                                             759    */
877   current_thread->cpu_state = cpu_state;          760   current_thread->cpu_state = cpu_state;
878                                                   761 
879   /* Perform an MMU context switch if needed *    762   /* Perform an MMU context switch if needed */
880   _prepare_mm_context((struct sos_thread*) cur    763   _prepare_mm_context((struct sos_thread*) current_thread);
881 }                                                 764 }
882                                                   765 
883                                                   766 
884 void sos_thread_prepare_exception_switch_back(    767 void sos_thread_prepare_exception_switch_back(struct sos_cpu_state *cpu_state)
885 {                                                 768 {
886   /* Don't preempt the current thread */          769   /* Don't preempt the current thread */
887                                                   770 
888   /*                                              771   /*
889    * Save the state of the interrupted context    772    * Save the state of the interrupted context to make sure that:
890    *   - The list of threads correctly reflect    773    *   - The list of threads correctly reflects that the thread is
891    *     running in user or kernel mode           774    *     running in user or kernel mode
892    *   - _prepare_mm_context() deals with the     775    *   - _prepare_mm_context() deals with the correct mm_context
893    */                                             776    */
894   current_thread->cpu_state = cpu_state;          777   current_thread->cpu_state = cpu_state;
895                                                   778 
896   /* Perform an MMU context switch if needed *    779   /* Perform an MMU context switch if needed */
897   _prepare_mm_context((struct sos_thread*) cur    780   _prepare_mm_context((struct sos_thread*) current_thread);
898 }                                                 781 }
899                                                   782 
900                                                   783 
901 void                                              784 void
902 sos_thread_prepare_irq_servicing(struct sos_cp    785 sos_thread_prepare_irq_servicing(struct sos_cpu_state *interrupted_state)
903 {                                                 786 {
904   current_thread->cpu_state = interrupted_stat    787   current_thread->cpu_state = interrupted_state;
905 }                                                 788 }
906                                                   789 
907                                                   790 
908 struct sos_cpu_state *                            791 struct sos_cpu_state *
909 sos_thread_prepare_irq_switch_back(void)          792 sos_thread_prepare_irq_switch_back(void)
910 {                                                 793 {
911   struct sos_thread *myself, *next_thread;        794   struct sos_thread *myself, *next_thread;
912                                                   795 
913   /* In SOS, threads in kernel mode are NEVER     796   /* In SOS, threads in kernel mode are NEVER preempted from the
914      interrupt handlers ! */                      797      interrupt handlers ! */
915   if (! sos_cpu_context_is_in_user_mode(curren    798   if (! sos_cpu_context_is_in_user_mode(current_thread->cpu_state))
916     return current_thread->cpu_state;             799     return current_thread->cpu_state;
917                                                   800 
918   /*                                              801   /*
919    * Here we are dealing only with possible pr    802    * Here we are dealing only with possible preemption of user threads
920    * in user context !                            803    * in user context !
921    */                                             804    */
922                                                   805 
923   /* Make sure the thread actually is a user t    806   /* Make sure the thread actually is a user thread */
924   SOS_ASSERT_FATAL(current_thread->process !=     807   SOS_ASSERT_FATAL(current_thread->process != NULL);
925                                                   808 
926   /* Save the state of the interrupted context    809   /* Save the state of the interrupted context */
927   myself = (struct sos_thread*)current_thread;    810   myself = (struct sos_thread*)current_thread;
928                                                   811 
929   /* Select the next thread to run */             812   /* Select the next thread to run */
930   next_thread = sos_reschedule(myself, FALSE);    813   next_thread = sos_reschedule(myself, FALSE);
931                                                   814 
932   /* Perform an MMU context switch if needed *    815   /* Perform an MMU context switch if needed */
933   _prepare_mm_context(next_thread);               816   _prepare_mm_context(next_thread);
934                                                   817 
935   /* Setup the next_thread's context into the     818   /* Setup the next_thread's context into the CPU */
936   _set_current(next_thread);                      819   _set_current(next_thread);
937   return next_thread->cpu_state;                  820   return next_thread->cpu_state;
938 }                                                 821 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]