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


001 /* Copyright (C) 2004  The SOS Team               001 /* Copyright (C) 2004  The SOS Team
002    Copyright (C) 1999  Free Software Foundatio    002    Copyright (C) 1999  Free Software Foundation, Inc.
003                                                   003 
004    This program is free software; you can redi    004    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU Genera    005    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundatio    006    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any lat    007    of the License, or (at your option) any later version.
008                                                   008    
009    This program is distributed in the hope tha    009    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the     010    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR    011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details    012    GNU General Public License for more details.
013                                                   013    
014    You should have received a copy of the GNU     014    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to t    015    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 3    016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA.                                           017    USA. 
018 */                                                018 */
019                                                   019 
020 /* Include definitions of the multiboot standa    020 /* Include definitions of the multiboot standard */
021 #include <bootstrap/multiboot.h>                  021 #include <bootstrap/multiboot.h>
022 #include <hwcore/idt.h>                           022 #include <hwcore/idt.h>
023 #include <hwcore/gdt.h>                           023 #include <hwcore/gdt.h>
024 #include <hwcore/irq.h>                           024 #include <hwcore/irq.h>
025 #include <hwcore/exception.h>                     025 #include <hwcore/exception.h>
026 #include <hwcore/i8254.h>                         026 #include <hwcore/i8254.h>
027 #include <sos/list.h>                             027 #include <sos/list.h>
028 #include <sos/physmem.h>                          028 #include <sos/physmem.h>
029 #include <hwcore/paging.h>                        029 #include <hwcore/paging.h>
030 #include <sos/kmem_vmm.h>                         030 #include <sos/kmem_vmm.h>
031 #include <sos/kmalloc.h>                          031 #include <sos/kmalloc.h>
032 #include <sos/klibc.h>                            032 #include <sos/klibc.h>
033 #include <sos/assert.h>                           033 #include <sos/assert.h>
034 #include <drivers/x86_videomem.h>                 034 #include <drivers/x86_videomem.h>
035 #include <drivers/bochs.h>                        035 #include <drivers/bochs.h>
036                                                   036 
037                                                   037 
038 /* Helper function to display each bits of a 3    038 /* Helper function to display each bits of a 32bits integer on the
039    screen as dark or light carrets */             039    screen as dark or light carrets */
040 static void display_bits(unsigned char row, un !! 040 void display_bits(unsigned char row, unsigned char col,
041                          unsigned char attribu !! 041                   unsigned char attribute,
042                          sos_ui32_t integer)   !! 042                   sos_ui32_t integer)
043 {                                                 043 {
044   int i;                                          044   int i;
045   /* Scan each bit of the integer, MSb first *    045   /* Scan each bit of the integer, MSb first */
046   for (i = 31 ; i >= 0 ; i--)                     046   for (i = 31 ; i >= 0 ; i--)
047     {                                             047     {
048       /* Test if bit i of 'integer' is set */     048       /* Test if bit i of 'integer' is set */
049       int bit_i = (integer & (1 << i));           049       int bit_i = (integer & (1 << i));
050       /* Ascii 219 => dark carret, Ascii 177 =    050       /* Ascii 219 => dark carret, Ascii 177 => light carret */
051       unsigned char ascii_code = bit_i?219:177    051       unsigned char ascii_code = bit_i?219:177;
052       sos_x86_videomem_putchar(row, col++,        052       sos_x86_videomem_putchar(row, col++,
053                                attribute,         053                                attribute,
054                                ascii_code);       054                                ascii_code);
055     }                                             055     }
056 }                                                 056 }
057                                                   057 
058                                                   058 
059 /* Clock IRQ handler */                           059 /* Clock IRQ handler */
060 static void clk_it(int intid)                  !! 060 static void clk_it(int intid,
                                                   >> 061                    const struct sos_cpu_kstate *cpu_kstate)
061 {                                                 062 {
062   static sos_ui32_t clock_count = 0;              063   static sos_ui32_t clock_count = 0;
063                                                   064 
064   display_bits(0, 48,                             065   display_bits(0, 48,
065                SOS_X86_VIDEO_FG_LTGREEN | SOS_    066                SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
066                clock_count);                      067                clock_count);
067   clock_count++;                                  068   clock_count++;
068                                                << 
069 }                                                 069 }
070 struct digit                                   !! 070 
                                                   >> 071 
                                                   >> 072 /* ======================================================================
                                                   >> 073  * Page fault exception handling
                                                   >> 074  */
                                                   >> 075 
                                                   >> 076 /* Helper function to dump a backtrace on bochs and/or the console */
                                                   >> 077 static void dump_backtrace(const struct sos_cpu_kstate *cpu_kstate,
                                                   >> 078                            sos_vaddr_t stack_bottom,
                                                   >> 079                            sos_size_t  stack_size,
                                                   >> 080                            sos_bool_t on_console,
                                                   >> 081                            sos_bool_t on_bochs)
071 {                                                 082 {
072   struct digit *prev, *next;                   !! 083   static void backtracer(sos_vaddr_t PC,
073   char value;                                  !! 084                          sos_vaddr_t params,
074 };                                             !! 085                          sos_ui32_t depth,
                                                   >> 086                          void *custom_arg)
                                                   >> 087     {
                                                   >> 088       sos_ui32_t invalid = 0xffffffff, *arg1, *arg2, *arg3, *arg4;
075                                                   089 
076 /* Representation of a big (positive) integer: !! 090       /* Get the address of the first 3 arguments from the
077    (MSD) is the HEAD of the list. Least Signif !! 091          frame. Among these arguments, 0, 1, 2, 3 arguments might be
078    TAIL of the list */                         !! 092          meaningful (depending on how many arguments the function may
079 typedef struct digit * big_number_t;           !! 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 arguments fit inside the
                                                   >> 100          stack boundaries */
                                                   >> 101 #define INTERVAL_OK(b,v,u) ( ((b) <= (sos_vaddr_t)(v)) \
                                                   >> 102                              && ((sos_vaddr_t)(v) < (u)) )
                                                   >> 103       if (!INTERVAL_OK(stack_bottom, arg1, stack_bottom + stack_size))
                                                   >> 104         arg1 = &invalid;
                                                   >> 105       if (!INTERVAL_OK(stack_bottom, arg2, stack_bottom + stack_size))
                                                   >> 106         arg2 = &invalid;
                                                   >> 107       if (!INTERVAL_OK(stack_bottom, arg3, stack_bottom + stack_size))
                                                   >> 108         arg3 = &invalid;
                                                   >> 109       if (!INTERVAL_OK(stack_bottom, arg4, stack_bottom + stack_size))
                                                   >> 110         arg4 = &invalid;
                                                   >> 111 
                                                   >> 112       /* Print the function context for this frame */
                                                   >> 113       if (on_bochs)
                                                   >> 114         sos_bochs_printf("[%d] PC=0x%x arg1=0x%x arg2=0x%x arg3=0x%x\n",
                                                   >> 115                          (unsigned)depth, (unsigned)PC,
                                                   >> 116                          (unsigned)*arg1, (unsigned)*arg2,
                                                   >> 117                          (unsigned)*arg3);
                                                   >> 118 
                                                   >> 119       if (on_console)
                                                   >> 120         sos_x86_videomem_printf(23-depth, 3,
                                                   >> 121                                 SOS_X86_VIDEO_BG_BLUE
                                                   >> 122                                   | SOS_X86_VIDEO_FG_LTGREEN,
                                                   >> 123                                 "[%d] PC=0x%x arg1=0x%x arg2=0x%x arg3=0x%x arg4=0x%x",
                                                   >> 124                                 (unsigned)depth, PC,
                                                   >> 125                                 (unsigned)*arg1, (unsigned)*arg2,
                                                   >> 126                                 (unsigned)*arg3, (unsigned)*arg4);
                                                   >> 127       
                                                   >> 128     }
                                                   >> 129 
                                                   >> 130   sos_backtrace(cpu_kstate, 15, stack_bottom, stack_size, backtracer, NULL);
                                                   >> 131 }
080                                                   132 
081                                                   133 
082 /* Add a new digit after the LSD */            !! 134 /* Page fault exception handler with demand paging for the kernel */
083 void bn_push_lsd(big_number_t * bn, char value !! 135 static void pgflt_ex(int intid, const struct sos_cpu_kstate *ctxt)
084 {                                                 136 {
085   struct digit *d;                             !! 137   static sos_ui32_t demand_paging_count = 0;
086   d = (struct digit*) sos_kmalloc(sizeof(struc !! 138   sos_vaddr_t faulting_vaddr = sos_cpu_kstate_get_EX_faulting_vaddr(ctxt);
087   SOS_ASSERT_FATAL(d != NULL);                 !! 139   sos_paddr_t ppage_paddr;
088   d->value = value;                            !! 140 
089   list_add_tail(*bn, d);                       !! 141   /* Check if address is covered by any VMM range */
                                                   >> 142   if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr))
                                                   >> 143     {
                                                   >> 144       /* No: The page fault is out of any kernel virtual region. For
                                                   >> 145          the moment, we don't handle this. */
                                                   >> 146       dump_backtrace(ctxt,
                                                   >> 147                      bootstrap_stack_bottom,
                                                   >> 148                      bootstrap_stack_size,
                                                   >> 149                      TRUE, TRUE);
                                                   >> 150       sos_display_fatal_error("Unresolved page Fault on access to address 0x%x (info=%x)!",
                                                   >> 151                               (unsigned)faulting_vaddr,
                                                   >> 152                               (unsigned)sos_cpu_kstate_get_EX_info(ctxt));
                                                   >> 153       SOS_ASSERT_FATAL(! "Got page fault (note: demand paging is disabled)");
                                                   >> 154     }
                                                   >> 155 
                                                   >> 156 
                                                   >> 157   /*
                                                   >> 158    * Demand paging
                                                   >> 159    */
                                                   >> 160  
                                                   >> 161   /* Update the number of demand paging requests handled */
                                                   >> 162   demand_paging_count ++;
                                                   >> 163   display_bits(0, 0,
                                                   >> 164                SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
                                                   >> 165                demand_paging_count);
                                                   >> 166 
                                                   >> 167   /* Allocate a new page for the virtual address */
                                                   >> 168   ppage_paddr = sos_physmem_ref_physpage_new(FALSE);
                                                   >> 169   if (! ppage_paddr)
                                                   >> 170     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(ppage_paddr,
                                                   >> 172                                             SOS_PAGE_ALIGN_INF(faulting_vaddr),
                                                   >> 173                                             FALSE,
                                                   >> 174                                             SOS_VM_MAP_PROT_READ
                                                   >> 175                                             | SOS_VM_MAP_PROT_WRITE
                                                   >> 176                                             | SOS_VM_MAP_ATOMIC));
                                                   >> 177   sos_physmem_unref_physpage(ppage_paddr);
                                                   >> 178 
                                                   >> 179   /* Ok, we can now return to interrupted context */
090 }                                                 180 }
091                                                   181 
092                                                   182 
093 /* Add a new digit before the MSD */           !! 183 
094 void bn_push_msd(big_number_t * bn, char value !! 184 /* ======================================================================
                                                   >> 185  * Demonstrate the use of the CPU kernet context management API:
                                                   >> 186  *  - A coroutine prints "Hlowrd" and switches to the other after each
                                                   >> 187  *    letter
                                                   >> 188  *  - A coroutine prints "el ol\n" and switches back to the other after
                                                   >> 189  *    each letter.
                                                   >> 190  * The first to reach the '\n' returns back to main.
                                                   >> 191  */
                                                   >> 192 struct sos_cpu_kstate *ctxt_hello1;
                                                   >> 193 struct sos_cpu_kstate *ctxt_hello2;
                                                   >> 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_vaddr)
095 {                                                 198 {
096   struct digit *d;                             !! 199   sos_kfree(stack_vaddr);
097   d = (struct digit*) sos_kmalloc(sizeof(struc << 
098   SOS_ASSERT_FATAL(d != NULL);                 << 
099   d->value = value;                            << 
100   list_add_head(*bn, d);                       << 
101 }                                                 200 }
102                                                   201 
103                                                   202 
104 /* Construct a big integer from a (machine) in !! 203 static void exit_hello12(sos_vaddr_t stack_vaddr)
105 big_number_t bn_new(unsigned long int i)       << 
106 {                                                 204 {
107   big_number_t retval;                         !! 205   sos_cpu_kstate_exit_to(ctxt_main,
                                                   >> 206                          (sos_cpu_kstate_function_arg1_t*) reclaim_stack,
                                                   >> 207                          stack_vaddr);
                                                   >> 208 }
108                                                   209 
109   list_init(retval);                           !! 210 
110   do                                           !! 211 static void hello1 (char *str)
                                                   >> 212 {
                                                   >> 213   for ( ; *str != '\n' ; str++)
111     {                                             214     {
112       bn_push_msd(&retval, i%10);              !! 215       sos_bochs_printf("hello1: %c\n", *str);
113       i /= 10;                                 !! 216       sos_cpu_kstate_switch(& ctxt_hello1, ctxt_hello2);
114     }                                             217     }
115   while (i != 0);                              << 
116                                                   218 
117   return retval;                               !! 219   /* You can uncomment this in case you explicitly want to exit
                                                   >> 220      now. But returning from the function will do the same */
                                                   >> 221   /* sos_cpu_kstate_exit_to(ctxt_main,
                                                   >> 222                          (sos_cpu_kstate_function_arg1_t*) reclaim_stack,
                                                   >> 223                          hello1_stack); */
118 }                                                 224 }
119                                                   225 
120                                                   226 
121 /* Create a new big integer from another big i !! 227 static void hello2 (char *str)
122 big_number_t bn_copy(const big_number_t bn)    << 
123 {                                                 228 {
124   big_number_t retval;                         !! 229   for ( ; *str != '\n' ; str++)
125   int nb_elts;                                 << 
126   struct digit *d;                             << 
127                                                << 
128   list_init(retval);                           << 
129   list_foreach(bn, d, nb_elts)                 << 
130     {                                             230     {
131       bn_push_lsd(&retval, d->value);          !! 231       sos_bochs_printf("hello2: %c\n", *str);
                                                   >> 232       sos_cpu_kstate_switch(& ctxt_hello2, ctxt_hello1);
132     }                                             233     }
133                                                   234 
134   return retval;                               !! 235   /* You can uncomment this in case you explicitly want to exit
                                                   >> 236      now. But returning from the function will do the same */
                                                   >> 237   /* sos_cpu_kstate_exit_to(ctxt_main,
                                                   >> 238                          (sos_cpu_kstate_function_arg1_t*) reclaim_stack,
                                                   >> 239                          hello2_stack); */
135 }                                                 240 }
136                                                   241 
137                                                   242 
138 /* Free the memory used by a big integer */    !! 243 void print_hello_world ()
139 void bn_del(big_number_t * bn)                 << 
140 {                                                 244 {
141   struct digit *d;                             !! 245 #define DEMO_STACK_SIZE 1024
                                                   >> 246   /* Allocate the stacks */
                                                   >> 247   hello1_stack = sos_kmalloc(DEMO_STACK_SIZE, 0);
                                                   >> 248   hello2_stack = sos_kmalloc(DEMO_STACK_SIZE, 0);
                                                   >> 249 
                                                   >> 250   /* Initialize the coroutines' contexts */
                                                   >> 251   sos_cpu_kstate_init(&ctxt_hello1,
                                                   >> 252                       (sos_cpu_kstate_function_arg1_t*) hello1,
                                                   >> 253                       (sos_ui32_t) "Hlowrd",
                                                   >> 254                       (sos_vaddr_t) hello1_stack, DEMO_STACK_SIZE,
                                                   >> 255                       (sos_cpu_kstate_function_arg1_t*) exit_hello12,
                                                   >> 256                       (sos_ui32_t) hello1_stack);
                                                   >> 257   sos_cpu_kstate_init(&ctxt_hello2,
                                                   >> 258                       (sos_cpu_kstate_function_arg1_t*) hello2,
                                                   >> 259                       (sos_ui32_t) "el ol\n",
                                                   >> 260                       (sos_vaddr_t) hello2_stack, DEMO_STACK_SIZE,
                                                   >> 261                       (sos_cpu_kstate_function_arg1_t*) exit_hello12,
                                                   >> 262                       (sos_ui32_t) hello2_stack);
                                                   >> 263 
                                                   >> 264   /* Go to first coroutine */
                                                   >> 265   sos_bochs_printf("Printing Hello World\\n...\n");
                                                   >> 266   sos_cpu_kstate_switch(& ctxt_main, ctxt_hello1);
142                                                   267 
143   list_collapse(*bn, d)                        !! 268   /* The first coroutine to reach the '\n' switched back to us */
144     {                                          !! 269   sos_bochs_printf("Back in main !\n");
145       sos_kfree((sos_vaddr_t)d);               << 
146     }                                          << 
147 }                                                 270 }
148                                                   271 
149                                                   272 
150 /* Shift left a big integer: bn := bn*10^shift !! 273 /* ======================================================================
151 void bn_shift(big_number_t *bn, int shift)     !! 274  * Generate page faults on an unmapped but allocated kernel virtual
                                                   >> 275  * region, which results in a series of physical memory mappings for the
                                                   >> 276  * faulted pages.
                                                   >> 277  */
                                                   >> 278 static void test_demand_paging(int nb_alloc_vpages, int nb_alloc_ppages)
152 {                                                 279 {
153   for ( ; shift > 0 ; shift --)                !! 280   int i;
                                                   >> 281   sos_vaddr_t base_vaddr;
                                                   >> 282 
                                                   >> 283   sos_x86_videomem_printf(10, 0,
                                                   >> 284                           SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_LTGREEN,
                                                   >> 285                           "Demand paging test (alloc %dMB of VMM, test %dkB RAM)",
                                                   >> 286                           nb_alloc_vpages >> 8, nb_alloc_ppages << 2);
                                                   >> 287   
                                                   >> 288   /* Allocate virtual memory */
                                                   >> 289   base_vaddr = sos_kmem_vmm_alloc(nb_alloc_vpages, 0);
                                                   >> 290 
                                                   >> 291   SOS_ASSERT_FATAL(base_vaddr != (sos_vaddr_t)NULL);
                                                   >> 292   sos_x86_videomem_printf(11, 0,
                                                   >> 293                           SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 294                           "Allocated virtual region [0x%x, 0x%x[",
                                                   >> 295                           base_vaddr,
                                                   >> 296                           base_vaddr + nb_alloc_vpages*SOS_PAGE_SIZE);
                                                   >> 297 
                                                   >> 298   /* Now use part of it in physical memory */
                                                   >> 299   for (i = 0 ; (i < nb_alloc_ppages) && (i < nb_alloc_vpages) ; i++)
154     {                                             300     {
155       bn_push_lsd(bn, 0);                      !! 301       /* Compute an address inside the range */
                                                   >> 302       sos_ui32_t *value, j;
                                                   >> 303       sos_vaddr_t vaddr = base_vaddr;
                                                   >> 304       vaddr += (nb_alloc_vpages - (i + 1))*SOS_PAGE_SIZE;
                                                   >> 305       vaddr += 2345;
                                                   >> 306 
                                                   >> 307       sos_x86_videomem_printf(12, 0,
                                                   >> 308                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 309                               "Writing %d at virtual address 0x%x...",
                                                   >> 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 been allocated for us */
                                                   >> 317       sos_x86_videomem_printf(13, 0,
                                                   >> 318                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 319                               "Value read at address 0x%x = %d",
                                                   >> 320                               vaddr, (unsigned)*value);
156     }                                             321     }
                                                   >> 322 
                                                   >> 323   SOS_ASSERT_FATAL(SOS_OK == sos_kmem_vmm_free(base_vaddr));
                                                   >> 324   /* Yep ! A new page should normally have been allocated for us */
                                                   >> 325   sos_x86_videomem_printf(14, 0,
                                                   >> 326                           SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 327                           "Done (area un-allocated)");
157 }                                                 328 }
158                                                   329 
159                                                   330 
160 /* Dump the big integer in bochs */            !! 331 
161 void bn_print_bochs(const big_number_t bn)     !! 332 /* ======================================================================
                                                   >> 333  * Shows how the backtrace stuff works
                                                   >> 334  */
                                                   >> 335 
                                                   >> 336 /* Recursive function. Print the backtrace from the innermost function */
                                                   >> 337 static void test_backtrace(int i, int magic, sos_vaddr_t stack_bottom,
                                                   >> 338                            sos_size_t  stack_size)
162 {                                                 339 {
163   int nb_elts;                                 !! 340   if (i <= 0)
164   const struct digit *d;                       !! 341     {
                                                   >> 342       /* The page fault exception handler will print the backtrace of
                                                   >> 343          this function, because address 0x42 is not mapped */
                                                   >> 344       *((char*)0x42) = 12;
165                                                   345 
166   if (list_is_empty(bn))                       !! 346       /* More direct variant: */
167     sos_bochs_printf("0");                     !! 347       /* dump_backtrace(NULL, stack_bottom, stack_size, TRUE, TRUE); */
                                                   >> 348     }
168   else                                            349   else
169     list_foreach(bn, d, nb_elts)               !! 350     test_backtrace(i-1, magic, stack_bottom, stack_size);
170       sos_bochs_printf("%d", d->value);        << 
171 }                                                 351 }
172                                                   352 
173 /* Dump the big integer on the console */      !! 353 
174 void bn_print_console(unsigned char row, unsig !! 354 /* ======================================================================
175                       unsigned char attribute, !! 355  * Parsing of Mathematical expressions
176                       const big_number_t bn,   !! 356  *
177                       int nb_decimals)         !! 357  * This is a recursive lexer/parser/evaluator for arithmetical
                                                   >> 358  * expressions. Supports both binary +/-* and unary +- operators, as
                                                   >> 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 Expr_lr | Nothing
                                                   >> 370  *  Term       ::= Factor Term_lr
                                                   >> 371  *  Term_lr    ::= * Factor Term_lr | / Factor Term_lr | Nothing
                                                   >> 372  *  Factor     ::= - Factor | + Factor | Scalar | ( Expression )
                                                   >> 373  *  Scalar     ::= Number | Variable
                                                   >> 374  *
                                                   >> 375  * Note. This is the left-recursive equivalent of the following basic grammar:
                                                   >> 376  *  Expression ::= Expression + Term | Expression - Term
                                                   >> 377  *  Term       ::= Term * Factor | Term / Factor
                                                   >> 378  *  factor     ::= - Factor | + Factor | Scalar | Variable | ( Expression )
                                                   >> 379  *  Scalar     ::= Number | Variable
                                                   >> 380  *
                                                   >> 381  * The parsing is composed of a 3 stages pipeline:
                                                   >> 382  *  - The reader: reads a string 1 character at a time, transferring
                                                   >> 383  *    the control back to lexer after each char. This function shows the
                                                   >> 384  *    interest in using coroutines, because its state (str) is
                                                   >> 385  *    implicitely stored in the stack between each iteration.
                                                   >> 386  *  - The lexer: consumes the characters from the reader and identifies
                                                   >> 387  *    the terminal tokens, 1 token at a time, transferring control back
                                                   >> 388  *    to the parser after each token. This function shows the interest
                                                   >> 389  *    in using coroutines, because its state (c and got_what_before) is
                                                   >> 390  *    implicitely stored in the stack between each iteration.
                                                   >> 391  *  - The parser: consumes the tokens from the lexer and builds the
                                                   >> 392  *    syntax tree of the expression. There is no real algorithmic
                                                   >> 393  *    interest in defining a coroutine devoted to do this. HOWEVER, we
                                                   >> 394  *    do use one for that because this allows us to switch to a much
                                                   >> 395  *    deeper stack. Actually, the parser is highly recursive, so that
                                                   >> 396  *    the default 16kB stack of the sos_main() function might not be
                                                   >> 397  *    enough. Here, we switch to a 64kB stack, which is safer for
                                                   >> 398  *    recursive functions. The Parser uses intermediary functions: these
                                                   >> 399  *    are defined and implemented as internal nested functions. This is
                                                   >> 400  *    just for the sake of clarity, and is absolutely not mandatory for
                                                   >> 401  *    the algorithm: one can transfer these functions out of the parser
                                                   >> 402  *    function without restriction.
                                                   >> 403  *
                                                   >> 404  * The evaluator is another recursive function that reuses the
                                                   >> 405  * parser's stack to evaluate the parsed expression with the given
                                                   >> 406  * values for the variables present in the expression. As for the
                                                   >> 407  * parser function, this function defines and uses a nested function,
                                                   >> 408  * which can be extracted from the main evaluation function at will.
                                                   >> 409  *
                                                   >> 410  * All these functions support a kind of "exception" feature: when
                                                   >> 411  * something goes wrong, control is transferred DIRECTLY back to the
                                                   >> 412  * sos_main() context, without unrolling the recursions. This shows
                                                   >> 413  * how exceptions basically work, but one should not consider this as
                                                   >> 414  * a reference exceptions implementation. Real exception mechanisms
                                                   >> 415  * (such as that in the C++ language) call the destructors to the
                                                   >> 416  * objects allocated on the stack during the "stack unwinding" process
                                                   >> 417  * upon exception handling, which complicates a lot the mechanism. We
                                                   >> 418  * don't have real Objects here (in the OOP sense, full-featured with
                                                   >> 419  * destructors), so we don't have to complicate things.
                                                   >> 420  *
                                                   >> 421  * After this little coroutine demo, one should forget all about such
                                                   >> 422  * a low-level manual direct manipulation of stacks. This would
                                                   >> 423  * probably mess up the whole kernel to do what we do here (locked
                                                   >> 424  * resources such as mutex/semaphore won't be correctly unlocked,
                                                   >> 425  * ...). Higher level "kernel thread" primitives will soon be
                                                   >> 426  * presented, which provide a higher-level set of APIs to manage CPU
                                                   >> 427  * contexts. You'll have to use EXCLUSIVELY those APIs. If you still
                                                   >> 428  * need a huge stack to do recursion for example, please don't even
                                                   >> 429  * think of changing manually the stack for something bigger ! Simply
                                                   >> 430  * rethink your algorithm, making it non-recursive.
                                                   >> 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 parser and the evaluator */
                                                   >> 438 
                                                   >> 439 /* The CPU states for the various coroutines */
                                                   >> 440 static struct sos_cpu_kstate *st_reader, *st_lexer, *st_parser,
                                                   >> 441   *st_eval, *st_free, *st_main;
                                                   >> 442 
                                                   >> 443 
                                                   >> 444 /*
                                                   >> 445  * Default exit/reclaim functions: return control to the "sos_main()"
                                                   >> 446  * context
                                                   >> 447  */
                                                   >> 448 static void reclaim(int unused)
178 {                                                 449 {
179   if (list_is_empty(bn))                       !! 450 }
180     sos_x86_videomem_printf(row, col, attribut !! 451 static void func_exit(sos_ui32_t unused)
181   else                                         !! 452 {
182     {                                          !! 453   sos_cpu_kstate_exit_to(st_main, (sos_cpu_kstate_function_arg1_t*)reclaim, 0);
183       int nb_elts;                             !! 454 }
184       const struct digit *d;                   << 
185       unsigned char x = col;                   << 
186                                                   455 
187       list_foreach(bn, d, nb_elts)             << 
188         {                                      << 
189           if (nb_elts == 0)                    << 
190             {                                  << 
191               sos_x86_videomem_printf(row, x,  << 
192               x += 2;                          << 
193             }                                  << 
194           else if (nb_elts < nb_decimals)      << 
195             {                                  << 
196               sos_x86_videomem_printf(row, x,  << 
197               x ++;                            << 
198             }                                  << 
199         }                                      << 
200                                                   456 
201       sos_x86_videomem_printf(row, x, attribut !! 457 /*
                                                   >> 458  * The reader coroutine and associated variable. This coroutine could
                                                   >> 459  * have been a normal function, except that the current parsed
                                                   >> 460  * character would have to be stored somewhere.
                                                   >> 461  */
                                                   >> 462 static char data_reader_to_lexer;
                                                   >> 463 
                                                   >> 464 static void func_reader(const char *str)
                                                   >> 465 {
                                                   >> 466   for ( ; str && (*str != '\0') ; str++)
                                                   >> 467     {
                                                   >> 468       data_reader_to_lexer = *str;
                                                   >> 469       sos_cpu_kstate_switch(& st_reader, st_lexer);
202     }                                             470     }
                                                   >> 471 
                                                   >> 472   data_reader_to_lexer = '\0';
                                                   >> 473   sos_cpu_kstate_switch(& st_reader, st_lexer);
203 }                                                 474 }
204                                                   475 
205                                                   476 
206 /* Result is the addition of 2 big integers */ !! 477 /*
207 big_number_t bn_add (const big_number_t bn1, c !! 478  * The Lexer coroutine and associated types/variables. This coroutine
                                                   >> 479  * could have been a normal function, except that the current parsed
                                                   >> 480  * character, token and previous token would have to be stored
                                                   >> 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_VAR,
                                                   >> 487          LEX_IS_OPENPAR, LEX_IS_CLOSEPAR, LEX_END } type;
                                                   >> 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)
208 {                                                 496 {
209   big_number_t retval;                         !! 497   char c;
210   const struct digit *d1, *d2;                 !! 498   enum { GOT_SPACE, GOT_NUM, GOT_OP, GOT_STR,
211   sos_bool_t  bn1_end = FALSE, bn2_end = FALSE !! 499          GOT_OPENPAR, GOT_CLOSEPAR } got_what, got_what_before;
212   char carry = 0;                              << 
213                                                   500 
214   list_init(retval);                           !! 501   data_lexer_to_parser.number = 0;
215   d1 = list_get_tail(bn1);                     !! 502   got_what_before = GOT_SPACE;
216   bn1_end = list_is_empty(bn1);                << 
217   d2 = list_get_tail(bn2);                     << 
218   bn2_end = list_is_empty(bn2);                << 
219   do                                              503   do
220     {                                             504     {
221       if (! bn1_end)                           !! 505       /* Consume one character from the reader */
222         carry += d1->value;                    !! 506       sos_cpu_kstate_switch(& st_lexer, st_reader);
223       if (! bn2_end)                           !! 507       c = data_reader_to_lexer;
224         carry += d2->value;                    !! 508 
225                                                !! 509       /* Classify the consumed character */
226       bn_push_msd(&retval, carry % 10);        !! 510       if ( (c >= '0') && (c <= '9') )
227       carry  /= 10;                            !! 511         got_what = GOT_NUM;
228                                                !! 512       else if ( (c == '+') || (c == '-') || (c == '*') || (c == '/') )
229       if (! bn1_end)                           !! 513         got_what = GOT_OP;
230         d1 = d1->prev;                         !! 514       else if ( ( (c >= 'a') && (c <= 'z') )
231       if (! bn2_end)                           !! 515                 || ( (c >= 'A') && (c <= 'Z') ) )
232         d2 = d2->prev;                         !! 516         got_what = GOT_STR;
233       if (d1 == list_get_tail(bn1))            !! 517       else if (c == '(')
234         bn1_end = TRUE;                        !! 518         got_what = GOT_OPENPAR;
235       if (d2 == list_get_tail(bn2))            !! 519       else if (c == ')')
236         bn2_end = TRUE;                        !! 520         got_what = GOT_CLOSEPAR;
237     }                                          !! 521       else
238   while (!bn1_end || !bn2_end);                !! 522         got_what = GOT_SPACE;
                                                   >> 523 
                                                   >> 524       /* Determine whether the current token is ended */
                                                   >> 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 if the previous token
                                                   >> 531              has been recognized */
                                                   >> 532           if ( (got_what_before != GOT_SPACE) )
                                                   >> 533             sos_cpu_kstate_switch(& st_lexer, st_parser);
239                                                   534 
240   if (carry > 0)                               !! 535           data_lexer_to_parser.number = 0;
241     {                                          !! 536         }
242       bn_push_msd(&retval, carry);             !! 537 
                                                   >> 538       /* Update the token being currently recognized */
                                                   >> 539       if (got_what == GOT_OP)
                                                   >> 540         {
                                                   >> 541           data_lexer_to_parser.type = LEX_IS_OPER;
                                                   >> 542           data_lexer_to_parser.operator = c;
                                                   >> 543         }
                                                   >> 544       else if (got_what == GOT_NUM)
                                                   >> 545         {
                                                   >> 546           data_lexer_to_parser.type = LEX_IS_NUMBER;
                                                   >> 547           data_lexer_to_parser.number *= 10;
                                                   >> 548           data_lexer_to_parser.number += (c - '0');
                                                   >> 549         }
                                                   >> 550       else if (got_what == GOT_STR)
                                                   >> 551         {
                                                   >> 552           char to_cat[] = { c, '\0' };
                                                   >> 553           data_lexer_to_parser.type = LEX_IS_VAR;
                                                   >> 554           strzcat(data_lexer_to_parser.var, to_cat, STR_VAR_MAXLEN);
                                                   >> 555         }
                                                   >> 556       else if (got_what == GOT_OPENPAR)
                                                   >> 557         data_lexer_to_parser.type = LEX_IS_OPENPAR;
                                                   >> 558       else if (got_what == GOT_CLOSEPAR)
                                                   >> 559         data_lexer_to_parser.type = LEX_IS_CLOSEPAR;
                                                   >> 560 
                                                   >> 561       got_what_before = got_what;
243     }                                             562     }
                                                   >> 563   while (c != '\0');
244                                                   564 
245   return retval;                               !! 565   /* Transfer last recognized token to the parser */
                                                   >> 566   if ( (got_what_before != GOT_SPACE) )
                                                   >> 567     sos_cpu_kstate_switch(& st_lexer, st_parser);
                                                   >> 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 having received the last
                                                   >> 574      one */
                                                   >> 575   sos_bochs_printf("Error: end of string already reached !\n");
                                                   >> 576   sos_cpu_kstate_switch(& st_lexer, st_main);
246 }                                                 577 }
247                                                   578 
248                                                   579 
249 /* Result is the multiplication of a big integ !! 580 /*
250 big_number_t bn_muli (const big_number_t bn, c !! 581  * The Parser coroutine and associated types/variables
                                                   >> 582  */
                                                   >> 583 struct syntax_node
251 {                                                 584 {
252   big_number_t retval;                         !! 585   enum { YY_IS_BINOP, YY_IS_UNAROP, YY_IS_NUM, YY_IS_VAR } type;
253   int nb_elts;                                 !! 586   union
254   char   carry = 0;                            !! 587   {
255   const struct digit *d;                       !! 588     int  number;
                                                   >> 589     char var[STR_VAR_MAXLEN];
                                                   >> 590     struct
                                                   >> 591     {
                                                   >> 592       char op;
                                                   >> 593       struct syntax_node *parm_left, *parm_right;
                                                   >> 594     } binop;
                                                   >> 595     struct
                                                   >> 596     {
                                                   >> 597       char op;
                                                   >> 598       struct syntax_node *parm;
                                                   >> 599     } unarop;
                                                   >> 600   };
                                                   >> 601 };
256                                                   602 
257   list_init(retval);                           !! 603 static void func_parser(struct syntax_node ** syntax_tree)
258   list_foreach_backward(bn, d, nb_elts)        !! 604 {
                                                   >> 605   static struct syntax_node *alloc_node_num(int val);
                                                   >> 606   static struct syntax_node *alloc_node_var(const char * name);
                                                   >> 607   static struct syntax_node *alloc_node_binop(char op,
                                                   >> 608                                               struct syntax_node *parm_left,
                                                   >> 609                                               struct syntax_node *parm_right);
                                                   >> 610   static struct syntax_node *alloc_node_unarop(char op,
                                                   >> 611                                                struct syntax_node *parm);
                                                   >> 612   static struct syntax_node * get_expr();
                                                   >> 613   static struct syntax_node * get_expr_lr(struct syntax_node *n);
                                                   >> 614   static struct syntax_node * get_term();
                                                   >> 615   static struct syntax_node * get_term_lr(struct syntax_node *n);
                                                   >> 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(int val)
                                                   >> 621     {
                                                   >> 622       struct syntax_node *n
                                                   >> 623         = (struct syntax_node*) sos_kmalloc(sizeof(struct syntax_node), 0);
                                                   >> 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(const char * name)
                                                   >> 630     {
                                                   >> 631       struct syntax_node *n
                                                   >> 632         = (struct syntax_node*) sos_kmalloc(sizeof(struct syntax_node), 0);
                                                   >> 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 operator */
                                                   >> 638   static struct syntax_node *alloc_node_binop(char op,
                                                   >> 639                                               struct syntax_node *parm_left,
                                                   >> 640                                               struct syntax_node *parm_right)
259     {                                             641     {
260       carry += d->value * digit;               !! 642       struct syntax_node *n
261       bn_push_msd(&retval, carry % 10);        !! 643         = (struct syntax_node*) sos_kmalloc(sizeof(struct syntax_node), 0);
262       carry /= 10;                             !! 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 operator */
                                                   >> 651   static struct syntax_node *alloc_node_unarop(char op,
                                                   >> 652                                                struct syntax_node *parm)
                                                   >> 653     {
                                                   >> 654       struct syntax_node *n
                                                   >> 655         = (struct syntax_node*) sos_kmalloc(sizeof(struct syntax_node), 0);
                                                   >> 656       n->type        = YY_IS_UNAROP;
                                                   >> 657       n->unarop.op   = op;
                                                   >> 658       n->unarop.parm = parm;
                                                   >> 659       return n;
263     }                                             660     }
264                                                   661 
265   if (carry > 0)                               !! 662   /* Raise an exception: transfer control back to main context,
                                                   >> 663      without unrolling the whole recursion */
                                                   >> 664   static void parser_exception(const char *str)
266     {                                             665     {
267       bn_push_msd(&retval, carry);             !! 666       sos_bochs_printf("Parser exception: %s\n", str);
                                                   >> 667       sos_cpu_kstate_switch(& st_parser, st_main);
268     }                                             668     }
269                                                   669 
270   return retval;                               !! 670   /* Consume the current terminal "number" token and ask for a new
                                                   >> 671      token */
                                                   >> 672   static int get_number()
                                                   >> 673     {
                                                   >> 674       int v;
                                                   >> 675       if (data_lexer_to_parser.type != LEX_IS_NUMBER)
                                                   >> 676         parser_exception("Expected number");
                                                   >> 677       v = data_lexer_to_parser.number;
                                                   >> 678       sos_cpu_kstate_switch(& st_parser, st_lexer);
                                                   >> 679       return v;
                                                   >> 680     }
                                                   >> 681   /* Consume the current terminal "variable" token and ask for a new
                                                   >> 682      token */
                                                   >> 683   static void get_str(char name[STR_VAR_MAXLEN])
                                                   >> 684     {
                                                   >> 685       if (data_lexer_to_parser.type != LEX_IS_VAR)
                                                   >> 686         parser_exception("Expected variable");
                                                   >> 687       strzcpy(name, data_lexer_to_parser.var, STR_VAR_MAXLEN);
                                                   >> 688       sos_cpu_kstate_switch(& st_parser, st_lexer);
                                                   >> 689     }
                                                   >> 690   /* Consume the current terminal "operator" token and ask for a new
                                                   >> 691      token */
                                                   >> 692   static char get_op()
                                                   >> 693     {
                                                   >> 694       char op;
                                                   >> 695       if (data_lexer_to_parser.type != LEX_IS_OPER)
                                                   >> 696         parser_exception("Expected operator");
                                                   >> 697       op = data_lexer_to_parser.operator;
                                                   >> 698       sos_cpu_kstate_switch(& st_parser, st_lexer);
                                                   >> 699       return op;
                                                   >> 700     }
                                                   >> 701   /* Consume the current terminal "parenthese" token and ask for a new
                                                   >> 702      token */
                                                   >> 703   static void get_par()
                                                   >> 704     {
                                                   >> 705       if ( (data_lexer_to_parser.type != LEX_IS_OPENPAR)
                                                   >> 706            && (data_lexer_to_parser.type != LEX_IS_CLOSEPAR) )
                                                   >> 707         parser_exception("Expected parenthese");
                                                   >> 708       sos_cpu_kstate_switch(& st_parser, st_lexer);
                                                   >> 709     }
                                                   >> 710 
                                                   >> 711   /* Parse an Expression */
                                                   >> 712   static struct syntax_node * get_expr()
                                                   >> 713     {
                                                   >> 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(struct syntax_node *n)
                                                   >> 719     {
                                                   >> 720       if ( (data_lexer_to_parser.type == LEX_IS_OPER)
                                                   >> 721            && ( (data_lexer_to_parser.operator == '+')
                                                   >> 722                 || (data_lexer_to_parser.operator == '-') ) )
                                                   >> 723         {
                                                   >> 724           char op = get_op();
                                                   >> 725           struct syntax_node *term = get_term();
                                                   >> 726           struct syntax_node *node_op = alloc_node_binop(op, n, term);
                                                   >> 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(struct syntax_node *n)
                                                   >> 739     {
                                                   >> 740       if ( (data_lexer_to_parser.type == LEX_IS_OPER)
                                                   >> 741            && ( (data_lexer_to_parser.operator == '*')
                                                   >> 742                 || (data_lexer_to_parser.operator == '/') ) )
                                                   >> 743         {
                                                   >> 744           char op = get_op();
                                                   >> 745           struct syntax_node *factor = get_factor();
                                                   >> 746           struct syntax_node *node_op = alloc_node_binop(op, n, factor);
                                                   >> 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_IS_OPER)
                                                   >> 755            && ( (data_lexer_to_parser.operator == '-')
                                                   >> 756                 || (data_lexer_to_parser.operator == '+') ) )
                                                   >> 757         { char op = data_lexer_to_parser.operator;
                                                   >> 758         get_op(); return alloc_node_unarop(op, get_factor()); }
                                                   >> 759       else if (data_lexer_to_parser.type == LEX_IS_OPENPAR)
                                                   >> 760         {
                                                   >> 761           struct syntax_node *expr;
                                                   >> 762           get_par();
                                                   >> 763           expr = get_expr();
                                                   >> 764           if (data_lexer_to_parser.type != LEX_IS_CLOSEPAR)
                                                   >> 765             parser_exception("Mismatched parentheses");
                                                   >> 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     {
                                                   >> 775       if (data_lexer_to_parser.type != LEX_IS_NUMBER)
                                                   >> 776         {
                                                   >> 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     }
                                                   >> 783 
                                                   >> 784 
                                                   >> 785   /*
                                                   >> 786    * Body of the function
                                                   >> 787    */
                                                   >> 788 
                                                   >> 789   /* Get the first token */
                                                   >> 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 parameter */
271 }                                                 795 }
272                                                   796 
273                                                   797 
274 /* Result is the multiplication of 2 big integ !! 798 /*
275 big_number_t bn_mult(const big_number_t bn1, c !! 799  * Setup the parser's pipeline
                                                   >> 800  */
                                                   >> 801 static struct syntax_node * parse_expression(const char *expr)
276 {                                                 802 {
277   int shift = 0;                               !! 803   struct syntax_node *retval = NULL;
278   big_number_t retval;                         << 
279   int nb_elts;                                 << 
280   struct digit *d;                             << 
281                                                << 
282   list_init(retval);                           << 
283   list_foreach_backward(bn2, d, nb_elts)       << 
284     {                                          << 
285       big_number_t retmult = bn_muli(bn1, d->v << 
286       big_number_t old_retval = retval;        << 
287       bn_shift(& retmult, shift);              << 
288       retval = bn_add(old_retval, retmult);    << 
289       bn_del(& retmult);                       << 
290       bn_del(& old_retval);                    << 
291       shift ++;                                << 
292     }                                          << 
293                                                   804 
                                                   >> 805   /* Build the context of the functions in the pipeline */
                                                   >> 806   sos_cpu_kstate_init(& st_reader,
                                                   >> 807                       (sos_cpu_kstate_function_arg1_t*)func_reader,
                                                   >> 808                       (sos_ui32_t)expr,
                                                   >> 809                       (sos_vaddr_t)stack_reader, sizeof(stack_reader),
                                                   >> 810                       (sos_cpu_kstate_function_arg1_t*)func_exit, 0);
                                                   >> 811   sos_cpu_kstate_init(& st_lexer,
                                                   >> 812                       (sos_cpu_kstate_function_arg1_t*)func_lexer,
                                                   >> 813                       0,
                                                   >> 814                       (sos_vaddr_t)stack_lexer, sizeof(stack_lexer),
                                                   >> 815                       (sos_cpu_kstate_function_arg1_t*)func_exit, 0);
                                                   >> 816   sos_cpu_kstate_init(& st_parser,
                                                   >> 817                       (sos_cpu_kstate_function_arg1_t*)func_parser,
                                                   >> 818                       (sos_ui32_t) /* syntax tree ! */&retval,
                                                   >> 819                       (sos_vaddr_t)deep_stack, sizeof(deep_stack),
                                                   >> 820                       (sos_cpu_kstate_function_arg1_t*)func_exit, 0);
                                                   >> 821 
                                                   >> 822   /* Parse the expression */
                                                   >> 823   sos_cpu_kstate_switch(& st_main, st_parser);
294   return retval;                                  824   return retval;
295 }                                                 825 }
296                                                   826 
297                                                   827 
298 /* Result is the factorial of an integer */    !! 828 /*
299 big_number_t bn_fact(unsigned long int v)      !! 829  * The Evaluator coroutine and associated types/variables
                                                   >> 830  */
                                                   >> 831 struct func_eval_params
300 {                                                 832 {
301   unsigned long int i;                         !! 833   const struct syntax_node *e;
302   big_number_t retval = bn_new(1);             !! 834   const char **var_name;
303   for (i = 1 ; i <= v ; i++)                   !! 835   int *var_val;
304     {                                          !! 836   int nb_vars;
305       big_number_t I   = bn_new(i);            !! 837 
306       big_number_t tmp = bn_mult(retval, I);   !! 838   int result;
307       sos_x86_videomem_printf(4, 0,            !! 839 };
308                               SOS_X86_VIDEO_BG !! 840 
309                               "%d! = ", (int)i !! 841 static void func_eval(struct func_eval_params *parms)
310       bn_print_console(4, 8, SOS_X86_VIDEO_BG_ !! 842 {
311                        tmp, 55);               !! 843   /* The internal (recursive) nested function to evaluate each node of
312       bn_del(& I);                             !! 844      the syntax tree */
313       bn_del(& retval);                        !! 845   static int rec_eval(const struct syntax_node *n,
314       retval = tmp;                            !! 846                       const char* var_name[], int var_val[], int nb_vars)
                                                   >> 847     {
                                                   >> 848       switch (n->type)
                                                   >> 849         {
                                                   >> 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->var))
                                                   >> 858                 return var_val[i];
                                                   >> 859 
                                                   >> 860             /* Exception: no variable with that name ! */
                                                   >> 861             sos_bochs_printf("ERROR: unknown variable %s\n", n->var);
                                                   >> 862             sos_cpu_kstate_switch(& st_eval, st_main);
                                                   >> 863           }
                                                   >> 864 
                                                   >> 865         case YY_IS_BINOP:
                                                   >> 866           {
                                                   >> 867             int left = rec_eval(n->binop.parm_left,
                                                   >> 868                                 var_name, var_val, nb_vars);
                                                   >> 869             int right = rec_eval(n->binop.parm_right,
                                                   >> 870                                  var_name, var_val, nb_vars);
                                                   >> 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 (INTERNAL error) ! */
                                                   >> 879                 sos_bochs_printf("ERROR: unknown binop %c\n", n->binop.op);
                                                   >> 880                 sos_cpu_kstate_switch(& st_eval, st_main);
                                                   >> 881               }
                                                   >> 882           }
                                                   >> 883 
                                                   >> 884         case YY_IS_UNAROP:
                                                   >> 885           {
                                                   >> 886             int arg = rec_eval(n->unarop.parm, var_name, var_val, nb_vars);
                                                   >> 887             switch (n->unarop.op)
                                                   >> 888               {
                                                   >> 889               case '-': return -arg;
                                                   >> 890               case '+': return arg;
                                                   >> 891               default:
                                                   >> 892                 /* Exception: no such operator (INTERNAL error) ! */
                                                   >> 893                 sos_bochs_printf("ERROR: unknown unarop %c\n", n->unarop.op);
                                                   >> 894                 sos_cpu_kstate_switch(& st_eval, st_main);
                                                   >> 895               }
                                                   >> 896           }
                                                   >> 897         }
                                                   >> 898       
                                                   >> 899       /* Exception: no such syntax node (INTERNAL error) ! */
                                                   >> 900       sos_bochs_printf("ERROR: invalid node type\n");
                                                   >> 901       sos_cpu_kstate_switch(& st_eval, st_main);
                                                   >> 902       return -1; /* let's make gcc happy */
315     }                                             903     }
316                                                   904 
317   return retval;                               !! 905 
                                                   >> 906   /*
                                                   >> 907    * Function BODY
                                                   >> 908    */
                                                   >> 909   /* Update p.result returned back to calling function */
                                                   >> 910   parms->result
                                                   >> 911     = rec_eval(parms->e, parms->var_name, parms->var_val, parms->nb_vars);
                                                   >> 912 }
                                                   >> 913 
                                                   >> 914 /*
                                                   >> 915  * Change the stack for something larger in order to call the
                                                   >> 916  * recursive function above in a safe way
                                                   >> 917  */
                                                   >> 918 static int eval_expression(const struct syntax_node *e,
                                                   >> 919                            const char* var_name[], int var_val[], int nb_vars)
                                                   >> 920 {
                                                   >> 921   struct func_eval_params p
                                                   >> 922     = (struct func_eval_params){ .e=e,
                                                   >> 923                                  .var_name=var_name,
                                                   >> 924                                  .var_val=var_val,
                                                   >> 925                                  .nb_vars=nb_vars,
                                                   >> 926                                  .result = 0 };
                                                   >> 927 
                                                   >> 928   sos_cpu_kstate_init(& st_eval,
                                                   >> 929                       (sos_cpu_kstate_function_arg1_t*)func_eval,
                                                   >> 930                       (sos_ui32_t)/* p.result is modified upon success */&p,
                                                   >> 931                       (sos_vaddr_t)deep_stack, sizeof(deep_stack),
                                                   >> 932                       (sos_cpu_kstate_function_arg1_t*)func_exit, 0);
                                                   >> 933 
                                                   >> 934   /* Go ! */
                                                   >> 935   sos_cpu_kstate_switch(& st_main, st_eval);
                                                   >> 936   return p.result;
318 }                                                 937 }
319                                                   938 
320                                                   939 
321 void bn_test()                                 !! 940 /*
                                                   >> 941  * Function to free the syntax tree
                                                   >> 942  */
                                                   >> 943 static void func_free(struct syntax_node *n)
322 {                                                 944 {
323   big_number_t bn = bn_fact(1000);             !! 945   switch (n->type)
324   sos_bochs_printf("1000! = ");                !! 946     {
325   bn_print_bochs(bn);                          !! 947     case YY_IS_NUM:
326   sos_bochs_printf("\n");                      !! 948     case YY_IS_VAR:
                                                   >> 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     }
327                                                   960   
                                                   >> 961   sos_kfree((sos_vaddr_t)n);
328 }                                                 962 }
329                                                   963 
                                                   >> 964 /*
                                                   >> 965  * Change the stack for something larger in order to call the
                                                   >> 966  * recursive function above in a safe way
                                                   >> 967  */
                                                   >> 968 static void free_syntax_tree(struct syntax_node *tree)
                                                   >> 969 {
                                                   >> 970   sos_cpu_kstate_init(& st_free,
                                                   >> 971                       (sos_cpu_kstate_function_arg1_t*)func_free,
                                                   >> 972                       (sos_ui32_t)tree,
                                                   >> 973                       (sos_vaddr_t)deep_stack, sizeof(deep_stack),
                                                   >> 974                       (sos_cpu_kstate_function_arg1_t*)func_exit, 0);
330                                                   975 
331 /* The C entry point of our operating system * !! 976   /* Go ! */
                                                   >> 977   sos_cpu_kstate_switch(& st_main, st_free);
                                                   >> 978 }
                                                   >> 979 
                                                   >> 980 
                                                   >> 981 /* ======================================================================
                                                   >> 982  * The C entry point of our operating system
                                                   >> 983  */
332 void sos_main(unsigned long magic, unsigned lo    984 void sos_main(unsigned long magic, unsigned long addr)
333 {                                                 985 {
334   unsigned i;                                     986   unsigned i;
335   sos_paddr_t sos_kernel_core_base_paddr, sos_    987   sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
                                                   >> 988   struct syntax_node *syntax_tree;
336                                                   989 
337   /* Grub sends us a structure, called multibo    990   /* Grub sends us a structure, called multiboot_info_t with a lot of
338      precious informations about the system, s    991      precious informations about the system, see the multiboot
339      documentation for more information. */       992      documentation for more information. */
340   multiboot_info_t *mbi;                          993   multiboot_info_t *mbi;
341   mbi = (multiboot_info_t *) addr;                994   mbi = (multiboot_info_t *) addr;
342                                                   995 
343   /* Setup bochs and console, and clear the co    996   /* Setup bochs and console, and clear the console */
344   sos_bochs_setup();                              997   sos_bochs_setup();
345                                                   998 
346   sos_x86_videomem_setup();                       999   sos_x86_videomem_setup();
347   sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);    1000   sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
348                                                   1001 
349   /* Greetings from SOS */                        1002   /* Greetings from SOS */
350   if (magic == MULTIBOOT_BOOTLOADER_MAGIC)        1003   if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
351     /* Loaded with Grub */                        1004     /* Loaded with Grub */
352     sos_x86_videomem_printf(1, 0,                 1005     sos_x86_videomem_printf(1, 0,
353                             SOS_X86_VIDEO_FG_Y    1006                             SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
354                             "Welcome From GRUB    1007                             "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
355                             "SOS", ',',           1008                             "SOS", ',',
356                             (unsigned)(mbi->me    1009                             (unsigned)(mbi->mem_upper >> 10) + 1,
357                             (unsigned)mbi->mem    1010                             (unsigned)mbi->mem_upper);
358   else                                            1011   else
359     /* Not loaded with grub */                    1012     /* Not loaded with grub */
360     sos_x86_videomem_printf(1, 0,                 1013     sos_x86_videomem_printf(1, 0,
361                             SOS_X86_VIDEO_FG_Y    1014                             SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
362                             "Welcome to SOS");    1015                             "Welcome to SOS");
363                                                   1016 
364   sos_bochs_putstring("Message in a bochs\n");    1017   sos_bochs_putstring("Message in a bochs\n");
365                                                   1018 
366   /* Setup CPU segmentation and IRQ subsystem     1019   /* Setup CPU segmentation and IRQ subsystem */
367   sos_gdt_setup();                             !! 1020   sos_gdt_subsystem_setup();
368   sos_idt_setup();                             !! 1021   sos_idt_subsystem_setup();
369                                                   1022 
370   /* Setup SOS IRQs and exceptions subsystem *    1023   /* Setup SOS IRQs and exceptions subsystem */
371   sos_exceptions_setup();                      !! 1024   sos_exception_subsystem_setup();
372   sos_irq_setup();                             !! 1025   sos_irq_subsystem_setup();
373                                                   1026 
374   /* Configure the timer so as to raise the IR    1027   /* Configure the timer so as to raise the IRQ0 at a 100Hz rate */
375   sos_i8254_set_frequency(100);                   1028   sos_i8254_set_frequency(100);
376                                                   1029 
377                                                << 
378   /* We need a multiboot-compliant boot loader    1030   /* We need a multiboot-compliant boot loader to get the size of the RAM */
379   if (magic != MULTIBOOT_BOOTLOADER_MAGIC)        1031   if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
380     {                                             1032     {
381       sos_x86_videomem_putstring(20, 0,           1033       sos_x86_videomem_putstring(20, 0,
382                                  SOS_X86_VIDEO    1034                                  SOS_X86_VIDEO_FG_LTRED
383                                    | SOS_X86_V    1035                                    | SOS_X86_VIDEO_BG_BLUE
384                                    | SOS_X86_V    1036                                    | SOS_X86_VIDEO_FG_BLINKING,
385                                  "I'm not load    1037                                  "I'm not loaded with Grub !");
386       /* STOP ! */                                1038       /* STOP ! */
387       for (;;)                                    1039       for (;;)
388         continue;                                 1040         continue;
389     }                                             1041     }
390                                                   1042 
                                                   >> 1043   /*
                                                   >> 1044    * Some interrupt handlers
                                                   >> 1045    */
                                                   >> 1046 
391   /* Binding some HW interrupts and exceptions    1047   /* Binding some HW interrupts and exceptions to software routines */
392   sos_irq_set_routine(SOS_IRQ_TIMER,              1048   sos_irq_set_routine(SOS_IRQ_TIMER,
393                             clk_it);           !! 1049                       clk_it);
394   /* Enabling the HW interrupts here, this wil !! 1050 
395      interrupt call our clk_it handler */      !! 1051   /*
396   asm volatile ("sti\n");                      !! 1052    * Setup physical memory management
                                                   >> 1053    */
                                                   >> 1054 
397   /* Multiboot says: "The value returned for u    1055   /* Multiboot says: "The value returned for upper memory is maximally
398      the address of the first upper memory hol    1056      the address of the first upper memory hole minus 1 megabyte.". It
399      also adds: "It is not guaranteed to be th    1057      also adds: "It is not guaranteed to be this value." aka "YMMV" ;) */
400   sos_physmem_setup((mbi->mem_upper<<10) + (1< !! 1058   sos_physmem_subsystem_setup((mbi->mem_upper<<10) + (1<<20),
401                     & sos_kernel_core_base_pad !! 1059                               & sos_kernel_core_base_paddr,
402                     & sos_kernel_core_top_padd !! 1060                               & sos_kernel_core_top_paddr);
403                                                   1061   
404   /*                                              1062   /*
405    * Switch to paged-memory mode                  1063    * Switch to paged-memory mode
406    */                                             1064    */
407                                                   1065 
408   /* Disabling interrupts should seem more cor    1066   /* Disabling interrupts should seem more correct, but it's not really
409      necessary at this stage */                   1067      necessary at this stage */
410   if (sos_paging_setup(sos_kernel_core_base_pa !! 1068   SOS_ASSERT_FATAL(SOS_OK ==
411                        sos_kernel_core_top_pad !! 1069                    sos_paging_subsystem_setup(sos_kernel_core_base_paddr,
412     sos_bochs_printf("Could not setup paged me !! 1070                                               sos_kernel_core_top_paddr));
413   sos_x86_videomem_printf(2, 0,                !! 1071   
414                           SOS_X86_VIDEO_FG_YEL !! 1072   /* Bind the page fault exception */
415                           "Paged-memory mode i !! 1073   sos_exception_set_routine(SOS_EXCEPT_PAGE_FAULT,
                                                   >> 1074                             pgflt_ex);
416                                                   1075 
                                                   >> 1076   /*
                                                   >> 1077    * Setup kernel virtual memory allocator
                                                   >> 1078    */ 
417                                                   1079 
418   if (sos_kmem_vmm_setup(sos_kernel_core_base_ !! 1080   if (sos_kmem_vmm_subsystem_setup(sos_kernel_core_base_paddr,
419                          sos_kernel_core_top_p !! 1081                                    sos_kernel_core_top_paddr,
                                                   >> 1082                                    bootstrap_stack_bottom,
                                                   >> 1083                                    bootstrap_stack_bottom
                                                   >> 1084                                    + bootstrap_stack_size))
420     sos_bochs_printf("Could not setup the Kern    1085     sos_bochs_printf("Could not setup the Kernel virtual space allocator\n");
421                                                   1086 
422   if (sos_kmalloc_setup())                     !! 1087   if (sos_kmalloc_subsystem_setup())
423     sos_bochs_printf("Could not setup the Kmal    1088     sos_bochs_printf("Could not setup the Kmalloc subsystem\n");
424                                                   1089 
425   /* Run some kmalloc tests */                 !! 1090   /*
426   bn_test();                                   !! 1091    * Enabling the HW interrupts here, this will make the timer HW
                                                   >> 1092    * interrupt call our clk_it handler
                                                   >> 1093    */
                                                   >> 1094   asm volatile ("sti\n");
                                                   >> 1095 
                                                   >> 1096   /*
                                                   >> 1097    * Print hello world using coroutines
                                                   >> 1098    */
                                                   >> 1099   print_hello_world();
                                                   >> 1100 
                                                   >> 1101 
                                                   >> 1102   /*
                                                   >> 1103    * Run coroutine tests
                                                   >> 1104    */
                                                   >> 1105   sos_x86_videomem_printf(4, 0,
                                                   >> 1106                           SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_LTGREEN,
                                                   >> 1107                           "Coroutine test");
                                                   >> 1108   sos_x86_videomem_printf(5, 0,
                                                   >> 1109                           SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 1110                           "Parsing...");
                                                   >> 1111   syntax_tree = parse_expression(" -  ( (69/ toto)+ ( (( - +-- 1))) + --toto*((toto+ - - y - +2*(y-toto))*y) +2*(y-toto) )/- (( y - toto)*2)");
                                                   >> 1112 
                                                   >> 1113   if (syntax_tree != NULL)
                                                   >> 1114     {
                                                   >> 1115       sos_x86_videomem_printf(6, 0,
                                                   >> 1116                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 1117                               "Evaluating...");
                                                   >> 1118       sos_x86_videomem_printf(7, 0,
                                                   >> 1119                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 1120                               "Result=%d (if 0: check bochs output)",
                                                   >> 1121                               eval_expression(syntax_tree,
                                                   >> 1122                                               (const char*[]){"toto", "y"},
                                                   >> 1123                                               (int[]){3, 4},
                                                   >> 1124                                               2));
                                                   >> 1125       free_syntax_tree(syntax_tree);
                                                   >> 1126       sos_x86_videomem_printf(8, 0,
                                                   >> 1127                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 1128                               "Done (un-allocated syntax tree)");
                                                   >> 1129     }
                                                   >> 1130   else
                                                   >> 1131     {
                                                   >> 1132       sos_x86_videomem_printf(6, 0,
                                                   >> 1133                               SOS_X86_VIDEO_BG_BLUE | SOS_X86_VIDEO_FG_YELLOW,
                                                   >> 1134                               "Error in parsing (see bochs output)");
                                                   >> 1135     }
                                                   >> 1136 
                                                   >> 1137   /*
                                                   >> 1138    * Run some demand-paging tests
                                                   >> 1139    */
                                                   >> 1140   test_demand_paging(234567, 500);
                                                   >> 1141 
                                                   >> 1142 
                                                   >> 1143   /*
                                                   >> 1144    * Create an un-resolved page fault, which will make the page fault
                                                   >> 1145    * handler print the backtrace.
                                                   >> 1146    */
                                                   >> 1147   test_backtrace(6, 0xdeadbeef, bootstrap_stack_bottom, bootstrap_stack_size);
                                                   >> 1148 
                                                   >> 1149   /*
                                                   >> 1150    * System should be halted BEFORE here !
                                                   >> 1151    */
                                                   >> 1152 
427                                                   1153 
428   /* An operatig system never ends */             1154   /* An operatig system never ends */
429   for (;;)                                        1155   for (;;)
430     continue;                                  !! 1156     {
                                                   >> 1157       /* Remove this instruction if you get an "Invalid opcode" CPU
                                                   >> 1158          exception (old 80386 CPU) */
                                                   >> 1159       asm("hlt\n");
431                                                   1160 
432   return;                                      !! 1161       continue;
                                                   >> 1162     }
433 }                                                 1163 }
                                                      

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