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/main.c (Article 6) and /sos/main.c (Article 9.5)


001 /* Copyright (C) 2004  The SOS Team               001 /* Copyright (C) 2004  The SOS Team
002    Copyright (C) 1999  Free Software Foundatio << 
003                                                   002 
004    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
008                                                   007    
009    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details    011    GNU General Public License for more details.
013                                                   012    
014    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA.                                           016    USA. 
018 */                                                017 */
019                                                   018 
                                                   >> 019 #include <sos/errno.h>
                                                   >> 020 
020 /* Include definitions of the multiboot standa    021 /* Include definitions of the multiboot standard */
021 #include <bootstrap/multiboot.h>                  022 #include <bootstrap/multiboot.h>
022 #include <hwcore/idt.h>                           023 #include <hwcore/idt.h>
023 #include <hwcore/gdt.h>                           024 #include <hwcore/gdt.h>
024 #include <hwcore/irq.h>                           025 #include <hwcore/irq.h>
025 #include <hwcore/exception.h>                     026 #include <hwcore/exception.h>
026 #include <hwcore/i8254.h>                         027 #include <hwcore/i8254.h>
027 #include <sos/list.h>                             028 #include <sos/list.h>
028 #include <sos/physmem.h>                          029 #include <sos/physmem.h>
029 #include <hwcore/paging.h>                        030 #include <hwcore/paging.h>
                                                   >> 031 #include <hwcore/mm_context.h>
                                                   >> 032 #include <hwcore/swintr.h>
030 #include <sos/kmem_vmm.h>                         033 #include <sos/kmem_vmm.h>
031 #include <sos/kmalloc.h>                          034 #include <sos/kmalloc.h>
                                                   >> 035 #include <sos/time.h>
                                                   >> 036 #include <sos/thread.h>
                                                   >> 037 #include <sos/process.h>
                                                   >> 038 #include <sos/umem_vmm.h>
032 #include <sos/klibc.h>                            039 #include <sos/klibc.h>
033 #include <sos/assert.h>                           040 #include <sos/assert.h>
034 #include <drivers/x86_videomem.h>                 041 #include <drivers/x86_videomem.h>
035 #include <drivers/bochs.h>                        042 #include <drivers/bochs.h>
036                                                !! 043 #include <sos/calcload.h>
                                                   >> 044 #include <sos/umem_vmm.h>
                                                   >> 045 #include <sos/binfmt_elf32.h>
                                                   >> 046 #include <drivers/zero.h>
                                                   >> 047 #include <sos/fs.h>
                                                   >> 048 #include <drivers/fs_virtfs.h>
                                                   >> 049 #include <drivers/devices.h>
                                                   >> 050 #include <drivers/mem.h>
                                                   >> 051 #include <drivers/tty.h>
                                                   >> 052 #include <drivers/console.h>
                                                   >> 053 #include <drivers/serial.h>
                                                   >> 054 #include <sos/blkdev.h>
                                                   >> 055 #include <sos/fs_pagecache.h>
                                                   >> 056 #include <drivers/ide.h>
037                                                   057 
038 /* Helper function to display each bits of a 3    058 /* Helper function to display each bits of a 32bits integer on the
039    screen as dark or light carrets */             059    screen as dark or light carrets */
040 void display_bits(unsigned char row, unsigned     060 void display_bits(unsigned char row, unsigned char col,
041                   unsigned char attribute,        061                   unsigned char attribute,
042                   sos_ui32_t integer)             062                   sos_ui32_t integer)
043 {                                                 063 {
044   int i;                                          064   int i;
045   /* Scan each bit of the integer, MSb first *    065   /* Scan each bit of the integer, MSb first */
046   for (i = 31 ; i >= 0 ; i--)                     066   for (i = 31 ; i >= 0 ; i--)
047     {                                             067     {
048       /* Test if bit i of 'integer' is set */     068       /* Test if bit i of 'integer' is set */
049       int bit_i = (integer & (1 << i));           069       int bit_i = (integer & (1 << i));
050       /* Ascii 219 => dark carret, Ascii 177 =    070       /* Ascii 219 => dark carret, Ascii 177 => light carret */
051       unsigned char ascii_code = bit_i?219:177    071       unsigned char ascii_code = bit_i?219:177;
052       sos_x86_videomem_putchar(row, col++,        072       sos_x86_videomem_putchar(row, col++,
053                                attribute,         073                                attribute,
054                                ascii_code);       074                                ascii_code);
055     }                                             075     }
056 }                                                 076 }
057                                                   077 
058                                                << 
059 /* Clock IRQ handler */                           078 /* Clock IRQ handler */
060 static void clk_it(int intid,                  !! 079 static void clk_it(int intid)
061                    const struct sos_cpu_kstate << 
062 {                                                 080 {
063   static sos_ui32_t clock_count = 0;              081   static sos_ui32_t clock_count = 0;
064                                                   082 
065   display_bits(0, 48,                             083   display_bits(0, 48,
066                SOS_X86_VIDEO_FG_LTGREEN | SOS_    084                SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
067                clock_count);                      085                clock_count);
068   clock_count++;                                  086   clock_count++;
                                                   >> 087 
                                                   >> 088   /* Execute the expired timeout actions (if any) */
                                                   >> 089   sos_time_do_tick();
                                                   >> 090 
                                                   >> 091   /* Update scheduler statistics and status */
                                                   >> 092   sos_sched_do_timer_tick();
069 }                                                 093 }
070                                                   094 
071                                                   095 
072 /* ===========================================    096 /* ======================================================================
073  * Page fault exception handling                  097  * Page fault exception handling
074  */                                               098  */
075                                                   099 
076 /* Helper function to dump a backtrace on boch << 
077 static void dump_backtrace(const struct sos_cp << 
078                            sos_vaddr_t stack_b << 
079                            sos_size_t  stack_s << 
080                            sos_bool_t on_conso << 
081                            sos_bool_t on_bochs << 
082 {                                              << 
083   static void backtracer(sos_vaddr_t PC,       << 
084                          sos_vaddr_t params,   << 
085                          sos_ui32_t depth,     << 
086                          void *custom_arg)     << 
087     {                                          << 
088       sos_ui32_t invalid = 0xffffffff, *arg1,  << 
089                                                << 
090       /* Get the address of the first 3 argume << 
091          frame. Among these arguments, 0, 1, 2 << 
092          meaningful (depending on how many arg << 
093          take). */                             << 
094       arg1 = (sos_ui32_t*)params;              << 
095       arg2 = (sos_ui32_t*)(params+4);          << 
096       arg3 = (sos_ui32_t*)(params+8);          << 
097       arg4 = (sos_ui32_t*)(params+12);         << 
098                                                << 
099       /* Make sure the addresses of these argu << 
100          stack boundaries */                   << 
101 #define INTERVAL_OK(b,v,u) ( ((b) <= (sos_vadd << 
102                              && ((sos_vaddr_t) << 
103       if (!INTERVAL_OK(stack_bottom, arg1, sta << 
104         arg1 = &invalid;                       << 
105       if (!INTERVAL_OK(stack_bottom, arg2, sta << 
106         arg2 = &invalid;                       << 
107       if (!INTERVAL_OK(stack_bottom, arg3, sta << 
108         arg3 = &invalid;                       << 
109       if (!INTERVAL_OK(stack_bottom, arg4, sta << 
110         arg4 = &invalid;                       << 
111                                                << 
112       /* Print the function context for this f << 
113       if (on_bochs)                            << 
114         sos_bochs_printf("[%d] PC=0x%x arg1=0x << 
115                          (unsigned)depth, (uns << 
116                          (unsigned)*arg1, (uns << 
117                          (unsigned)*arg3);     << 
118                                                << 
119       if (on_console)                          << 
120         sos_x86_videomem_printf(23-depth, 3,   << 
121                                 SOS_X86_VIDEO_ << 
122                                   | SOS_X86_VI << 
123                                 "[%d] PC=0x%x  << 
124                                 (unsigned)dept << 
125                                 (unsigned)*arg << 
126                                 (unsigned)*arg << 
127                                                << 
128     }                                          << 
129                                                << 
130   sos_backtrace(cpu_kstate, 15, stack_bottom,  << 
131 }                                              << 
132                                                << 
133                                                   100 
134 /* Page fault exception handler with demand pa    101 /* Page fault exception handler with demand paging for the kernel */
135 static void pgflt_ex(int intid, const struct s !! 102 static void pgflt_ex(int intid, struct sos_cpu_state *ctxt)
136 {                                                 103 {
137   static sos_ui32_t demand_paging_count = 0;      104   static sos_ui32_t demand_paging_count = 0;
138   sos_vaddr_t faulting_vaddr = sos_cpu_kstate_ !! 105   struct sos_thread * cur_thr = sos_thread_get_current();
                                                   >> 106   sos_vaddr_t faulting_vaddr  = sos_cpu_context_get_EX_faulting_vaddr(ctxt);
139   sos_paddr_t ppage_paddr;                        107   sos_paddr_t ppage_paddr;
140                                                   108 
                                                   >> 109   if (sos_cpu_context_is_in_user_mode(ctxt)
                                                   >> 110       || (cur_thr->fixup_uaccess.return_vaddr))
                                                   >> 111     {
                                                   >> 112       __label__ unforce_address_space;
                                                   >> 113       sos_bool_t need_to_setup_mmu;
                                                   >> 114       sos_ui32_t errcode = sos_cpu_context_get_EX_info(ctxt);
                                                   >> 115 
                                                   >> 116       /* Make sure to always stay in the interrupted thread's MMU
                                                   >> 117          configuration */
                                                   >> 118       need_to_setup_mmu = (cur_thr->squatted_mm_context
                                                   >> 119                            != sos_process_get_mm_context(cur_thr->process));
                                                   >> 120       if (need_to_setup_mmu)
                                                   >> 121         sos_thread_prepare_user_space_access(NULL, 0);
                                                   >> 122 
                                                   >> 123       if (SOS_OK ==
                                                   >> 124           sos_umem_vmm_try_resolve_page_fault(faulting_vaddr,
                                                   >> 125                                               errcode & (1 << 1),
                                                   >> 126                                               TRUE))
                                                   >> 127         goto unforce_address_space;
                                                   >> 128 
                                                   >> 129       /* If the page fault occured in kernel mode, return to kernel to
                                                   >> 130          the fixup address */
                                                   >> 131       if (! sos_cpu_context_is_in_user_mode(ctxt))
                                                   >> 132         {
                                                   >> 133           cur_thr->fixup_uaccess.faulted_uaddr = faulting_vaddr;
                                                   >> 134           sos_cpu_context_set_EX_return_address(ctxt,
                                                   >> 135                                                 cur_thr->fixup_uaccess.return_vaddr);
                                                   >> 136           goto unforce_address_space;
                                                   >> 137         }
                                                   >> 138 
                                                   >> 139       if (need_to_setup_mmu)
                                                   >> 140         sos_thread_end_user_space_access();
                                                   >> 141 
                                                   >> 142       sos_bochs_printf("\e[35mTHR %p: Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\e[m\n",
                                                   >> 143                        (void*)sos_thread_get_current(),
                                                   >> 144                        sos_cpu_context_get_PC(ctxt),
                                                   >> 145                        (unsigned)faulting_vaddr,
                                                   >> 146                        (unsigned)sos_cpu_context_get_EX_info(ctxt));
                                                   >> 147       sos_bochs_printf("Terminating User thread\n");
                                                   >> 148       sos_thread_exit();
                                                   >> 149 
                                                   >> 150     unforce_address_space:
                                                   >> 151       if (need_to_setup_mmu)
                                                   >> 152         sos_thread_end_user_space_access();
                                                   >> 153       return;
                                                   >> 154     }
                                                   >> 155 
141   /* Check if address is covered by any VMM ra    156   /* Check if address is covered by any VMM range */
142   if (! sos_kmem_vmm_is_valid_vaddr(faulting_v    157   if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr))
143     {                                             158     {
144       /* No: The page fault is out of any kern    159       /* No: The page fault is out of any kernel virtual region. For
145          the moment, we don't handle this. */     160          the moment, we don't handle this. */
146       dump_backtrace(ctxt,                     !! 161       sos_display_fatal_error("Unresolved page Fault at instruction 0x%x on access to address 0x%x (info=%x)!",
147                      bootstrap_stack_bottom,   !! 162                               sos_cpu_context_get_PC(ctxt),
148                      bootstrap_stack_size,     << 
149                      TRUE, TRUE);              << 
150       sos_display_fatal_error("Unresolved page << 
151                               (unsigned)faulti    163                               (unsigned)faulting_vaddr,
152                               (unsigned)sos_cp !! 164                               (unsigned)sos_cpu_context_get_EX_info(ctxt));
153       SOS_ASSERT_FATAL(! "Got page fault (note    165       SOS_ASSERT_FATAL(! "Got page fault (note: demand paging is disabled)");
154     }                                             166     }
155                                                   167 
156                                                   168 
157   /*                                              169   /*
158    * Demand paging                             !! 170    * Demand paging in kernel space
159    */                                             171    */
160                                                   172  
161   /* Update the number of demand paging reques    173   /* Update the number of demand paging requests handled */
162   demand_paging_count ++;                         174   demand_paging_count ++;
163   display_bits(0, 0,                              175   display_bits(0, 0,
164                SOS_X86_VIDEO_FG_LTRED | SOS_X8    176                SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
165                demand_paging_count);              177                demand_paging_count);
166                                                   178 
167   /* Allocate a new page for the virtual addre    179   /* Allocate a new page for the virtual address */
168   ppage_paddr = sos_physmem_ref_physpage_new(F    180   ppage_paddr = sos_physmem_ref_physpage_new(FALSE);
169   if (! ppage_paddr)                              181   if (! ppage_paddr)
170     SOS_ASSERT_FATAL(! "TODO: implement swap.     182     SOS_ASSERT_FATAL(! "TODO: implement swap. (Out of mem in demand paging because no swap for kernel yet !)");
171   SOS_ASSERT_FATAL(SOS_OK == sos_paging_map(pp    183   SOS_ASSERT_FATAL(SOS_OK == sos_paging_map(ppage_paddr,
172                                             SO    184                                             SOS_PAGE_ALIGN_INF(faulting_vaddr),
173                                             FA    185                                             FALSE,
174                                             SO    186                                             SOS_VM_MAP_PROT_READ
175                                             |     187                                             | SOS_VM_MAP_PROT_WRITE
176                                             |     188                                             | SOS_VM_MAP_ATOMIC));
177   sos_physmem_unref_physpage(ppage_paddr);        189   sos_physmem_unref_physpage(ppage_paddr);
178                                                   190 
179   /* Ok, we can now return to interrupted cont    191   /* Ok, we can now return to interrupted context */
180 }                                                 192 }
181                                                   193 
182                                                   194 
183                                                   195 
184 /* ===========================================    196 /* ======================================================================
185  * Demonstrate the use of the CPU kernet conte !! 197  * An operating system MUST always have a ready thread ! Otherwise:
186  *  - A coroutine prints "Hlowrd" and switches !! 198  * what would the CPU have to execute ?!
187  *    letter                                   << 
188  *  - A coroutine prints "el ol\n" and switche << 
189  *    each letter.                             << 
190  * The first to reach the '\n' returns back to << 
191  */                                               199  */
192 struct sos_cpu_kstate *ctxt_hello1;            !! 200 static void idle_thread(void* unused) __attribute__((noreturn));
193 struct sos_cpu_kstate *ctxt_hello2;            !! 201 static void idle_thread(void* unused)
194 struct sos_cpu_kstate *ctxt_main;              << 
195 sos_vaddr_t hello1_stack, hello2_stack;        << 
196                                                << 
197 static void reclaim_stack(sos_vaddr_t stack_va << 
198 {                                                 202 {
199   sos_kfree(stack_vaddr);                      !! 203   sos_ui32_t idle_twiddle = 0;
200 }                                              << 
201                                                << 
202                                                   204 
203 static void exit_hello12(sos_vaddr_t stack_vad !! 205   while (1)
204 {                                              << 
205   sos_cpu_kstate_exit_to(ctxt_main,            << 
206                          (sos_cpu_kstate_funct << 
207                          stack_vaddr);         << 
208 }                                              << 
209                                                << 
210                                                << 
211 static void hello1 (char *str)                 << 
212 {                                              << 
213   for ( ; *str != '\n' ; str++)                << 
214     {                                             206     {
215       sos_bochs_printf("hello1: %c\n", *str);  !! 207       /* Remove this instruction if you get an "Invalid opcode" CPU
216       sos_cpu_kstate_switch(& ctxt_hello1, ctx !! 208          exception (old 80386 CPU) */
217     }                                          !! 209       asm("hlt\n");
218                                                << 
219   /* You can uncomment this in case you explic << 
220      now. But returning from the function will << 
221   /* sos_cpu_kstate_exit_to(ctxt_main,         << 
222                          (sos_cpu_kstate_funct << 
223                          hello1_stack); */     << 
224 }                                              << 
225                                                << 
226                                                << 
227 static void hello2 (char *str)                 << 
228 {                                              << 
229   for ( ; *str != '\n' ; str++)                << 
230     {                                          << 
231       sos_bochs_printf("hello2: %c\n", *str);  << 
232       sos_cpu_kstate_switch(& ctxt_hello2, ctx << 
233     }                                          << 
234                                                << 
235   /* You can uncomment this in case you explic << 
236      now. But returning from the function will << 
237   /* sos_cpu_kstate_exit_to(ctxt_main,         << 
238                          (sos_cpu_kstate_funct << 
239                          hello2_stack); */     << 
240 }                                              << 
241                                                << 
242                                                << 
243 void print_hello_world ()                      << 
244 {                                              << 
245 #define DEMO_STACK_SIZE 1024                   << 
246   /* Allocate the stacks */                    << 
247   hello1_stack = sos_kmalloc(DEMO_STACK_SIZE,  << 
248   hello2_stack = sos_kmalloc(DEMO_STACK_SIZE,  << 
249                                                << 
250   /* Initialize the coroutines' contexts */    << 
251   sos_cpu_kstate_init(&ctxt_hello1,            << 
252                       (sos_cpu_kstate_function << 
253                       (sos_ui32_t) "Hlowrd",   << 
254                       (sos_vaddr_t) hello1_sta << 
255                       (sos_cpu_kstate_function << 
256                       (sos_ui32_t) hello1_stac << 
257   sos_cpu_kstate_init(&ctxt_hello2,            << 
258                       (sos_cpu_kstate_function << 
259                       (sos_ui32_t) "el ol\n",  << 
260                       (sos_vaddr_t) hello2_sta << 
261                       (sos_cpu_kstate_function << 
262                       (sos_ui32_t) hello2_stac << 
263                                                << 
264   /* Go to first coroutine */                  << 
265   sos_bochs_printf("Printing Hello World\\n... << 
266   sos_cpu_kstate_switch(& ctxt_main, ctxt_hell << 
267                                                << 
268   /* The first coroutine to reach the '\n' swi << 
269   sos_bochs_printf("Back in main !\n");        << 
270 }                                              << 
271                                                << 
272                                                << 
273 /* =========================================== << 
274  * Generate page faults on an unmapped but all << 
275  * region, which results in a series of physic << 
276  * faulted pages.                              << 
277  */                                            << 
278 static void test_demand_paging(int nb_alloc_vp << 
279 {                                              << 
280   int i;                                       << 
281   sos_vaddr_t base_vaddr;                      << 
282                                                << 
283   sos_x86_videomem_printf(10, 0,               << 
284                           SOS_X86_VIDEO_BG_BLU << 
285                           "Demand paging test  << 
286                           nb_alloc_vpages >> 8 << 
287                                                << 
288   /* Allocate virtual memory */                << 
289   base_vaddr = sos_kmem_vmm_alloc(nb_alloc_vpa << 
290                                                << 
291   SOS_ASSERT_FATAL(base_vaddr != (sos_vaddr_t) << 
292   sos_x86_videomem_printf(11, 0,               << 
293                           SOS_X86_VIDEO_BG_BLU << 
294                           "Allocated virtual r << 
295                           base_vaddr,          << 
296                           base_vaddr + nb_allo << 
297                                                   210 
298   /* Now use part of it in physical memory */  !! 211       idle_twiddle ++;
299   for (i = 0 ; (i < nb_alloc_ppages) && (i < n !! 212       display_bits(0, 0, SOS_X86_VIDEO_FG_GREEN | SOS_X86_VIDEO_BG_BLUE,
300     {                                          !! 213                    idle_twiddle);
301       /* Compute an address inside the range * !! 214       
302       sos_ui32_t *value, j;                    !! 215       /* Lend the CPU to some other thread */
303       sos_vaddr_t vaddr = base_vaddr;          !! 216       sos_thread_yield();
304       vaddr += (nb_alloc_vpages - (i + 1))*SOS << 
305       vaddr += 2345;                           << 
306                                                << 
307       sos_x86_videomem_printf(12, 0,           << 
308                               SOS_X86_VIDEO_BG << 
309                               "Writing %d at v << 
310                               i, vaddr);       << 
311                                                << 
312       /* Write at this address */              << 
313       value = (sos_ui32_t*)vaddr;              << 
314       *value = i;                              << 
315                                                << 
316       /* Yep ! A new page should normally have << 
317       sos_x86_videomem_printf(13, 0,           << 
318                               SOS_X86_VIDEO_BG << 
319                               "Value read at a << 
320                               vaddr, (unsigned << 
321     }                                             217     }
322                                                << 
323   SOS_ASSERT_FATAL(SOS_OK == sos_kmem_vmm_free << 
324   /* Yep ! A new page should normally have bee << 
325   sos_x86_videomem_printf(14, 0,               << 
326                           SOS_X86_VIDEO_BG_BLU << 
327                           "Done (area un-alloc << 
328 }                                                 218 }
329                                                   219 
330                                                   220 
331                                                << 
332 /* ===========================================    221 /* ======================================================================
333  * Shows how the backtrace stuff works         !! 222  * Kernel thread showing some CPU usage statistics on the console every 1s
334  */                                               223  */
335                                                !! 224 #define LOAD_DISPLAY_BASELINE  4
336 /* Recursive function. Print the backtrace fro !! 225 #define LOAD_DISPLAY_STARTROW 34
337 static void test_backtrace(int i, int magic, s !! 226 static void stat_thread(void * unused) __attribute__((noreturn));
338                            sos_size_t  stack_s !! 227 static void stat_thread(void * unused)
339 {                                              !! 228 {
340   if (i <= 0)                                  !! 229   while (1)
341     {                                          !! 230     {
342       /* The page fault exception handler will !! 231       sos_ui32_t flags;
343          this function, because address 0x42 i !! 232       sos_ui32_t load1, load5, load15;
344       *((char*)0x42) = 12;                     !! 233       char str1[11], str5[11], str15[11];
345                                                !! 234       struct sos_time t;
346       /* More direct variant: */               !! 235       t.sec = 1;
347       /* dump_backtrace(NULL, stack_bottom, st !! 236       t.nanosec = 0;
                                                   >> 237 
                                                   >> 238       sos_thread_sleep(& t);
                                                   >> 239 
                                                   >> 240       sos_disable_IRQs(flags);
                                                   >> 241 
                                                   >> 242       /* The IDLE task is EXcluded in the following computation */
                                                   >> 243       sos_load_get_sload(&load1, &load5, &load15);
                                                   >> 244       sos_load_to_string(str1, load1);
                                                   >> 245       sos_load_to_string(str5, load5);
                                                   >> 246       sos_load_to_string(str15, load15);
                                                   >> 247       sos_x86_videomem_printf(LOAD_DISPLAY_BASELINE+0, LOAD_DISPLAY_STARTROW,
                                                   >> 248                               SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 249                               "Kernel (- Idle): %s %s %s    ",
                                                   >> 250                               str1, str5, str15);
                                                   >> 251 
                                                   >> 252       sos_load_get_uload(&load1, &load5, &load15);
                                                   >> 253       sos_load_to_string(str1, load1);
                                                   >> 254       sos_load_to_string(str5, load5);
                                                   >> 255       sos_load_to_string(str15, load15);
                                                   >> 256       sos_x86_videomem_printf(LOAD_DISPLAY_BASELINE+1, LOAD_DISPLAY_STARTROW,
                                                   >> 257                               SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 258                               "User: %s %s %s        ",
                                                   >> 259                               str1, str5, str15);
                                                   >> 260 
                                                   >> 261       sos_load_get_uratio(&load1, &load5, &load15);
                                                   >> 262       sos_load_to_string(str1, load1);
                                                   >> 263       sos_load_to_string(str5, load5);
                                                   >> 264       sos_load_to_string(str15, load15);
                                                   >> 265       sos_x86_videomem_printf(LOAD_DISPLAY_BASELINE+2, LOAD_DISPLAY_STARTROW,
                                                   >> 266                               SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 267                               "User CPU %%: %s %s %s        ",
                                                   >> 268                               str1, str5, str15);
                                                   >> 269 
                                                   >> 270       /* The IDLE task is INcluded in the following computation */
                                                   >> 271       sos_load_get_sratio(&load1, &load5, &load15);
                                                   >> 272       sos_load_to_string(str1, load1);
                                                   >> 273       sos_load_to_string(str5, load5);
                                                   >> 274       sos_load_to_string(str15, load15);
                                                   >> 275       sos_x86_videomem_printf(LOAD_DISPLAY_BASELINE+3, LOAD_DISPLAY_STARTROW,
                                                   >> 276                               SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 277                               "Kernel CPU %% (+ Idle): %s %s %s    ",
                                                   >> 278                               str1, str5, str15);
                                                   >> 279       sos_restore_IRQs(flags);
348     }                                             280     }
349   else                                         << 
350     test_backtrace(i-1, magic, stack_bottom, s << 
351 }                                                 281 }
352                                                   282 
353                                                   283 
354 /* ===========================================    284 /* ======================================================================
355  * Parsing of Mathematical expressions         !! 285  * Start the "init" (userland) process
356  *                                             << 
357  * This is a recursive lexer/parser/evaluator  << 
358  * expressions. Supports both binary +/-* and  << 
359  * well as parentheses.                        << 
360  *                                             << 
361  * Terminal tokens (Lexer):                    << 
362  *  - Number: positive integer number          << 
363  *  - Variable: ascii name (regexp: [a-zA-Z]+) << 
364  *  - Operator: +*-/                           << 
365  *  - Opening/closing parentheses              << 
366  *                                             << 
367  * Grammar (Parser):                           << 
368  *  Expression ::= Term E'                     << 
369  *  Expr_lr    ::= + Term Expr_lr | - Term Exp << 
370  *  Term       ::= Factor Term_lr              << 
371  *  Term_lr    ::= * Factor Term_lr | / Factor << 
372  *  Factor     ::= - Factor | + Factor | Scala << 
373  *  Scalar     ::= Number | Variable           << 
374  *                                             << 
375  * Note. This is the left-recursive equivalent << 
376  *  Expression ::= Expression + Term | Express << 
377  *  Term       ::= Term * Factor | Term / Fact << 
378  *  factor     ::= - Factor | + Factor | Scala << 
379  *  Scalar     ::= Number | Variable           << 
380  *                                             << 
381  * The parsing is composed of a 3 stages pipel << 
382  *  - The reader: reads a string 1 character a << 
383  *    the control back to lexer after each cha << 
384  *    interest in using coroutines, because it << 
385  *    implicitely stored in the stack between  << 
386  *  - The lexer: consumes the characters from  << 
387  *    the terminal tokens, 1 token at a time,  << 
388  *    to the parser after each token. This fun << 
389  *    in using coroutines, because its state ( << 
390  *    implicitely stored in the stack between  << 
391  *  - The parser: consumes the tokens from the << 
392  *    syntax tree of the expression. There is  << 
393  *    interest in defining a coroutine devoted << 
394  *    do use one for that because this allows  << 
395  *    deeper stack. Actually, the parser is hi << 
396  *    the default 16kB stack of the sos_main() << 
397  *    enough. Here, we switch to a 64kB stack, << 
398  *    recursive functions. The Parser uses int << 
399  *    are defined and implemented as internal  << 
400  *    just for the sake of clarity, and is abs << 
401  *    the algorithm: one can transfer these fu << 
402  *    function without restriction.            << 
403  *                                             << 
404  * The evaluator is another recursive function << 
405  * parser's stack to evaluate the parsed expre << 
406  * values for the variables present in the exp << 
407  * parser function, this function defines and  << 
408  * which can be extracted from the main evalua << 
409  *                                             << 
410  * All these functions support a kind of "exce << 
411  * something goes wrong, control is transferre << 
412  * sos_main() context, without unrolling the r << 
413  * how exceptions basically work, but one shou << 
414  * a reference exceptions implementation. Real << 
415  * (such as that in the C++ language) call the << 
416  * objects allocated on the stack during the " << 
417  * upon exception handling, which complicates  << 
418  * don't have real Objects here (in the OOP se << 
419  * destructors), so we don't have to complicat << 
420  *                                             << 
421  * After this little coroutine demo, one shoul << 
422  * a low-level manual direct manipulation of s << 
423  * probably mess up the whole kernel to do wha << 
424  * resources such as mutex/semaphore won't be  << 
425  * ...). Higher level "kernel thread" primitiv << 
426  * presented, which provide a higher-level set << 
427  * contexts. You'll have to use EXCLUSIVELY th << 
428  * need a huge stack to do recursion for examp << 
429  * think of changing manually the stack for so << 
430  * rethink your algorithm, making it non-recur << 
431  */                                            << 
432                                                << 
433                                                << 
434 /* The stacks involved */                      << 
435 static char stack_reader[1024];                << 
436 static char stack_lexer[1024];                 << 
437 static char deep_stack[65536]; /* For the pars << 
438                                                << 
439 /* The CPU states for the various coroutines * << 
440 static struct sos_cpu_kstate *st_reader, *st_l << 
441   *st_eval, *st_free, *st_main;                << 
442                                                << 
443                                                << 
444 /*                                             << 
445  * Default exit/reclaim functions: return cont << 
446  * context                                     << 
447  */                                               286  */
448 static void reclaim(int unused)                !! 287 static sos_ret_t
                                                   >> 288 start_init(struct sos_fs_manager_instance * rootfs)
449 {                                                 289 {
450 }                                              !! 290   sos_ret_t retval;
451 static void func_exit(sos_ui32_t unused)       !! 291   struct sos_umem_vmm_as *as_init;
452 {                                              !! 292   struct sos_process *proc_init;
453   sos_cpu_kstate_exit_to(st_main, (sos_cpu_kst !! 293   struct sos_thread *new_thr;
454 }                                              !! 294   sos_uaddr_t ustack, start_uaddr;
                                                   >> 295   struct sos_fs_opened_file * init_root, * init_cwd, * unused_of;
455                                                   296 
                                                   >> 297   /* Create the new process */
                                                   >> 298   proc_init = sos_process_create("init", FALSE);
                                                   >> 299   if (! proc_init)
                                                   >> 300     return -SOS_ENOMEM;
                                                   >> 301   as_init = sos_process_get_address_space(proc_init);
456                                                   302 
457 /*                                             << 
458  * The reader coroutine and associated variabl << 
459  * have been a normal function, except that th << 
460  * character would have to be stored somewhere << 
461  */                                            << 
462 static char data_reader_to_lexer;              << 
463                                                   303 
464 static void func_reader(const char *str)       !! 304   /*
465 {                                              !! 305    * Setup the root and CWD directories of the process. The root of
466   for ( ; str && (*str != '\0') ; str++)       !! 306    * this process will correspond to the "global" root of the whole
                                                   >> 307    * system since all the future processes will duplicate it !
                                                   >> 308    */
                                                   >> 309   retval = sos_fs_new_opened_file(proc_init, rootfs->root,
                                                   >> 310                                   SOS_FS_OPEN_READ | SOS_FS_OPEN_WRITE,
                                                   >> 311                                   & init_root);
                                                   >> 312   if (SOS_OK != retval)
467     {                                             313     {
468       data_reader_to_lexer = *str;             !! 314       sos_process_unref(proc_init);
469       sos_cpu_kstate_switch(& st_reader, st_le !! 315       return -SOS_ENOENT;
470     }                                             316     }
471                                                   317 
472   data_reader_to_lexer = '\0';                 !! 318   /* Duplicate the root file to set the current working directory of
473   sos_cpu_kstate_switch(& st_reader, st_lexer) !! 319      the init process */
474 }                                              !! 320   retval = sos_fs_duplicate_opened_file(init_root, proc_init,
475                                                !! 321                                         & init_cwd);
476                                                !! 322   if (SOS_OK != retval)
477 /*                                             << 
478  * The Lexer coroutine and associated types/va << 
479  * could have been a normal function, except t << 
480  * character, token and previous token would h << 
481  * somewhere.                                  << 
482  */                                            << 
483 #define STR_VAR_MAXLEN 16                      << 
484 static struct lex_elem                         << 
485 {                                              << 
486   enum { LEX_IS_NUMBER, LEX_IS_OPER, LEX_IS_VA << 
487          LEX_IS_OPENPAR, LEX_IS_CLOSEPAR, LEX_ << 
488   union {                                      << 
489     int  number;                               << 
490     char operator;                             << 
491     char var[STR_VAR_MAXLEN];                  << 
492   };                                           << 
493 } data_lexer_to_parser;                        << 
494                                                << 
495 static void func_lexer(sos_ui32_t unused)      << 
496 {                                              << 
497   char c;                                      << 
498   enum { GOT_SPACE, GOT_NUM, GOT_OP, GOT_STR,  << 
499          GOT_OPENPAR, GOT_CLOSEPAR } got_what, << 
500                                                << 
501   data_lexer_to_parser.number = 0;             << 
502   got_what_before = GOT_SPACE;                 << 
503   do                                           << 
504     {                                             323     {
505       /* Consume one character from the reader !! 324       sos_fs_close(init_root);
506       sos_cpu_kstate_switch(& st_lexer, st_rea !! 325       sos_process_unref(proc_init);
507       c = data_reader_to_lexer;                !! 326       return -SOS_ENOENT;
508                                                << 
509       /* Classify the consumed character */    << 
510       if ( (c >= '0') && (c <= '9') )          << 
511         got_what = GOT_NUM;                    << 
512       else if ( (c == '+') || (c == '-') || (c << 
513         got_what = GOT_OP;                     << 
514       else if ( ( (c >= 'a') && (c <= 'z') )   << 
515                 || ( (c >= 'A') && (c <= 'Z')  << 
516         got_what = GOT_STR;                    << 
517       else if (c == '(')                       << 
518         got_what = GOT_OPENPAR;                << 
519       else if (c == ')')                       << 
520         got_what = GOT_CLOSEPAR;               << 
521       else                                     << 
522         got_what = GOT_SPACE;                  << 
523                                                << 
524       /* Determine whether the current token i << 
525       if ( (got_what != got_what_before)       << 
526            || (got_what_before == GOT_OP)      << 
527            || (got_what_before == GOT_OPENPAR) << 
528            || (got_what_before == GOT_CLOSEPAR << 
529         {                                      << 
530           /* return control back to the parser << 
531              has been recognized */            << 
532           if ( (got_what_before != GOT_SPACE)  << 
533             sos_cpu_kstate_switch(& st_lexer,  << 
534                                                << 
535           data_lexer_to_parser.number = 0;     << 
536         }                                      << 
537                                                << 
538       /* Update the token being currently reco << 
539       if (got_what == GOT_OP)                  << 
540         {                                      << 
541           data_lexer_to_parser.type = LEX_IS_O << 
542           data_lexer_to_parser.operator = c;   << 
543         }                                      << 
544       else if (got_what == GOT_NUM)            << 
545         {                                      << 
546           data_lexer_to_parser.type = LEX_IS_N << 
547           data_lexer_to_parser.number *= 10;   << 
548           data_lexer_to_parser.number += (c -  << 
549         }                                      << 
550       else if (got_what == GOT_STR)            << 
551         {                                      << 
552           char to_cat[] = { c, '\0' };         << 
553           data_lexer_to_parser.type = LEX_IS_V << 
554           strzcat(data_lexer_to_parser.var, to << 
555         }                                      << 
556       else if (got_what == GOT_OPENPAR)        << 
557         data_lexer_to_parser.type = LEX_IS_OPE << 
558       else if (got_what == GOT_CLOSEPAR)       << 
559         data_lexer_to_parser.type = LEX_IS_CLO << 
560                                                << 
561       got_what_before = got_what;              << 
562     }                                             327     }
563   while (c != '\0');                           << 
564                                                << 
565   /* Transfer last recognized token to the par << 
566   if ( (got_what_before != GOT_SPACE) )        << 
567     sos_cpu_kstate_switch(& st_lexer, st_parse << 
568                                                << 
569   /* Signal that no more token are available * << 
570   data_lexer_to_parser.type = LEX_END;         << 
571   sos_cpu_kstate_switch(& st_lexer, st_parser) << 
572                                                << 
573   /* Exception: parser asks for a token AFTER  << 
574      one */                                    << 
575   sos_bochs_printf("Error: end of string alrea << 
576   sos_cpu_kstate_switch(& st_lexer, st_main);  << 
577 }                                              << 
578                                                   328 
579                                                !! 329   /* Now update the process ! */
580 /*                                             !! 330   if ( ( SOS_OK != sos_process_chroot(proc_init, init_root, & unused_of) )
581  * The Parser coroutine and associated types/v !! 331        || ( SOS_OK != sos_process_chdir(proc_init, init_cwd, & unused_of) ) )
582  */                                            << 
583 struct syntax_node                             << 
584 {                                              << 
585   enum { YY_IS_BINOP, YY_IS_UNAROP, YY_IS_NUM, << 
586   union                                        << 
587   {                                            << 
588     int  number;                               << 
589     char var[STR_VAR_MAXLEN];                  << 
590     struct                                     << 
591     {                                          << 
592       char op;                                 << 
593       struct syntax_node *parm_left, *parm_rig << 
594     } binop;                                   << 
595     struct                                     << 
596     {                                             332     {
597       char op;                                 !! 333       sos_fs_close(init_root);
598       struct syntax_node *parm;                !! 334       sos_fs_close(init_cwd);
599     } unarop;                                  !! 335       sos_process_chroot(proc_init, NULL, & unused_of);
600   };                                           !! 336       sos_process_chdir(proc_init, NULL, & unused_of);
601 };                                             !! 337       sos_process_unref(proc_init);
602                                                !! 338       return -SOS_ENOENT;
603 static void func_parser(struct syntax_node **  << 
604 {                                              << 
605   static struct syntax_node *alloc_node_num(in << 
606   static struct syntax_node *alloc_node_var(co << 
607   static struct syntax_node *alloc_node_binop( << 
608                                                << 
609                                                << 
610   static struct syntax_node *alloc_node_unarop << 
611                                                << 
612   static struct syntax_node * get_expr();      << 
613   static struct syntax_node * get_expr_lr(stru << 
614   static struct syntax_node * get_term();      << 
615   static struct syntax_node * get_term_lr(stru << 
616   static struct syntax_node * get_factor();    << 
617   static struct syntax_node * get_scalar();    << 
618                                                << 
619   /* Create a new node to store a number */    << 
620   static struct syntax_node *alloc_node_num(in << 
621     {                                          << 
622       struct syntax_node *n                    << 
623         = (struct syntax_node*) sos_kmalloc(si << 
624       n->type   = YY_IS_NUM;                   << 
625       n->number = val;                         << 
626       return n;                                << 
627     }                                          << 
628   /* Create a new node to store a variable */  << 
629   static struct syntax_node *alloc_node_var(co << 
630     {                                          << 
631       struct syntax_node *n                    << 
632         = (struct syntax_node*) sos_kmalloc(si << 
633       n->type   = YY_IS_VAR;                   << 
634       strzcpy(n->var, name, STR_VAR_MAXLEN);   << 
635       return n;                                << 
636     }                                          << 
637   /* Create a new node to store a binary opera << 
638   static struct syntax_node *alloc_node_binop( << 
639                                                << 
640                                                << 
641     {                                          << 
642       struct syntax_node *n                    << 
643         = (struct syntax_node*) sos_kmalloc(si << 
644       n->type             = YY_IS_BINOP;       << 
645       n->binop.op         = op;                << 
646       n->binop.parm_left  = parm_left;         << 
647       n->binop.parm_right = parm_right;        << 
648       return n;                                << 
649     }                                          << 
650   /* Create a new node to store a unary operat << 
651   static struct syntax_node *alloc_node_unarop << 
652                                                << 
653     {                                          << 
654       struct syntax_node *n                    << 
655         = (struct syntax_node*) sos_kmalloc(si << 
656       n->type        = YY_IS_UNAROP;           << 
657       n->unarop.op   = op;                     << 
658       n->unarop.parm = parm;                   << 
659       return n;                                << 
660     }                                             339     }
661                                                   340 
662   /* Raise an exception: transfer control back << 
663      without unrolling the whole recursion */  << 
664   static void parser_exception(const char *str << 
665     {                                          << 
666       sos_bochs_printf("Parser exception: %s\n << 
667       sos_cpu_kstate_switch(& st_parser, st_ma << 
668     }                                          << 
669                                                   341 
670   /* Consume the current terminal "number" tok << 
671      token */                                  << 
672   static int get_number()                      << 
673     {                                          << 
674       int v;                                   << 
675       if (data_lexer_to_parser.type != LEX_IS_ << 
676         parser_exception("Expected number");   << 
677       v = data_lexer_to_parser.number;         << 
678       sos_cpu_kstate_switch(& st_parser, st_le << 
679       return v;                                << 
680     }                                          << 
681   /* Consume the current terminal "variable" t << 
682      token */                                  << 
683   static void get_str(char name[STR_VAR_MAXLEN << 
684     {                                          << 
685       if (data_lexer_to_parser.type != LEX_IS_ << 
686         parser_exception("Expected variable"); << 
687       strzcpy(name, data_lexer_to_parser.var,  << 
688       sos_cpu_kstate_switch(& st_parser, st_le << 
689     }                                          << 
690   /* Consume the current terminal "operator" t << 
691      token */                                  << 
692   static char get_op()                         << 
693     {                                          << 
694       char op;                                 << 
695       if (data_lexer_to_parser.type != LEX_IS_ << 
696         parser_exception("Expected operator"); << 
697       op = data_lexer_to_parser.operator;      << 
698       sos_cpu_kstate_switch(& st_parser, st_le << 
699       return op;                               << 
700     }                                          << 
701   /* Consume the current terminal "parenthese" << 
702      token */                                  << 
703   static void get_par()                        << 
704     {                                          << 
705       if ( (data_lexer_to_parser.type != LEX_I << 
706            && (data_lexer_to_parser.type != LE << 
707         parser_exception("Expected parenthese" << 
708       sos_cpu_kstate_switch(& st_parser, st_le << 
709     }                                          << 
710                                                   342 
711   /* Parse an Expression */                    !! 343   /* Map the 'init' program in user space */
712   static struct syntax_node * get_expr()       !! 344   start_uaddr = sos_binfmt_elf32_map(as_init, "init");
713     {                                          !! 345   if (0 == start_uaddr)
714       struct syntax_node *t = get_term();      << 
715       return get_expr_lr(t);                   << 
716     }                                          << 
717   /* Parse an Expr_lr */                       << 
718   static struct syntax_node * get_expr_lr(stru << 
719     {                                          << 
720       if ( (data_lexer_to_parser.type == LEX_I << 
721            && ( (data_lexer_to_parser.operator << 
722                 || (data_lexer_to_parser.opera << 
723         {                                      << 
724           char op = get_op();                  << 
725           struct syntax_node *term = get_term( << 
726           struct syntax_node *node_op = alloc_ << 
727           return get_expr_lr(node_op);         << 
728         }                                      << 
729       return n;                                << 
730     }                                          << 
731   /* Parse a Term */                           << 
732   static struct syntax_node * get_term()       << 
733     {                                          << 
734       struct syntax_node *f1 = get_factor();   << 
735       return get_term_lr(f1);                  << 
736     }                                          << 
737   /* Parse a Term_lr */                        << 
738   static struct syntax_node * get_term_lr(stru << 
739     {                                          << 
740       if ( (data_lexer_to_parser.type == LEX_I << 
741            && ( (data_lexer_to_parser.operator << 
742                 || (data_lexer_to_parser.opera << 
743         {                                      << 
744           char op = get_op();                  << 
745           struct syntax_node *factor = get_fac << 
746           struct syntax_node *node_op = alloc_ << 
747           return get_term_lr(node_op);         << 
748         }                                      << 
749       return n;                                << 
750     }                                          << 
751   /* Parse a Factor */                         << 
752   static struct syntax_node * get_factor()     << 
753     {                                          << 
754       if ( (data_lexer_to_parser.type == LEX_I << 
755            && ( (data_lexer_to_parser.operator << 
756                 || (data_lexer_to_parser.opera << 
757         { char op = data_lexer_to_parser.opera << 
758         get_op(); return alloc_node_unarop(op, << 
759       else if (data_lexer_to_parser.type == LE << 
760         {                                      << 
761           struct syntax_node *expr;            << 
762           get_par();                           << 
763           expr = get_expr();                   << 
764           if (data_lexer_to_parser.type != LEX << 
765             parser_exception("Mismatched paren << 
766           get_par();                           << 
767           return expr;                         << 
768         }                                      << 
769                                                << 
770       return get_scalar();                     << 
771     }                                          << 
772   /* Parse a Scalar */                         << 
773   static struct syntax_node * get_scalar()     << 
774     {                                             346     {
775       if (data_lexer_to_parser.type != LEX_IS_ !! 347       sos_process_unref(proc_init);
776         {                                      !! 348       return -SOS_ENOENT;
777           char var[STR_VAR_MAXLEN];            << 
778           get_str(var);                        << 
779           return alloc_node_var(var);          << 
780         }                                      << 
781       return alloc_node_num(get_number());     << 
782     }                                             349     }
783                                                   350 
784                                                !! 351   /* Allocate the user stack */
785   /*                                           !! 352   ustack = (SOS_PAGING_TOP_USER_ADDRESS - SOS_DEFAULT_USER_STACK_SIZE) + 1;
786    * Body of the function                      !! 353   retval = sos_dev_zero_map(as_init, &ustack, SOS_DEFAULT_USER_STACK_SIZE,
787    */                                          !! 354                             SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE,
788                                                !! 355                             /* PRIVATE */ 0);
789   /* Get the first token */                    !! 356   if (SOS_OK != retval)
790   sos_cpu_kstate_switch(& st_parser, st_lexer) << 
791                                                << 
792   /* Begin the parsing ! */                    << 
793   *syntax_tree = get_expr();                   << 
794   /* The result is returned in the syntax_tree << 
795 }                                              << 
796                                                << 
797                                                << 
798 /*                                             << 
799  * Setup the parser's pipeline                 << 
800  */                                            << 
801 static struct syntax_node * parse_expression(c << 
802 {                                              << 
803   struct syntax_node *retval = NULL;           << 
804                                                << 
805   /* Build the context of the functions in the << 
806   sos_cpu_kstate_init(& st_reader,             << 
807                       (sos_cpu_kstate_function << 
808                       (sos_ui32_t)expr,        << 
809                       (sos_vaddr_t)stack_reade << 
810                       (sos_cpu_kstate_function << 
811   sos_cpu_kstate_init(& st_lexer,              << 
812                       (sos_cpu_kstate_function << 
813                       0,                       << 
814                       (sos_vaddr_t)stack_lexer << 
815                       (sos_cpu_kstate_function << 
816   sos_cpu_kstate_init(& st_parser,             << 
817                       (sos_cpu_kstate_function << 
818                       (sos_ui32_t) /* syntax t << 
819                       (sos_vaddr_t)deep_stack, << 
820                       (sos_cpu_kstate_function << 
821                                                << 
822   /* Parse the expression */                   << 
823   sos_cpu_kstate_switch(& st_main, st_parser); << 
824   return retval;                               << 
825 }                                              << 
826                                                << 
827                                                << 
828 /*                                             << 
829  * The Evaluator coroutine and associated type << 
830  */                                            << 
831 struct func_eval_params                        << 
832 {                                              << 
833   const struct syntax_node *e;                 << 
834   const char **var_name;                       << 
835   int *var_val;                                << 
836   int nb_vars;                                 << 
837                                                << 
838   int result;                                  << 
839 };                                             << 
840                                                << 
841 static void func_eval(struct func_eval_params  << 
842 {                                              << 
843   /* The internal (recursive) nested function  << 
844      the syntax tree */                        << 
845   static int rec_eval(const struct syntax_node << 
846                       const char* var_name[],  << 
847     {                                             357     {
848       switch (n->type)                         !! 358       sos_process_unref(proc_init);
849         {                                      !! 359       return -SOS_ENOMEM;
850         case YY_IS_NUM:                        << 
851           return n->number;                    << 
852                                                << 
853         case YY_IS_VAR:                        << 
854           {                                    << 
855             int i;                             << 
856             for (i = 0 ; i < nb_vars ; i++)    << 
857               if (0 == strcmp(var_name[i], n-> << 
858                 return var_val[i];             << 
859                                                << 
860             /* Exception: no variable with tha << 
861             sos_bochs_printf("ERROR: unknown v << 
862             sos_cpu_kstate_switch(& st_eval, s << 
863           }                                    << 
864                                                << 
865         case YY_IS_BINOP:                      << 
866           {                                    << 
867             int left = rec_eval(n->binop.parm_ << 
868                                 var_name, var_ << 
869             int right = rec_eval(n->binop.parm << 
870                                  var_name, var << 
871             switch (n->binop.op)               << 
872               {                                << 
873               case '+': return left + right;   << 
874               case '-': return left - right;   << 
875               case '*': return left * right;   << 
876               case '/': return left / right;   << 
877               default:                         << 
878                 /* Exception: no such operator << 
879                 sos_bochs_printf("ERROR: unkno << 
880                 sos_cpu_kstate_switch(& st_eva << 
881               }                                << 
882           }                                    << 
883                                                << 
884         case YY_IS_UNAROP:                     << 
885           {                                    << 
886             int arg = rec_eval(n->unarop.parm, << 
887             switch (n->unarop.op)              << 
888               {                                << 
889               case '-': return -arg;           << 
890               case '+': return arg;            << 
891               default:                         << 
892                 /* Exception: no such operator << 
893                 sos_bochs_printf("ERROR: unkno << 
894                 sos_cpu_kstate_switch(& st_eva << 
895               }                                << 
896           }                                    << 
897         }                                      << 
898                                                << 
899       /* Exception: no such syntax node (INTER << 
900       sos_bochs_printf("ERROR: invalid node ty << 
901       sos_cpu_kstate_switch(& st_eval, st_main << 
902       return -1; /* let's make gcc happy */    << 
903     }                                             360     }
904                                                   361 
905                                                !! 362   /* Now create the user thread */
906   /*                                           !! 363   new_thr = sos_create_user_thread(NULL,
907    * Function BODY                             !! 364                                    proc_init,
908    */                                          !! 365                                    start_uaddr,
909   /* Update p.result returned back to calling  !! 366                                    0, 0,
910   parms->result                                !! 367                                    ustack + SOS_DEFAULT_USER_STACK_SIZE - 4,
911     = rec_eval(parms->e, parms->var_name, parm !! 368                                    SOS_SCHED_PRIO_TS_LOWEST);
912 }                                              !! 369   if (! new_thr)
913                                                << 
914 /*                                             << 
915  * Change the stack for something larger in or << 
916  * recursive function above in a safe way      << 
917  */                                            << 
918 static int eval_expression(const struct syntax << 
919                            const char* var_nam << 
920 {                                              << 
921   struct func_eval_params p                    << 
922     = (struct func_eval_params){ .e=e,         << 
923                                  .var_name=var << 
924                                  .var_val=var_ << 
925                                  .nb_vars=nb_v << 
926                                  .result = 0 } << 
927                                                << 
928   sos_cpu_kstate_init(& st_eval,               << 
929                       (sos_cpu_kstate_function << 
930                       (sos_ui32_t)/* p.result  << 
931                       (sos_vaddr_t)deep_stack, << 
932                       (sos_cpu_kstate_function << 
933                                                << 
934   /* Go ! */                                   << 
935   sos_cpu_kstate_switch(& st_main, st_eval);   << 
936   return p.result;                             << 
937 }                                              << 
938                                                << 
939                                                << 
940 /*                                             << 
941  * Function to free the syntax tree            << 
942  */                                            << 
943 static void func_free(struct syntax_node *n)   << 
944 {                                              << 
945   switch (n->type)                             << 
946     {                                             370     {
947     case YY_IS_NUM:                            !! 371       sos_process_unref(proc_init);
948     case YY_IS_VAR:                            !! 372       return -SOS_ENOMEM;
949       break;                                   << 
950                                                << 
951     case YY_IS_BINOP:                          << 
952       func_free(n->binop.parm_left);           << 
953       func_free(n->binop.parm_right);          << 
954       break;                                   << 
955                                                << 
956     case YY_IS_UNAROP:                         << 
957       func_free(n->unarop.parm);               << 
958       break;                                   << 
959     }                                             373     }
960                                                << 
961   sos_kfree((sos_vaddr_t)n);                   << 
962 }                                              << 
963                                                << 
964 /*                                             << 
965  * Change the stack for something larger in or << 
966  * recursive function above in a safe way      << 
967  */                                            << 
968 static void free_syntax_tree(struct syntax_nod << 
969 {                                              << 
970   sos_cpu_kstate_init(& st_free,               << 
971                       (sos_cpu_kstate_function << 
972                       (sos_ui32_t)tree,        << 
973                       (sos_vaddr_t)deep_stack, << 
974                       (sos_cpu_kstate_function << 
975                                                   374 
976   /* Go ! */                                   !! 375   sos_process_unref(proc_init);
977   sos_cpu_kstate_switch(& st_main, st_free);   !! 376   return SOS_OK;
978 }                                                 377 }
979                                                   378 
980                                                   379 
                                                   >> 380 
981 /* ===========================================    381 /* ======================================================================
982  * The C entry point of our operating system      382  * The C entry point of our operating system
983  */                                               383  */
984 void sos_main(unsigned long magic, unsigned lo !! 384 void sos_main(unsigned long magic, unsigned long arg)
                                                   >> 385      __attribute__((noreturn));
                                                   >> 386 void sos_main(unsigned long magic, unsigned long arg)
985 {                                                 387 {
986   unsigned i;                                  << 
987   sos_paddr_t sos_kernel_core_base_paddr, sos_    388   sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
988   struct syntax_node *syntax_tree;             !! 389   struct sos_time tick_resolution;
                                                   >> 390   struct sos_fs_manager_instance * rootfs;
989                                                   391 
990   /* Grub sends us a structure, called multibo !! 392   /* Size of RAM above 1MB. Might be undefined ! */
991      precious informations about the system, s !! 393   unsigned long int upper_mem = 0;
992      documentation for more information. */    << 
993   multiboot_info_t *mbi;                       << 
994   mbi = (multiboot_info_t *) addr;             << 
995                                                   394 
996   /* Setup bochs and console, and clear the co    395   /* Setup bochs and console, and clear the console */
997   sos_bochs_setup();                           !! 396   sos_bochs_subsystem_setup();
998                                                   397 
999   sos_x86_videomem_setup();                       398   sos_x86_videomem_setup();
1000   sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE)    399   sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
1001                                                  400 
1002   /* Greetings from SOS */                       401   /* Greetings from SOS */
1003   if (magic == MULTIBOOT_BOOTLOADER_MAGIC)       402   if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
1004     /* Loaded with Grub */                    !! 403     {
1005     sos_x86_videomem_printf(1, 0,             !! 404       /* Grub sends us a structure, called multiboot_info_t with a lot of
1006                             SOS_X86_VIDEO_FG_ !! 405          precious informations about the system, see the multiboot
1007                             "Welcome From GRU !! 406          documentation for more information. */
1008                             "SOS", ',',       !! 407       multiboot_info_t *mbi = (multiboot_info_t *) arg;
1009                             (unsigned)(mbi->m !! 408 
1010                             (unsigned)mbi->me !! 409       /* Multiboot says: "The value returned for upper memory is
                                                   >> 410          maximally the address of the first upper memory hole minus 1
                                                   >> 411          megabyte.". It also adds: "It is not guaranteed to be this
                                                   >> 412          value." aka "YMMV" ;) */
                                                   >> 413       upper_mem = mbi->mem_upper;
                                                   >> 414       sos_x86_videomem_printf(1, 0,
                                                   >> 415                               SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 416                               "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
                                                   >> 417                               "SOS article 9.5", ',',
                                                   >> 418                               (unsigned)(upper_mem >> 10) + 1,
                                                   >> 419                               (unsigned)upper_mem);
                                                   >> 420     }
                                                   >> 421   else if (magic == 0x42244224)
                                                   >> 422     {
                                                   >> 423       /* Loaded with SOS bootsect */
                                                   >> 424       upper_mem = arg;
                                                   >> 425       sos_x86_videomem_printf(1, 0,
                                                   >> 426                               SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 427                               "Welcome to %s%c RAM is %dMB (upper mem = 0x%x kB)",
                                                   >> 428                               "SOS article 9.5", ',',
                                                   >> 429                               (unsigned)(upper_mem >> 10) + 1,
                                                   >> 430                               (unsigned)upper_mem);
                                                   >> 431     }
1011   else                                           432   else
1012     /* Not loaded with grub */                !! 433     /* Not loaded with grub, not from an enhanced bootsect */
1013     sos_x86_videomem_printf(1, 0,                434     sos_x86_videomem_printf(1, 0,
1014                             SOS_X86_VIDEO_FG_    435                             SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
1015                             "Welcome to SOS") !! 436                             "Welcome to SOS article 9.5");
1016                                                  437 
1017   sos_bochs_putstring("Message in a bochs\n") !! 438   sos_bochs_putstring("Message in a bochs: This is SOS article 9.5.\n");
1018                                                  439 
1019   /* Setup CPU segmentation and IRQ subsystem    440   /* Setup CPU segmentation and IRQ subsystem */
1020   sos_gdt_subsystem_setup();                     441   sos_gdt_subsystem_setup();
1021   sos_idt_subsystem_setup();                     442   sos_idt_subsystem_setup();
1022                                                  443 
1023   /* Setup SOS IRQs and exceptions subsystem     444   /* Setup SOS IRQs and exceptions subsystem */
1024   sos_exception_subsystem_setup();               445   sos_exception_subsystem_setup();
1025   sos_irq_subsystem_setup();                     446   sos_irq_subsystem_setup();
1026                                                  447 
1027   /* Configure the timer so as to raise the I    448   /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */
1028   sos_i8254_set_frequency(100);                  449   sos_i8254_set_frequency(100);
1029                                                  450 
1030   /* We need a multiboot-compliant boot loade !! 451   /* Setup the kernel time subsystem to get prepared to take the timer
1031   if (magic != MULTIBOOT_BOOTLOADER_MAGIC)    !! 452      ticks into account */
                                                   >> 453   tick_resolution = (struct sos_time) { .sec=0, .nanosec=10000000UL };
                                                   >> 454   sos_time_subsysem_setup(& tick_resolution);
                                                   >> 455 
                                                   >> 456   /* We need to know the RAM size */
                                                   >> 457   if (upper_mem == 0)
1032     {                                            458     {
1033       sos_x86_videomem_putstring(20, 0,          459       sos_x86_videomem_putstring(20, 0,
1034                                  SOS_X86_VIDE    460                                  SOS_X86_VIDEO_FG_LTRED
1035                                    | SOS_X86_    461                                    | SOS_X86_VIDEO_BG_BLUE
1036                                    | SOS_X86_    462                                    | SOS_X86_VIDEO_FG_BLINKING,
1037                                  "I'm not loa !! 463                                  "I don't know RAM size ! Load me with Grub...");
1038       /* STOP ! */                               464       /* STOP ! */
1039       for (;;)                                   465       for (;;)
1040         continue;                                466         continue;
1041     }                                            467     }
1042                                                  468 
1043   /*                                             469   /*
1044    * Some interrupt handlers                     470    * Some interrupt handlers
1045    */                                            471    */
1046                                                  472 
1047   /* Binding some HW interrupts and exception    473   /* Binding some HW interrupts and exceptions to software routines */
1048   sos_irq_set_routine(SOS_IRQ_TIMER,             474   sos_irq_set_routine(SOS_IRQ_TIMER,
1049                       clk_it);                   475                       clk_it);
1050                                                  476 
1051   /*                                             477   /*
1052    * Setup physical memory management            478    * Setup physical memory management
1053    */                                            479    */
1054                                                  480 
1055   /* Multiboot says: "The value returned for  !! 481   SOS_ASSERT_FATAL(SOS_OK
1056      the address of the first upper memory ho !! 482                    == sos_physmem_subsystem_setup((upper_mem<<10) + (1<<20),
1057      also adds: "It is not guaranteed to be t !! 483                                                   &sos_kernel_core_base_paddr,
1058   sos_physmem_subsystem_setup((mbi->mem_upper !! 484                                                   &sos_kernel_core_top_paddr));
1059                               & sos_kernel_co << 
1060                               & sos_kernel_co << 
1061                                                  485   
1062   /*                                             486   /*
1063    * Switch to paged-memory mode                 487    * Switch to paged-memory mode
1064    */                                            488    */
1065                                                  489 
1066   /* Disabling interrupts should seem more co    490   /* Disabling interrupts should seem more correct, but it's not really
1067      necessary at this stage */                  491      necessary at this stage */
1068   SOS_ASSERT_FATAL(SOS_OK ==                     492   SOS_ASSERT_FATAL(SOS_OK ==
1069                    sos_paging_subsystem_setup    493                    sos_paging_subsystem_setup(sos_kernel_core_base_paddr,
1070                                                  494                                               sos_kernel_core_top_paddr));
1071                                                  495   
1072   /* Bind the page fault exception */            496   /* Bind the page fault exception */
1073   sos_exception_set_routine(SOS_EXCEPT_PAGE_F    497   sos_exception_set_routine(SOS_EXCEPT_PAGE_FAULT,
1074                             pgflt_ex);           498                             pgflt_ex);
1075                                                  499 
1076   /*                                             500   /*
1077    * Setup kernel virtual memory allocator       501    * Setup kernel virtual memory allocator
1078    */                                         !! 502    */
1079                                                  503 
1080   if (sos_kmem_vmm_subsystem_setup(sos_kernel    504   if (sos_kmem_vmm_subsystem_setup(sos_kernel_core_base_paddr,
1081                                    sos_kernel    505                                    sos_kernel_core_top_paddr,
1082                                    bootstrap_    506                                    bootstrap_stack_bottom,
1083                                    bootstrap_    507                                    bootstrap_stack_bottom
1084                                    + bootstra    508                                    + bootstrap_stack_size))
1085     sos_bochs_printf("Could not setup the Ker    509     sos_bochs_printf("Could not setup the Kernel virtual space allocator\n");
1086                                                  510 
1087   if (sos_kmalloc_subsystem_setup())             511   if (sos_kmalloc_subsystem_setup())
1088     sos_bochs_printf("Could not setup the Kma    512     sos_bochs_printf("Could not setup the Kmalloc subsystem\n");
1089                                                  513 
1090   /*                                             514   /*
1091    * Enabling the HW interrupts here, this wi !! 515    * Initialize the MMU context subsystem
1092    * interrupt call our clk_it handler        << 
1093    */                                            516    */
1094   asm volatile ("sti\n");                     !! 517   sos_mm_context_subsystem_setup();
1095                                                  518 
1096   /*                                             519   /*
1097    * Print hello world using coroutines       !! 520    * Initialize the CPU context subsystem
1098    */                                            521    */
1099   print_hello_world();                        !! 522   sos_cpu_context_subsystem_setup();
1100                                               << 
1101                                                  523 
1102   /*                                             524   /*
1103    * Run coroutine tests                      !! 525    * Bind the syscall handler to its software interrupt handler
1104    */                                            526    */
1105   sos_x86_videomem_printf(4, 0,               !! 527   sos_swintr_subsystem_setup();
1106                           SOS_X86_VIDEO_BG_BL << 
1107                           "Coroutine test");  << 
1108   sos_x86_videomem_printf(5, 0,               << 
1109                           SOS_X86_VIDEO_BG_BL << 
1110                           "Parsing...");      << 
1111   syntax_tree = parse_expression(" -  ( (69/  << 
1112                                                  528 
1113   if (syntax_tree != NULL)                    << 
1114     {                                         << 
1115       sos_x86_videomem_printf(6, 0,           << 
1116                               SOS_X86_VIDEO_B << 
1117                               "Evaluating..." << 
1118       sos_x86_videomem_printf(7, 0,           << 
1119                               SOS_X86_VIDEO_B << 
1120                               "Result=%d (if  << 
1121                               eval_expression << 
1122                                               << 
1123                                               << 
1124                                               << 
1125       free_syntax_tree(syntax_tree);          << 
1126       sos_x86_videomem_printf(8, 0,           << 
1127                               SOS_X86_VIDEO_B << 
1128                               "Done (un-alloc << 
1129     }                                         << 
1130   else                                        << 
1131     {                                         << 
1132       sos_x86_videomem_printf(6, 0,           << 
1133                               SOS_X86_VIDEO_B << 
1134                               "Error in parsi << 
1135     }                                         << 
1136                                                  529 
1137   /*                                             530   /*
1138    * Run some demand-paging tests             !! 531    * Initialize the Kernel thread and scheduler subsystems
1139    */                                            532    */
1140   test_demand_paging(234567, 500);            !! 533   
                                                   >> 534   /* Initialize kernel thread subsystem */
                                                   >> 535   sos_thread_subsystem_setup(bootstrap_stack_bottom,
                                                   >> 536                              bootstrap_stack_size);
                                                   >> 537 
                                                   >> 538   /* Initialize the scheduler */
                                                   >> 539   sos_sched_subsystem_setup();
                                                   >> 540 
                                                   >> 541   /* Declare the IDLE thread */
                                                   >> 542   SOS_ASSERT_FATAL(sos_create_kernel_thread("idle", idle_thread, NULL,
                                                   >> 543                                             SOS_SCHED_PRIO_TS_LOWEST) != NULL);
                                                   >> 544 
                                                   >> 545   /* Prepare the stats subsystem */
                                                   >> 546   sos_load_subsystem_setup();
                                                   >> 547 
                                                   >> 548   /* Declare a thread that prints some stats */
                                                   >> 549   SOS_ASSERT_FATAL(sos_create_kernel_thread("stat_thread", stat_thread,
                                                   >> 550                                             NULL,
                                                   >> 551                                             SOS_SCHED_PRIO_TS_LOWEST) != NULL);
1141                                                  552 
1142                                                  553 
1143   /*                                             554   /*
1144    * Create an un-resolved page fault, which  !! 555    * Initialise user address space management subsystem
1145    * handler print the backtrace.             << 
1146    */                                            556    */
1147   test_backtrace(6, 0xdeadbeef, bootstrap_sta !! 557   sos_umem_vmm_subsystem_setup();
                                                   >> 558   sos_dev_zero_subsystem_setup();
                                                   >> 559   
                                                   >> 560   /* Initialize the page and block cache subsystems */
                                                   >> 561   sos_fs_pagecache_subsystem_setup();
                                                   >> 562   sos_blockdev_subsystem_setup();
                                                   >> 563   sos_dev_mem_chardev_setup();
1148                                                  564 
1149   /*                                             565   /*
1150    * System should be halted BEFORE here !    !! 566    * Initialize process stuff
1151    */                                            567    */
                                                   >> 568   sos_process_subsystem_setup();
1152                                                  569 
1153                                                  570 
1154   /* An operatig system never ends */         !! 571   /* Enabling the HW interrupts here, this will make the timer HW
1155   for (;;)                                    !! 572      interrupt call the scheduler */
1156     {                                         !! 573   asm volatile ("sti\n");
1157       /* Remove this instruction if you get a << 
1158          exception (old 80386 CPU) */         << 
1159       asm("hlt\n");                           << 
1160                                                  574 
1161       continue;                               !! 575 
1162     }                                         !! 576   SOS_ASSERT_FATAL(SOS_OK == sos_fs_virtfs_subsystem_setup());
                                                   >> 577   SOS_ASSERT_FATAL(SOS_OK == sos_fs_subsystem_setup(NULL,
                                                   >> 578                                                     "virtfs",
                                                   >> 579                                                     NULL,
                                                   >> 580                                                     & rootfs));
                                                   >> 581 
                                                   >> 582 
                                                   >> 583   tty_subsystem_setup();
                                                   >> 584   sos_ttyS0_subsystem_setup();
                                                   >> 585   sos_console_subsystem_setup();
                                                   >> 586 
                                                   >> 587 
                                                   >> 588   sos_ide_subsystem_setup();
                                                   >> 589 
                                                   >> 590 
                                                   >> 591 
                                                   >> 592   /* Start the 'init' process, which in turns launches the other
                                                   >> 593      programs */
                                                   >> 594   start_init(rootfs);
                                                   >> 595   /*
                                                   >> 596    * We can safely exit from this function now, for there is already
                                                   >> 597    * an idle Kernel thread ready to make the CPU busy working...
                                                   >> 598    *
                                                   >> 599    * However, we must EXPLICITELY call sos_thread_exit() because a
                                                   >> 600    * simple "return" will return nowhere ! Actually this first thread
                                                   >> 601    * was initialized by the Grub bootstrap stage, at a time when the
                                                   >> 602    * word "thread" did not exist. This means that the stack was not
                                                   >> 603    * setup in order for a return here to call sos_thread_exit()
                                                   >> 604    * automagically. Hence we must call it manually. This is the ONLY
                                                   >> 605    * kernel thread where we must do this manually.
                                                   >> 606    */
                                                   >> 607   sos_bochs_printf("Bye from primary thread !\n");
                                                   >> 608   sos_thread_exit();
                                                   >> 609   SOS_FATAL_ERROR("No trespassing !");
1163 }                                                610 }
                                                      

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