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 7) and /sos/thread.c (Article 7.5)


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

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