sos-code-article9.5.old/drivers/mem.c (2006-01-22 12:48:28.000000000 +0100 )
sos-code-article9.5/drivers/mem.c (2006-02-26 19:39:43.000000000 +0100 )
Line 91 
Line 91 
     + sos_umem_vmm_get_offset_in_resource(vr);     + sos_umem_vmm_get_offset_in_resource(vr);
  
   /* Don't allow demand paging of non kernel pages */   /* Don't allow demand paging of non kernel pages */
   if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_KERNEL_AREA(vaddr, 1))
  
   /* Lookup physical kernel page */   /* Lookup physical kernel page */
  
 

sos-code-article9.5.old/extra/bootsect.S (2006-01-22 12:48:28.000000000 +0100 )
sos-code-article9.5/extra/bootsect.S (2006-02-26 19:39:37.000000000 +0100 )
Line 1 
Line 1 
  
 /* /*
  * @(#) $Id: bootsect.S,v 1.12 2005/08/13 13:47:31 d2 Exp $  * @(#) $Id: bootsect.S 1310 2005-08-13 13:47:31Z d2 $
  * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty  * Auteurs : Thomas Petazzoni & Fabrice Gautier & Emmanuel Marty
  *           Jerome Petazzoni & Bernard Cassagne & coffeeman  *           Jerome Petazzoni & Bernard Cassagne & coffeeman
  
 

sos-code-article9.5.old/hwcore/paging.c (2006-01-22 12:48:30.000000000 +0100 )
sos-code-article9.5/hwcore/paging.c (2006-02-26 19:39:40.000000000 +0100 )
Line 954 
Line 954 
 { {
   SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(base_address));   SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(base_address));
   SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(length));   SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(length));
   SOS_ASSERT_FATAL(SOS_PAGING_BASE_USER_ADDRESS <= base_address);   SOS_ASSERT_FATAL(SOS_PAGING_IS_USER_AREA(base_address, length));
   /* Mark all the pages read-only, when already mapped in physical   /* Mark all the pages read-only, when already mapped in physical
      memory */      memory */
  
 

sos-code-article9.5.old/hwcore/paging.h (2006-01-22 12:48:30.000000000 +0100 )
sos-code-article9.5/hwcore/paging.h (2006-02-26 19:39:40.000000000 +0100 )
Line 40 
Line 40 
  
 /** /**
  * Basic SOS virtual memory organization  * Basic SOS virtual memory organization
  */  *
 /** Frontier between kernel and user space virtual addresses */  * - Kernel space starts at the lower 4kB address (first page is not
 #define SOS_PAGING_BASE_USER_ADDRESS (0x40000000) /* 1GB (must be 4MB-aligned) */  *   mapped in order to catch invalid pointers)
 #define SOS_PAGING_TOP_USER_ADDRESS  (0xFFFFFFFF) /* 4GB - 1B */  * - User space starts at the 1GB address
 #define SOS_PAGING_USER_SPACE_SIZE   (0xc0000000) /* 3GB */  */
  #define SOS_PAGING_BASE_KERNEL_ADDRESS (0x00001000) /* 4kB */
  #define SOS_PAGING_TOP_KERNEL_ADDRESS  (0x3FFFFFFF) /* 1GB - 1B */
  #define SOS_PAGING_KERNEL_SPACE_SIZE   (0x3FFFF000) /* 1GB - 4kB */
  #define SOS_PAGING_IS_KERNEL_AREA(base_addr, length) \
    ( (SOS_PAGING_BASE_KERNEL_ADDRESS <= (base_addr))  \
        && ((length) <= SOS_PAGING_KERNEL_SPACE_SIZE) )
  
  #define SOS_PAGING_BASE_USER_ADDRESS   (0x40000000) /* 1GB (must be 4MB-aligned) */
  #define SOS_PAGING_TOP_USER_ADDRESS    (0xFFFFFFFF) /* 4GB - 1B */
  #define SOS_PAGING_USER_SPACE_SIZE     (0xc0000000) /* 3GB */
  #define SOS_PAGING_IS_USER_AREA(base_addr, length) \
    ( (SOS_PAGING_BASE_USER_ADDRESS <= (base_addr))  \
        && ((length) <= SOS_PAGING_USER_SPACE_SIZE) )
 /** Length of the space reserved for the mirroring in the kernel /** Length of the space reserved for the mirroring in the kernel
     virtual space */     virtual space */
  
 

sos-code-article9.5.old/INSTALL (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/INSTALL (2006-02-26 19:39:43.000000000 +0100 )
Line 124 
Line 124 
  
 Release development platform: Release development platform:
  
  - OS           : Linux 2.6.14.3 x86_64  - OS           : Linux 2.6.16-rc2 i686
  - gcc          : i586-pc-elf-gcc-4.0.2 (GCC) 4.0.2  - gcc          : gcc (GCC) 4.0.3 20060128 (prerelease) (Debian 4.0.2-8)
  - GNU binutils : GNU ld version 2.16  - GNU binutils : GNU ld version 2.16.91 20060118 Debian GNU/Linux
  - GNU make     : GNU Make 3.80  - GNU make     : GNU Make 3.81beta4
 Usual development platforms known to work: Usual development platforms known to work:
  
  
 

sos-code-article9.5.old/sos/binfmt_elf32.c (2006-01-22 12:48:30.000000000 +0100 )
sos-code-article9.5/sos/binfmt_elf32.c (2006-02-26 19:39:41.000000000 +0100 )
Line 386 
Line 386 
           continue;           continue;
         }         }
              
       if (elf_phdrs[i].p_vaddr < SOS_PAGING_BASE_USER_ADDRESS)       if (! SOS_PAGING_IS_USER_AREA(elf_phdrs[i].p_vaddr,
                                      elf_phdrs[i].p_memsz) )
           sos_display_fatal_error("User program has an incorrect address");           sos_display_fatal_error("User program has an incorrect address");
         }         }
  
 

sos-code-article9.5.old/sos/main.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/main.c (2006-02-26 19:39:41.000000000 +0100 )
Line 110 
Line 110 
       || (cur_thr->fixup_uaccess.return_vaddr))       || (cur_thr->fixup_uaccess.return_vaddr))
     {     {
       __label__ unforce_address_space;       __label__ unforce_address_space;
       sos_bool_t need_to_setup_mmu;       sos_bool_t need_to_prepare_user_space_access;
  
       /* Make sure to always stay in the interrupted thread's MMU       /* Do we already try to access an address space ? */
          configuration */       need_to_prepare_user_space_access
       need_to_setup_mmu = (cur_thr->squatted_mm_context         = (sos_thread_get_current()->squatted_address_space == NULL);
                            != sos_process_get_mm_context(cur_thr->process)); 
       if (need_to_setup_mmu)       if (need_to_prepare_user_space_access)
          /* No: Need to configure the interrupted thread user space */
  
       if (SOS_OK ==       if (SOS_OK ==
Line 136 
Line 137 
           goto unforce_address_space;           goto unforce_address_space;
         }         }
  
       if (need_to_setup_mmu)       if (need_to_prepare_user_space_access)
  
       sos_bochs_printf("\e[35mTHR %p: Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\e[m\n",       sos_bochs_printf("\e[35mTHR %p: Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\e[m\n",
Line 148 
Line 149 
       sos_thread_exit();       sos_thread_exit();
  
     unforce_address_space:     unforce_address_space:
       if (need_to_setup_mmu)       if (need_to_prepare_user_space_access)
       return;       return;
     }     }
Line 292 
Line 293 
   struct sos_process *proc_init;   struct sos_process *proc_init;
   struct sos_thread *new_thr;   struct sos_thread *new_thr;
   sos_uaddr_t ustack, start_uaddr;   sos_uaddr_t ustack, start_uaddr;
    int fake_args[32];
    sos_ret_t ret;
   struct sos_fs_opened_file * init_root, * init_cwd, * unused_of;   struct sos_fs_opened_file * init_root, * init_cwd, * unused_of;
  
   /* Create the new process */   /* Create the new process */
Line 339 
Line 342 
     }     }
  
  
  
   start_uaddr = sos_binfmt_elf32_map(as_init, "init");   start_uaddr = sos_binfmt_elf32_map(as_init, "init");
   if (0 == start_uaddr)   if (0 == start_uaddr)
Line 359 
Line 361 
       return -SOS_ENOMEM;       return -SOS_ENOMEM;
     }     }
  
    /* Compute the address of the stack that will be used to initialize
       the user thread */
    ustack = SOS_ALIGN_INF((ustack + SOS_DEFAULT_USER_STACK_SIZE
                            - sizeof(fake_args)), 4);
  
    /* Build fake argv/envp arguments for the init process. See
       userland/crt.c for the format. */
    fake_args[0] = 0x1;                      /* argc */
    fake_args[1] = 4 * sizeof(fake_args[0]); /* offset of argv[0] */
    fake_args[2] = 0x0;                      /* delimiter between argv and envp */
    fake_args[3] = 0x0;                      /* end of envp */
    strzcpy ((char *) & fake_args[4],        /* argv[0] contents */
             "init", 5);
  
    /* Copy the arguments to the user thread stack */
    ret = sos_memcpy_to_specified_userspace (as_init,
                                             ustack,
                                             (sos_vaddr_t) fake_args,
                                             sizeof(fake_args));
    if (sizeof(fake_args) != ret)
      {
        sos_bochs_printf ("sos_memcpy_to_specified_userspace() failed, returned %d\n", ret);
        sos_process_unref(proc_init);
        return ret;
      }
  
   /* Now create the user thread */   /* Now create the user thread */
   new_thr = sos_create_user_thread(NULL,   new_thr = sos_create_user_thread(NULL,
                                    proc_init,                                    proc_init,
                                    start_uaddr,                                    start_uaddr,
                                    0, 0,                                    0, 0,
                                    ustack + SOS_DEFAULT_USER_STACK_SIZE - 4,                                    ustack,
   if (! new_thr)   if (! new_thr)
     {     {
  
 

sos-code-article9.5.old/sos/process.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/process.c (2006-02-26 19:39:40.000000000 +0100 )
Line 170 
Line 170 
     }     }
  
   if (do_copy_current_process)   if (do_copy_current_process)
     proc->address_space = sos_umem_vmm_duplicate_current_thread_as(proc);     {
        struct sos_process * myself = sos_thread_get_current()->process;
        proc->address_space
          = sos_umem_vmm_duplicate_as(sos_process_get_address_space(myself),
                                      proc);
      }
     proc->address_space = sos_umem_vmm_create_empty_as(proc);     proc->address_space = sos_umem_vmm_create_empty_as(proc);
  
Line 195 
Line 200 
   /* Add it to the global list of processes */   /* Add it to the global list of processes */
   sos_disable_IRQs(flags);   sos_disable_IRQs(flags);
   list_add_tail(process_list, proc);   list_add_tail(process_list, proc);
    proc->ref_cnt = 1;  /* Mark the process as referenced */
   sos_restore_IRQs(flags);   sos_restore_IRQs(flags);
  
   /* Mark the process as referenced */ 
   proc->ref_cnt = 1; 
  
   if (SOS_OK != retval)   if (SOS_OK != retval)
     {     {
  
 

sos-code-article9.5.old/sos/syscall.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/syscall.c (2006-02-26 19:39:40.000000000 +0100 )
Line 20 
Line 20 
 #include <sos/kmalloc.h> #include <sos/kmalloc.h>
 #include <sos/klibc.h> #include <sos/klibc.h>
 #include <drivers/bochs.h> #include <drivers/bochs.h>
 #include <hwcore/paging.h> 
 #include <sos/umem_vmm.h> #include <sos/umem_vmm.h>
 #include <drivers/zero.h> #include <drivers/zero.h>
Line 46 
Line 45 
 { {
   sos_ret_t retval;   sos_ret_t retval;
  
  
   switch(syscall_id)   switch(syscall_id)
     {     {
     case SOS_SYSCALL_ID_EXIT:     case SOS_SYSCALL_ID_EXIT:
Line 105 
Line 105 
         struct sos_process * proc;         struct sos_process * proc;
         struct sos_umem_vmm_as *new_as;         struct sos_umem_vmm_as *new_as;
         sos_uaddr_t user_str, ustack, start_uaddr;         sos_uaddr_t user_str, ustack, start_uaddr;
          sos_uaddr_t src_argaddr;
          sos_size_t  len_args;
         sos_size_t len;         sos_size_t len;
         char * str;         char * str;
  
Line 119 
Line 121 
           }           }
  
         /* Get the user arguments */         /* Get the user arguments */
         retval = sos_syscall_get2args(user_ctxt, & user_str, & len);         retval = sos_syscall_get4args(user_ctxt, & user_str, & len,
                                        & src_argaddr, & len_args);
           break;           break;
  
          /* Don't go any further is the arg/env array is obviously too
             large */
          if (SOS_DEFAULT_USER_STACK_SIZE <= len_args)
            {
              retval = -SOS_EINVAL;
              break;
            }
  
         /* Copy the program name into kernel sppace */         /* Copy the program name into kernel sppace */
         retval = sos_strndup_from_user(& str, user_str, len + 1, 0);         retval = sos_strndup_from_user(& str, user_str, len + 1, 0);
         if (SOS_OK != retval)         if (SOS_OK != retval)
Line 163 
Line 174 
             break;             break;
           }           }
  
          /* ustack now referes to the initial stack pointer of the new
             user thread: update it here */
          ustack = SOS_ALIGN_INF((ustack + SOS_DEFAULT_USER_STACK_SIZE
                                  - len_args), 4);
  
          if (len_args != sos_usercpy(new_as, ustack,
                                      NULL, src_argaddr,
                                      len_args))
            {
              sos_umem_vmm_delete_as(new_as);
              sos_kfree((sos_vaddr_t)str);
              retval = -SOS_EFAULT;
              break;
            }
  
         /* Now create the user thread */         /* Now create the user thread */
         new_thr = sos_create_user_thread(NULL,         new_thr = sos_create_user_thread(NULL,
                                          proc,                                          proc,
                                          start_uaddr,                                          start_uaddr,
                                          0, 0,                                          0, 0,
                                          ustack + SOS_DEFAULT_USER_STACK_SIZE                                          ustack,
                                            - 4, 
         if (! new_thr)         if (! new_thr)
           {           {
             sos_umem_vmm_delete_as(new_as);             sos_umem_vmm_delete_as(new_as);
             sos_kfree((sos_vaddr_t)str);             sos_kfree((sos_vaddr_t)str);
             retval = -SOS_ENOMEM;             retval = -SOS_ENOMEM;
             break;                         break;
  
         sos_process_set_name(proc, str);         sos_process_set_name(proc, str);
Line 188 
Line 213 
           {           {
             sos_umem_vmm_delete_as(new_as);             sos_umem_vmm_delete_as(new_as);
             sos_kfree((sos_vaddr_t)str);             sos_kfree((sos_vaddr_t)str);
             break;                         break;
  
         /* The current thread must exit now */         /* The current thread must exit now */
Line 297 
Line 322 
       }       }
       break;       break;
  
  
     case SOS_SYSCALL_ID_MSYNC:     case SOS_SYSCALL_ID_MSYNC:
       {       {
         sos_uaddr_t start_uaddr;         sos_uaddr_t start_uaddr;
Line 322 
Line 348 
       }       }
       break;       break;
  
  
     case SOS_SYSCALL_ID_NEW_THREAD:     case SOS_SYSCALL_ID_NEW_THREAD:
       {       {
         sos_uaddr_t start_func;         sos_uaddr_t start_func;
Line 1437 
Line 1464 
       sos_bochs_printf("Syscall: UNKNOWN[%d]\n", syscall_id);       sos_bochs_printf("Syscall: UNKNOWN[%d]\n", syscall_id);
       retval = -SOS_ENOSUP;       retval = -SOS_ENOSUP;
     }     }
    
 } }
  
 

sos-code-article9.5.old/sos/syscall.h (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/syscall.h (2006-02-26 19:39:40.000000000 +0100 )
Line 43 
Line 43 
  * User memory mappings management  * User memory mappings management
  */  */
 #define SOS_SYSCALL_ID_FORK        257 /**< Args: NONE, retval={father:child_pd, child:0} */ #define SOS_SYSCALL_ID_FORK        257 /**< Args: NONE, retval={father:child_pd, child:0} */
 #define SOS_SYSCALL_ID_EXEC        258 /**< Args: ptr_exec_path strlen_exec_path, retval=errno */ #define SOS_SYSCALL_ID_EXEC        258 /**< Args: ptr_exec_path strlen_exec_path addr_args len_args, retval=errno */
 #define SOS_SYSCALL_ID_MPROTECT    261 /**< Args: start_uaddr size access_rights, retval=errno */ #define SOS_SYSCALL_ID_MPROTECT    261 /**< Args: start_uaddr size access_rights, retval=errno */
 #define SOS_SYSCALL_ID_MRESIZE     262 /**< Args: old_uaddr old_size ptr_new_uaddr new_size flags, retval=errno */ #define SOS_SYSCALL_ID_MRESIZE     262 /**< Args: old_uaddr old_size ptr_new_uaddr new_size flags, retval=errno */
  
 

sos-code-article9.5.old/sos/thread.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/thread.c (2006-02-26 19:39:41.000000000 +0100 )
Line 70 
Line 70 
 static struct sos_kslab_cache *cache_thread; static struct sos_kslab_cache *cache_thread;
  
  
 /** 
  * (Forwad declaration) Helper function to change the MMU config of 
  * the current executing thread. Analogous to function 
  * sos_thread_change_current_mm_context() of article 7 
  */ 
 static sos_ret_t change_current_mm_context(struct sos_mm_context *mm_ctxt); 
  
  
 { {
   SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);   SOS_ASSERT_FATAL(current_thread->state == SOS_THR_RUNNING);
Line 361 
Line 353 
       SOS_ASSERT_FATAL(the_thread->process != NULL);       SOS_ASSERT_FATAL(the_thread->process != NULL);
  
       /* It should not squat any other's address space */       /* It should not squat any other's address space */
       SOS_ASSERT_FATAL(the_thread->squatted_mm_context == NULL);       SOS_ASSERT_FATAL(the_thread->squatted_address_space == NULL);
       /* Perform an MMU context switch if needed */       /* Perform an MMU context switch if needed */
       sos_mm_context_switch_to(sos_process_get_mm_context(the_thread->process));       sos_umem_vmm_set_current_as(sos_process_get_address_space(the_thread->process));
  
   /* the_thread is a kernel thread squatting a precise address   /* Restore the address space currently in use */
      space ? */   else
   else if (the_thread->squatted_mm_context != NULL)       sos_umem_vmm_set_current_as(the_thread->squatted_address_space);
     sos_mm_context_switch_to(the_thread->squatted_mm_context); 
  
  
Line 386 
Line 377 
  
   sos_kfree((sos_vaddr_t) thr->kernel_stack_base_addr);   sos_kfree((sos_vaddr_t) thr->kernel_stack_base_addr);
  
   /* If the thread squats an address space, release it */   /* Not allowed to squat any user space at deletion time */
   if (thr->squatted_mm_context)   SOS_ASSERT_FATAL(NULL == thr->squatted_address_space);
     SOS_ASSERT_FATAL(SOS_OK == change_current_mm_context(NULL)); 
   /* For a user thread: remove the thread from the process threads' list */   /* For a user thread: remove the thread from the process threads' list */
   if (thr->process)   if (thr->process)
Line 780 
Line 770 
  */  */
  
  
 static sos_ret_t 
 change_current_mm_context(struct sos_mm_context *mm_ctxt) 
 { 
   /* Retrieve the previous mm context */ 
   struct sos_mm_context * prev_mm_ctxt 
     = current_thread->squatted_mm_context; 
  
   /* Update current thread's squatted mm context */ 
   current_thread->squatted_mm_context = mm_ctxt; 
  
   /* Update the reference counts and switch the MMU configuration if 
      needed */ 
   if (mm_ctxt != NULL) 
     { 
       sos_mm_context_ref(mm_ctxt); /* Because it is now referenced as 
                                       the squatted_mm_context field of 
                                       the thread */ 
       sos_mm_context_switch_to(mm_ctxt); 
     } 
   else 
     sos_mm_context_unref(prev_mm_ctxt); /* Because it is not referenced as 
                                            the squatted_mm_context field of 
                                            the thread any more */ 
  
   return SOS_OK; 
 } 
  
  
 sos_thread_prepare_user_space_access(struct sos_umem_vmm_as * dest_as, sos_thread_prepare_user_space_access(struct sos_umem_vmm_as * dest_as,
                                      sos_vaddr_t fixup_retvaddr)                                      sos_vaddr_t fixup_retvaddr)
Line 823 
Line 785 
  
       dest_as = sos_process_get_address_space(current_thread->process);       dest_as = sos_process_get_address_space(current_thread->process);
     }     }
   else 
     /* Don't allow to access to an address space different than that 
        of the current thread if the page fault are allowed ! */ 
     SOS_ASSERT_FATAL(! fixup_retvaddr); 
   sos_disable_IRQs(flags);   sos_disable_IRQs(flags);
   SOS_ASSERT_FATAL(NULL == current_thread->squatted_mm_context);   SOS_ASSERT_FATAL(NULL == current_thread->squatted_address_space);
  
   /* Change the MMU configuration and init the fixup return address */   /* Change the MMU configuration and init the fixup return address */
   retval = change_current_mm_context(sos_umem_vmm_get_mm_context(dest_as));   retval = sos_umem_vmm_set_current_as(dest_as);
     {     {
        current_thread->squatted_address_space      = dest_as;
       current_thread->fixup_uaccess.return_vaddr  = fixup_retvaddr;       current_thread->fixup_uaccess.return_vaddr  = fixup_retvaddr;
       current_thread->fixup_uaccess.faulted_uaddr = 0;             current_thread->fixup_uaccess.faulted_uaddr = 0;
  
   sos_restore_IRQs(flags);   sos_restore_IRQs(flags);
Line 852 
Line 811 
   sos_ui32_t flags;   sos_ui32_t flags;
  
   sos_disable_IRQs(flags);   sos_disable_IRQs(flags);
   SOS_ASSERT_FATAL(NULL != current_thread->squatted_mm_context);   SOS_ASSERT_FATAL(NULL != current_thread->squatted_address_space);
   /* Don't impose anything regarding the current MMU configuration anymore */   /* Don't impose anything regarding the current MMU configuration anymore */
   retval = change_current_mm_context(NULL); 
   current_thread->fixup_uaccess.faulted_uaddr = 0;   current_thread->fixup_uaccess.faulted_uaddr = 0;
  
    retval = sos_umem_vmm_set_current_as(NULL);
    current_thread->squatted_address_space      = NULL;
  
   sos_restore_IRQs(flags);   sos_restore_IRQs(flags);
   return retval;   return retval;
 } }
  
 

sos-code-article9.5.old/sos/thread.h (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/thread.h (2006-02-26 19:39:41.000000000 +0100 )
Line 126 
Line 126 
    * This is the SOS implementation of the Linux "Lazy TLB" and    * This is the SOS implementation of the Linux "Lazy TLB" and
    * address-space loaning.    * address-space loaning.
    */    */
   struct sos_mm_context *squatted_mm_context;   struct sos_umem_vmm_as *squatted_address_space;
   /* Data specific to each state */   /* Data specific to each state */
   union   union
Line 349 
Line 349 
  * @param dest_as The address space we want to access, or NULL to  * @param dest_as The address space we want to access, or NULL to
  * access current thread's address space  * access current thread's address space
  *  *
  * @param fixup_retvaddr When != 0, then dest_as MUST BE NULL (we  * @param fixup_retvaddr When != 0, the page fault handler should
  * don't allow controlled access from kernel into user space from a  * accept page faults from the kernel in user space, and resolve them
  * foreign thread). In this case, the page fault handler should accept  * in the usual way. The value in retvaddr is where the page fault
  * page faults from the kernel in user space, and resolve them in the  * handler has to return to in case the page fault remains
  * usual way. The value in retvaddr is where the page fault handler  * unresolved. The address of the faulting address is kept in
  * has to return to in case the page fault remains unresolved. The 
  * address of the faulting address is kept in 
  *  *
  * @note typical values for fixup_retvaddr are obtained by "Labels as  * @note typical values for fixup_retvaddr are obtained by "Labels as
  
 

sos-code-article9.5.old/sos/uaccess.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/uaccess.c (2006-02-26 19:39:41.000000000 +0100 )
Line 34 
Line 34 
  ({ if (__uaccess_zero_fool_gcc) goto lbl; })  ({ if (__uaccess_zero_fool_gcc) goto lbl; })
  
  
 static sos_ret_t nocheck_user_memcpy(sos_vaddr_t dest, /**
   * @param user_as The user address space we want to transfer from/to
   *
   * @return >=0 : number of bytes successfully transferred, <0 an error code
   */
  static sos_ret_t nocheck_user_memcpy(struct sos_umem_vmm_as * user_as,
                                       sos_vaddr_t dest,
                                      sos_size_t size,                                      sos_size_t size,
                                      sos_bool_t transfer_from_user)                                      sos_bool_t transfer_from_user)
Line 50 
Line 56 
   if (size <= 0)   if (size <= 0)
     return 0;     return 0;
  
   retval = sos_thread_prepare_user_space_access(NULL,   retval = sos_thread_prepare_user_space_access(user_as,
   if (SOS_OK != retval)   if (SOS_OK != retval)
     return retval;     return retval;
Line 103 
Line 109 
                                sos_size_t size)                                sos_size_t size)
 { {
   /* Make sure user is trying to access user space */   /* Make sure user is trying to access user space */
   if (user_from < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(user_from, size) )
  
   if (user_from > SOS_PAGING_TOP_USER_ADDRESS - size)   /* Make sure the copy totally resides inside kernel space */
    if (! SOS_PAGING_IS_KERNEL_AREA(kernel_to, size) )
  
   return nocheck_user_memcpy(kernel_to, user_from, size, TRUE);   return nocheck_user_memcpy(NULL, kernel_to, user_from, size, TRUE);
  
  
Line 144 
Line 151 
                              sos_vaddr_t kernel_from,                              sos_vaddr_t kernel_from,
                              sos_size_t size)                              sos_size_t size)
 { {
    /* Make sure the source totally resides inside kernel space */
    if (! SOS_PAGING_IS_KERNEL_AREA(kernel_from, size) )
      return -SOS_EPERM;
  
   /* Make sure user is trying to access user space */   /* Make sure user is trying to access user space */
   if (user_to < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(user_to, size) )
  
   if (user_to > SOS_PAGING_TOP_USER_ADDRESS - size)   return nocheck_user_memcpy(NULL, user_to, kernel_from, size, FALSE);
  }
  
  
  sos_ret_t sos_memcpy_from_specified_userspace(sos_vaddr_t kernel_to,
                                                struct sos_umem_vmm_as * src_as,
                                                sos_uaddr_t user_from,
                                                sos_size_t size)
  {
    if (NULL == src_as)
      return -SOS_EINVAL;
    
    /* Make sure user is trying to access user space */
    if (! SOS_PAGING_IS_USER_AREA(user_from, size) )
      return -SOS_EPERM;
  
    /* Make sure the copy totally resides inside kernel space */
    if (! SOS_PAGING_IS_KERNEL_AREA(kernel_to, size) )
      return -SOS_EPERM;
  
    return nocheck_user_memcpy(src_as, kernel_to, user_from, size, TRUE);
  }
  
  
  sos_ret_t sos_memcpy_to_specified_userspace(struct sos_umem_vmm_as * dst_as,
                                              sos_uaddr_t user_to,
                                              sos_vaddr_t kernel_from,
                                              sos_size_t size)
  {
    if (NULL == dst_as)
      return -SOS_EINVAL;
    
    /* Make sure the source totally resides inside kernel space */
    if (! SOS_PAGING_IS_KERNEL_AREA(kernel_from, size) )
      return -SOS_EPERM;
  
    /* Make sure user is trying to access user space */
    if (! SOS_PAGING_IS_USER_AREA(user_to, size) )
      return -SOS_EPERM;
  
    return nocheck_user_memcpy(dst_as, user_to, kernel_from, size, FALSE);
  }
  
  
  sos_ret_t sos_usercpy(struct sos_umem_vmm_as * dst_as,
                        sos_uaddr_t dst_uaddr,
                        struct sos_umem_vmm_as * src_as,
                        sos_uaddr_t src_uaddr,
                        sos_size_t size)
  {
    sos_vaddr_t kern_addr;
    sos_ret_t retval;
  
    if (size <= 0)
      return 0;
  
    /* Make sure user is trying to access user space */
    if (! SOS_PAGING_IS_USER_AREA(src_uaddr, size) )
      return -SOS_EPERM;
    if (! SOS_PAGING_IS_USER_AREA(dst_uaddr, size) )
  
   return nocheck_user_memcpy(user_to, kernel_from, size, FALSE);   kern_addr = sos_kmalloc(size, 0);
    if (! kern_addr)
      return -SOS_ENOMEM;
  
    retval = nocheck_user_memcpy(src_as, kern_addr, src_uaddr,
                                 size, TRUE);
    if (retval <= 0)
      {
        sos_kfree((sos_vaddr_t)kern_addr);
        return retval;
      }
  
    retval = nocheck_user_memcpy(dst_as, dst_uaddr, kern_addr,
                                 retval, FALSE);
  
    sos_kfree((sos_vaddr_t)kern_addr);
  
    return retval;
  
  
Line 167 
Line 254 
     return 0;     return 0;
  
   /* Make sure user is trying to access user space */   /* Make sure user is trying to access user space */
   if (user_str < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(user_str, max_len) )
  
   /* Don't allow invalid max_len */ 
   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) ) 
     return -SOS_EINVAL; 
  
                                                 (sos_vaddr_t) && catch_pgflt);                                                 (sos_vaddr_t) && catch_pgflt);
   if (SOS_OK != retval)   if (SOS_OK != retval)
Line 252 
Line 335 
 sos_ret_t sos_strzcpy_from_user(char *kernel_to, sos_uaddr_t user_from, sos_ret_t sos_strzcpy_from_user(char *kernel_to, sos_uaddr_t user_from,
                                 sos_size_t max_len)                                 sos_size_t max_len)
 { {
    if (max_len <= 0)
      return -SOS_EINVAL;
  
   /* Make sure user is trying to access user space */   /* Make sure user is trying to access user space */
   if ((sos_uaddr_t)user_from < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(user_from, max_len) )
  
   /* Don't allow invalid max_len */   /* Make sure the copy totally resides inside kernel space */
   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )   if (! SOS_PAGING_IS_KERNEL_AREA((sos_vaddr_t)kernel_to, max_len) )
     return -SOS_EINVAL;     return -SOS_EPERM;
   return nocheck_user_strzcpy(kernel_to, (const char*)user_from, max_len);   return nocheck_user_strzcpy(kernel_to, (const char*)user_from, max_len);
 } }
Line 267 
Line 353 
 sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user_to, const char *kernel_from, sos_ret_t sos_strzcpy_to_user(sos_uaddr_t user_to, const char *kernel_from,
                               sos_size_t max_len)                               sos_size_t max_len)
 { {
   /* Make sure user is trying to access user space */   if (max_len <= 0)
   if ((sos_uaddr_t)user_to < SOS_PAGING_BASE_USER_ADDRESS)     return -SOS_EINVAL;
  
    /* Make sure the source totally resides inside kernel space */
    if (! SOS_PAGING_IS_KERNEL_AREA((sos_vaddr_t)kernel_from, max_len) )
  
   /* Don't allow invalid max_len */   /* Make sure user is trying to access user space */
   if ( (max_len < 1) || (max_len > SOS_PAGING_USER_SPACE_SIZE) )   if (! SOS_PAGING_IS_USER_AREA(user_to, max_len) )
     return -SOS_EINVAL;     return -SOS_EPERM;
   return nocheck_user_strzcpy((char*)user_to, kernel_from, max_len);   return nocheck_user_strzcpy((char*)user_to, kernel_from, max_len);
 } }
  
 

sos-code-article9.5.old/sos/uaccess.h (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/uaccess.h (2006-02-26 19:39:41.000000000 +0100 )
Line 27 
Line 27 
  
 #include <sos/types.h> #include <sos/types.h>
 #include <sos/errno.h> #include <sos/errno.h>
  #include <sos/umem_vmm.h>
 /** /**
  * Retrieve a bunch of data from the user space of the  * Retrieve a bunch of data from the user space of the
Line 55 
Line 55 
  
  
 /** /**
  * Transfer a bunch of data to the user space of the  * Transfer a bunch of data from kernel space into the user space of
  * current_thread->process  * the current_thread->process
  * @return <0 n error ! Return the number of bytes successfully copied  * @return <0 n error ! Return the number of bytes successfully copied
  * otherwise.  * otherwise.
Line 67 
Line 67 
  
  
 /** /**
   * Variant of sos_memcpy_from_user()
   * Retrieve a bunch of data from the user space of the given src_as
   * address space into kernel space
   *
   * @return NULL on error (including unresolved page fault during
   * transfer)
   *
   * @note src_as MUST NOT be NULL
   */
  sos_ret_t sos_memcpy_from_specified_userspace(sos_vaddr_t kernel_to,
                                                struct sos_umem_vmm_as * src_as,
                                                sos_uaddr_t user_from,
                                                sos_size_t size);
  
  
  /**
   * Variant of sos_memcpy_to_user()
   * Transfer a bunch of data from kernel space into the user space of
   * the given dst_as address space
   *
   * @return <0 n error ! Return the number of bytes successfully copied
   * otherwise.
   *
   * @note dst_as MUST NOT be NULL
   */
  sos_ret_t sos_memcpy_to_specified_userspace(struct sos_umem_vmm_as * dst_as,
                                              sos_uaddr_t user_to,
                                              sos_vaddr_t kernel_from,
                                              sos_size_t size);
  
  /**
   * Copy data from an user space into another
   * @return The number of bytes successfuly copied
   * @note dst_as and src_as may be NULL, in which case the current
   * thread->process address space is used for the copy
   */
  sos_ret_t sos_usercpy(struct sos_umem_vmm_as * dst_as,
                        sos_uaddr_t dst_uaddr,
                        struct sos_umem_vmm_as * src_as,
                        sos_uaddr_t src_uaddr,
                        sos_size_t size);
  
  
  /**
  * @return the length of the given user space string user_str  * @return the length of the given user space string user_str
  * (excluding the trailing \0), up to max_len bytes. <0 on error  * (excluding the trailing \0), up to max_len bytes. <0 on error
  * (unresolved page fault, etc.)  * (unresolved page fault, etc.)
  
 

sos-code-article9.5.old/sos/umem_vmm.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/umem_vmm.c (2006-02-26 19:39:41.000000000 +0100 )
Line 23 
Line 23 
 #include <drivers/bochs.h> #include <drivers/bochs.h>
 #include <hwcore/mm_context.h> #include <hwcore/mm_context.h>
 #include <hwcore/paging.h> #include <hwcore/paging.h>
  #include <hwcore/irq.h>
 #include <drivers/zero.h> #include <drivers/zero.h>
  
 #include "umem_vmm.h" #include "umem_vmm.h"
Line 230 
Line 231 
 } }
  
  
  static struct sos_umem_vmm_as * current_address_space = NULL;
  struct sos_umem_vmm_as * sos_umem_vmm_get_current_as(void)
  {
    return current_address_space;
  }
  
  
  sos_ret_t sos_umem_vmm_set_current_as(struct sos_umem_vmm_as * as)
  {
    sos_ui32_t flags;
    struct sos_umem_vmm_as *prev_as = current_address_space;
  
    if (current_address_space == as)
      return SOS_OK;
  
    if (NULL != as)
      {
        sos_disable_IRQs(flags);
        sos_process_ref(sos_umem_vmm_get_process(as));
        sos_mm_context_switch_to(sos_umem_vmm_get_mm_context(as));
        current_address_space = as;
        sos_restore_IRQs(flags);
      }
    else
      current_address_space = as;
  
    if (prev_as)
      sos_process_unref(sos_umem_vmm_get_process(prev_as));
  
    return SOS_OK;
  }
  
  
 struct sos_umem_vmm_as * struct sos_umem_vmm_as *
 sos_umem_vmm_create_empty_as(struct sos_process *owner) sos_umem_vmm_create_empty_as(struct sos_process *owner)
 { {
Line 252 
Line 286 
  
  
 struct sos_umem_vmm_as * struct sos_umem_vmm_as *
 sos_umem_vmm_duplicate_current_thread_as(struct sos_process *owner) sos_umem_vmm_duplicate_as(struct sos_umem_vmm_as * model_as,
                            struct sos_process *for_owner)
   __label__ undo_creation;   __label__ undo_creation;
   struct sos_umem_vmm_as * my_as; 
   int nb_vr;   int nb_vr;
  
Line 264 
Line 298 
   if (! new_as)   if (! new_as)
     return NULL;     return NULL;
  
   my_as = sos_process_get_address_space(sos_thread_get_current()->process);   new_as->process = for_owner;
   new_as->process = owner; 
  
   /*   /*
Line 274 
Line 307 
    * COW)    * COW)
    */    */
   SOS_ASSERT_FATAL(SOS_OK   SOS_ASSERT_FATAL(SOS_OK
                    == sos_thread_prepare_user_space_access(my_as,                    == sos_thread_prepare_user_space_access(model_as,
                                                              NULL));                                                              NULL));
  
   /* Copy the virtual regions */   /* Copy the virtual regions */
   list_foreach_named(my_as->list_vr, model_vr, nb_vr, prev_in_as, next_in_as)   list_foreach_named(model_as->list_vr, model_vr, nb_vr, prev_in_as, next_in_as)
       struct sos_umem_vmm_vr * vr;       struct sos_umem_vmm_vr * vr;
  
Line 315 
Line 348 
     }     }
  
   /* Now copy the current MMU configuration */   /* Now copy the current MMU configuration */
   new_as->mm_context = sos_mm_context_duplicate(my_as->mm_context);   new_as->mm_context = sos_mm_context_duplicate(model_as->mm_context);
     goto undo_creation;     goto undo_creation;
  
   /* Correct behavior */   /* Correct behavior */
   new_as->heap_start = my_as->heap_start;   new_as->heap_start = model_as->heap_start;
   new_as->heap_size  = my_as->heap_size;   new_as->heap_size  = model_as->heap_size;
   new_as->phys_total = my_as->phys_total;   new_as->phys_total = model_as->phys_total;
   memcpy(& new_as->vm_total, & my_as->vm_total, sizeof(struct vm_usage));   memcpy(& new_as->vm_total, & model_as->vm_total, sizeof(struct vm_usage));
   memcpy(& new_as->vm_shrd, & my_as->vm_shrd, sizeof(struct vm_usage));   memcpy(& new_as->vm_shrd, & model_as->vm_shrd, sizeof(struct vm_usage));
   return new_as;   return new_as;
  
Line 555 
Line 588 
        */        */
  
       /* Make sure the hint_uaddr hint is valid */       /* Make sure the hint_uaddr hint is valid */
       if (hint_uaddr < SOS_PAGING_BASE_USER_ADDRESS)       if (! SOS_PAGING_IS_USER_AREA(hint_uaddr, size) )
         { retval = -SOS_EINVAL; goto return_mmap; } 
       if (hint_uaddr > SOS_PAGING_TOP_USER_ADDRESS - size) 
  
       /* Unmap any overlapped VR */       /* Unmap any overlapped VR */
Line 712 
Line 743 
                    sos_uaddr_t uaddr, sos_size_t size)                    sos_uaddr_t uaddr, sos_size_t size)
 { {
   struct sos_umem_vmm_vr *vr, *preallocated_vr;   struct sos_umem_vmm_vr *vr, *preallocated_vr;
   sos_bool_t need_to_setup_mmu; 
    sos_bool_t need_to_change_address_space = FALSE;
  
   if (! SOS_IS_PAGE_ALIGNED(uaddr))   if (! SOS_IS_PAGE_ALIGNED(uaddr))
     return -SOS_EINVAL;     return -SOS_EINVAL;
Line 722 
Line 753 
   size = SOS_PAGE_ALIGN_SUP(size);   size = SOS_PAGE_ALIGN_SUP(size);
  
   /* Make sure the uaddr is valid */   /* Make sure the uaddr is valid */
   if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(uaddr, size) )
     return -SOS_EINVAL; 
   if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - size) 
  
   /* In some cases, the unmapping might imply a VR to be split into   /* In some cases, the unmapping might imply a VR to be split into
Line 875 
Line 904 
                               uaddr, size, vr->start, vr->size);                               uaddr, size, vr->start, vr->size);
     }     }
  
   need_to_setup_mmu = (sos_thread_get_current()->squatted_mm_context   /* When called from mresize, the address space is already squatted,
                        != as->mm_context);      so we don't have to change it again */
   if (need_to_setup_mmu)   need_to_change_address_space
      = (as != sos_thread_get_current()->squatted_address_space);
  
    if (need_to_change_address_space)
                      == sos_thread_prepare_user_space_access(as,                      == sos_thread_prepare_user_space_access(as,
                                                              (sos_vaddr_t)                                                              (sos_vaddr_t)
                                                                NULL));                                                              NULL));
  
  
    /* Begin independent sub-block */
     sos_ret_t sz_unmapped = sos_paging_unmap_interval(uaddr, size);     sos_ret_t sz_unmapped = sos_paging_unmap_interval(uaddr, size);
     SOS_ASSERT_FATAL(sz_unmapped >= 0);     SOS_ASSERT_FATAL(sz_unmapped >= 0);
     as->phys_total -= sz_unmapped;     as->phys_total -= sz_unmapped;
   }   }
   if (need_to_setup_mmu)   /* End independent sub-block */
  
    if (need_to_change_address_space)
  
   if (! used_preallocated_vr)   if (! used_preallocated_vr)
Line 913 
Line 950 
   size = SOS_PAGE_ALIGN_SUP(size);   size = SOS_PAGE_ALIGN_SUP(size);
  
   /* Make sure the uaddr is valid */   /* Make sure the uaddr is valid */
   if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(uaddr, size) )
     return -SOS_EINVAL; 
   if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - size) 
  
   /* Pre-allocate 2 new VRs (same reason as for unmap). Because chprot   /* Pre-allocate 2 new VRs (same reason as for unmap). Because chprot
Line 1224 
Line 1259 
   size = SOS_PAGE_ALIGN_SUP(size);   size = SOS_PAGE_ALIGN_SUP(size);
  
   /* Make sure the uaddr is valid */   /* Make sure the uaddr is valid */
   if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(uaddr, size) )
     return -SOS_EINVAL; 
   if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - size) 
  
   /* Go from page to page, and for each dirty page in the region, call   /* Go from page to page, and for each dirty page in the region, call
Line 1287 
Line 1320 
   struct sos_umem_vmm_vr *vr, *prev_vr, *next_vr;   struct sos_umem_vmm_vr *vr, *prev_vr, *next_vr;
  
   /* Make sure the new uaddr is valid */   /* Make sure the new uaddr is valid */
   if (*new_uaddr < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(*new_uaddr, new_size) )
     return -SOS_EINVAL; 
   if (*new_uaddr > SOS_PAGING_TOP_USER_ADDRESS - new_size) 
  
   old_uaddr = SOS_PAGE_ALIGN_INF(old_uaddr);   old_uaddr = SOS_PAGE_ALIGN_INF(old_uaddr);
Line 1347 
Line 1378 
     must_move_vr |= TRUE;     must_move_vr |= TRUE;
  
   /* If VR would be out-of-user-space, it must be moved */   /* If VR would be out-of-user-space, it must be moved */
   if (*new_uaddr < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(*new_uaddr, new_size) )
     must_move_vr |= TRUE; 
   if (*new_uaddr > SOS_PAGING_TOP_USER_ADDRESS - new_size) 
  
   /* The VR must be moved but the user forbids it */   /* The VR must be moved but the user forbids it */
Line 1464 
Line 1493 
                                               sos_bool_t write_access,                                               sos_bool_t write_access,
                                               sos_bool_t user_access)                                               sos_bool_t user_access)
 { {
   struct sos_process     *process = sos_thread_get_current()->process; 
   struct sos_umem_vmm_vr *vr;   struct sos_umem_vmm_vr *vr;
  
   if (! process)   as = current_address_space;
     return -SOS_EFAULT; 
  
   as = sos_process_get_address_space(process); 
     return -SOS_EFAULT;     return -SOS_EFAULT;
  
Line 1590 
Line 1615 
   struct sos_umem_vmm_vr *vr;   struct sos_umem_vmm_vr *vr;
   int nb_vr;   int nb_vr;
  
   if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)   if (! SOS_PAGING_IS_USER_AREA(uaddr, 1) )
     return NULL; 
   if (uaddr > SOS_PAGING_TOP_USER_ADDRESS) 
  
   list_foreach_named(as->list_vr, vr, nb_vr, prev_in_as, next_in_as)   list_foreach_named(as->list_vr, vr, nb_vr, prev_in_as, next_in_as)
  
 

sos-code-article9.5.old/sos/umem_vmm.h (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/sos/umem_vmm.h (2006-02-26 19:39:41.000000000 +0100 )
Line 285 
Line 285 
  
  
 /** /**
   * Get the current effective address space. This may be the "normal"
   * address space of the current thread, but not necessarilly: this
   * might be the address space of just another process ! This may
   * happen if a kernel thread of process P wants to access the address
   * space of another process P2. This might also be NULL (no access to
   * user space needed).
   */
  struct sos_umem_vmm_as * sos_umem_vmm_get_current_as(void);
  
  
  /**
   * Change the current effective address space, eventually
   * reconfiguring the MMU. This will increase the owning process's
   * reference count of the given AS, and decrease that of the previous
   * AS (when different).
   *
   * @param as may be NULL (no need to access user space)
   */
  sos_ret_t sos_umem_vmm_set_current_as(struct sos_umem_vmm_as * as);
  
  
  /**
  * Create a new, empty, address space  * Create a new, empty, address space
  *  *
  * @param owner The process that will own the new address space  * @param owner The process that will own the new address space
Line 297 
Line 319 
  
  
 /** /**
  * Create a new address space, copy of the current thread's address  * Create a new address space, copy of the model_as address
  * marked 'read-only' to activate the "copy-on-write" semantics.  * marked 'read-only' to activate the "copy-on-write" semantics.
  *  *
  * @param owner The process that will hold the new address space  * @param model_as The address space to copy
   * @param for_owner The process that will hold the new address space
  * @note automatically calls  * @note automatically calls
  * sos_thread_prepare_user_space_access()/sos_thread_end_user_space_access()  * sos_thread_prepare_user_space_access()/sos_thread_end_user_space_access()
  */  */
 struct sos_umem_vmm_as * struct sos_umem_vmm_as *
 sos_umem_vmm_duplicate_current_thread_as(struct sos_process *owner); sos_umem_vmm_duplicate_as(struct sos_umem_vmm_as * model_as,
                            struct sos_process *for_owner);
  
 /** /**
  
 

sos-code-article9.5.old/userland/crt_asm.S (1970-01-01 01:00:00.000000000 +0100 )
sos-code-article9.5/userland/crt_asm.S (2006-02-26 19:39:42.000000000 +0100 )
(New file) 
Line 1 
  /* Copyright (C) 2006  David Decotigny
  
     This program is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License
     as published by the Free Software Foundation; either version 2
     of the License, or (at your option) any later version.
  
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
  
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
     USA.
  */
  #define ASM_SOURCE 1
  
  .file "crt_asm.S"
  
  .text
  
  .extern _cmain
  
  /* User program entry point */
  .globl _start
          .type   _start, @function
  _start:
          pushl %esp
          call _cmain
          addl $4, %esp
  
          /* We should never reach this line */
          lcall 0 /* Crash the process */
  
 

sos-code-article9.5.old/userland/crt.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/userland/crt.c (2006-02-26 19:39:42.000000000 +0100 )
Line 27 
Line 27 
  
 #include <hwcore/swintr.h> #include <hwcore/swintr.h>
 #include <string.h> #include <string.h>
  
  #include "libc.h" /* putenv */
 #include "crt.h" #include "crt.h"
  
 /** /**
   * Macro used to retrieve the 2 parameters passed to any new thread
   * (architecture-dependent)
   */
  #define GET_THREAD_PARAMETERS(param1, param2) \
    asm volatile ("movl %%eax, %0 ; movl %%ebx, %1" \
                  : "=g"(param1), "=g"(param2) : : "%eax", "%ebx" )
  
  
  /**
   * Helper function to retrieve the arg array from the parameter area
   * sent by the parent.
   *
   * Format of the parent's args area:
   *   Number of arguments
   *   Offset of arg 0 (program's name)
   *   Offset of arg 1
   *   ...
   *   Offset of arg N (last argument)
   *   NULL
   *   Offset of environnement variable 0
   *   Offset of environnement variable 1
   *   ...
   *   Offset of environnement variable N
   *   NULL
   *   Contents of arg 0 with terminal \0
   *   Contents of arg 1 with terminal \0
   *   ...
   *   Contents of arg N with terminal \0
   *   Contents of env 0 with terminal \0
   *   Contents of env 1 with terminal \0
   *   ...
   *   Contents of env N with terminal \0
   *
   * This function simply transforms the N offsets into the real
   * addresses of the arg X contents (ie it simply adds the base address
   * of the area).
   */
  static void unmarshall_argv_envp(void * args,
                                   int * argc,
                                   const char ** * argv,
                                   const char ** * envp)
  {
    addr_t * offset = (addr_t*) args;
    *argc = 0;
    *argv = NULL;
  
    offset = args;
  
    /* Get argc */
    *argc = * (int*) offset;
    offset ++;
  
    /* Get base of argv */
    *argv = (const char **) offset;
  
    /* Walk the offsets array and transform these offsets into memory
       addresses */
    for ( ; 0 != *offset ; offset ++)
      *offset += (addr_t) args;
  
    /* Skip the NULL separating argv from envp */
    offset ++;
  
    /* Get base of envp */
    *envp = (const char **) offset;
  
    /* Walk the offsets array and transform these offsets into memory
       addresses */
    for ( ; 0 != *offset ; offset ++)
      {
        *offset += (addr_t) args;
  
        /* Register this environment variable */
        putenv((char*) *offset);
      }
  }
  
  
  /**
  * Starter function !  * Starter function !
  */  */
 void _start(void) __attribute__((noreturn)); /** Function called by crt_asm.S:_start to start user program */
 void _start(void) void _cmain(const char* arg_env_area[]) __attribute__((noreturn));
  void _cmain(const char* arg_env_area[])
  
    /* Will hold the parameters that will be passed to main */
    const char** argv;
    const char** envp;
    int argc;
  
  
   /* This starter function expects a main() function somewhere */   /* This starter function expects a main() function somewhere */
   extern int main(void);   extern int main(int argc, char const* argv[],
                    char const* envp[]);
   /* Reset the bss section */   /* Setup the arguments list and the environment variables */
   extern char _bbss, _ebss;   unmarshall_argv_envp (arg_env_area, & argc, & argv, & envp);
   memset(& _bbss, 0x0, (& _ebss) - (& _bbss)); 
   _sos_exit(main());   _sos_exit(main(argc, argv, envp));
  
  
Line 189 
Line 278 
 } }
  
  
 int _sos_exec(const char * prog) int _sos_exec(const char * prog,
 {               void const* args,
   return _sos_syscall2(SOS_SYSCALL_ID_EXEC, (unsigned int)prog,               size_t arglen)
                        (unsigned int)strlen(prog)); {
    return _sos_syscall4(SOS_SYSCALL_ID_EXEC, (unsigned int)prog,
                         (unsigned int)strlen(prog),
                         (unsigned int)args,
                         (unsigned int)arglen);
  
  
Line 244 
Line 337 
  */  */
 static void thread_routine(void) static void thread_routine(void)
 { {
   /* NOTE: variables as named registers is a gcc extension */   sos_thread_func_t * func;
   register unsigned long int reg_arg1 asm("%eax");   unsigned long int arg;
   register unsigned long int reg_arg2 asm("%ebx"); 
   sos_thread_func_t * func = (sos_thread_func_t*)reg_arg1;   GET_THREAD_PARAMETERS(func, arg);
   unsigned long int arg = reg_arg2; 
   func(arg);   func(arg);
   _sos_exit(0);   _sos_exit(0);
  
 

sos-code-article9.5.old/userland/crt.h (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/userland/crt.h (2006-02-26 19:39:42.000000000 +0100 )
Line 114 
Line 114 
 /** /**
  * Syscall to re-initialize the address space of the current process  * Syscall to re-initialize the address space of the current process
  * with that of the program 'progname'  * with that of the program 'progname'
  */  *
 int _sos_exec(const char * prog);  * The args argument is the address of an array that contains the
   * arguments and environnement variables for the new process.
   */
  int _sos_exec(const char * prog,
                void const* args,
                size_t arglen);
  
 /** /**
  
 

sos-code-article9.5.old/userland/envtest.c (1970-01-01 01:00:00.000000000 +0100 )
sos-code-article9.5/userland/envtest.c (2006-02-26 19:39:42.000000000 +0100 )
(New file) 
Line 1 
  #include <libc.h>
  
  int main(int argc, char * argv[], char *envp[])
  {
    int i;
    char **e;
  
    printf("Nargs: %d\n", argc);
    for (i = 0 ; i < argc ; i ++)
      printf("  arg[%d] = |%s|\n", i, argv[i]);
  
    for (e = envp ; e && *e ; e ++)
      printf("  ENV |%s|\n", *e);
  
    return 0;
  }
  
 

sos-code-article9.5.old/userland/fstest.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/userland/fstest.c (2006-02-26 19:39:42.000000000 +0100 )
Line 24 
Line 24 
  
 #include "fstest_utils.h" #include "fstest_utils.h"
  
 #define OPEN_BASE_FD 3 static const int OPEN_BASE_FD = 3;
 /** /**
  * @file fstest.c  * @file fstest.c
  
 

sos-code-article9.5.old/userland/ldscript.lds (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/userland/ldscript.lds (2006-02-26 19:39:42.000000000 +0100 )
Line 56 
Line 56 
     }     }
  
     /* Beginning of the BSS section (global uninitialized data) */     /* Beginning of the BSS section (global uninitialized data) */
     .bss SIZEOF(.rodata) + ADDR(.rodata) :     .bss ALIGN(SIZEOF(.rodata) + ADDR(.rodata), 4096) :
         PROVIDE(_bbss = .);         PROVIDE(_bbss = .);
         *(.bss)         *(.bss)
  
 

sos-code-article9.5.old/userland/libc.c (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/userland/libc.c (2006-02-26 19:39:42.000000000 +0100 )
Line 34 
Line 34 
 } }
  
  
 int exec(const char *progname) /**
   * Helper to transform the array of argv and envp into an area
   * suitable for the crt.c:unmarshall_argv_envp() function.
   * @see crt.c for the format of this array.
   */
  static void const* marshall_execve_parameters(char* const argv[],
                                                char* const envp[],
                                               /*out*/size_t * sz)
  {
    size_t i, i_offset, count_argv, count_envp, size;
    char * str;
    void * result;
    addr_t * offset;
  
    *sz = 0;
  
    /* Count the number of argv parameters and the size to allocate */
    for (count_argv = 0, size = 0 ; argv && argv[count_argv] != NULL ; count_argv ++)
      size += strlen(argv[count_argv]) + 1 /* trailing \0 */;
  
    /* Count the number of envp parameters and the size to allocate */
    for (count_envp = 0 ; envp && envp[count_envp] != NULL ; count_envp ++)
      size += strlen(envp[count_envp]) + 1 /* trailing \0 */;
  
    size += (count_argv + count_envp + 3) * sizeof(addr_t);
    result = malloc(size);
    if (NULL == result)
      return NULL;
  
    /* Build the array of offsets and the string contents */
    offset   = (addr_t*)result;
    str      = (char*) & offset[count_argv + count_envp + 3];
    i_offset = 0;
  
    /* First element of the array is the number of argv entries */
    offset [i_offset++] = count_argv;
  
    /* Marshall the argv array */
    for (i = 0 ; i < count_argv ; i ++, i_offset ++)
      {
        char const* c;
  
        offset[i_offset] = (void*)str - result;
  
        for (c = argv[i] ; *c ; c ++, str ++)
          *str = *c;
        *str = '\0'; str ++;
      }
  
    /* The NULL between argv and envp */
    offset [i_offset++] = 0;
  
    for (i = 0 ; i < count_envp ; i ++, i_offset ++)
      {
        char const* c;
  
        offset[i_offset] = (void*)str - result;
  
        for (c = envp[i] ; *c ; c ++, str ++)
          *str = *c;
        *str = '\0'; str ++;
      }
  
    /* Final NULL */
    offset[count_argv + count_envp + 2] = 0;
    *sz = size;
  
    return result;
  }
  
  
  int execve(const  char  *filename,
             char  *const argv [],
             char *const envp[])
   return _sos_exec(progname);   void const* args_area;
    size_t args_sz;
    int retval;
  
    args_area = marshall_execve_parameters(argv, envp, & args_sz);
  
    retval = _sos_exec(filename,
                       args_area, args_sz);
  
    if (NULL != args_area)
      free((void*)args_area);
  
    return retval;
  }
  
  
  int execv(const char  * filename,
            char  * const argv [])
  {
    return execve(filename, argv, environ);
  }
  
  
  static int compute_nargs(va_list ap)
  {
    int nargs = 0;
    while (va_arg(ap, char*))
      nargs ++;
    return nargs;
  }
  
  
  static int vexec(const  char  *path, va_list ap, int envp_in_list)
  {
    int retval;
    char ** vector, **entry;
    char *str;
    char ** envp;
  
    size_t nargs = compute_nargs(ap);
  
    /* Allocate the char* vector */
    vector = malloc((nargs + 1)*sizeof(char*));
    if (! vector)
      return -1;
  
    /* Fill it */
    entry = vector;
    while ((str = va_arg(ap, char*)) != NULL)
      {
        *entry = str;
        entry ++;
      }
    *entry = NULL;
  
    if (envp_in_list)
      envp = (char**)va_arg(ap, char*);
    else
      envp = environ;
  
    retval = execve(path, vector, envp);
    free(vector);
    return retval;
  }
  
  
  int  execl(const  char  *path, ...)
  {
    int retval;
    va_list ap;
    va_start(ap, path);
    retval = vexec(path, ap, FALSE);
    va_end(ap);
    return retval;
  }
  
  
  int  execle(const  char  *path, ...)
  {
    int retval;
    va_list ap;
    va_start(ap, path);
    retval = vexec(path, ap, TRUE);
    va_end(ap);
    return retval;
  }
  
  
  int exec(char  * const filename)
  {
    return execl(filename, filename, NULL);
  
  
Line 53 
Line 216 
 } }
  
  
  /**
   * Max number of environment variables
   */
  #define SOS_MAX_ENVVARS 1024
  
  char **environ = NULL;
  
  
  /**
   * Compare the keys of two strings of the form "key=val"
   */
  static int equal_key(const char *e1,
                       const char *e2)
  {
    for ( ; e1 && (*e1) && e2 && (*e2) && (*e1 == *e2) ; e1++, e2++)
      if (*e1 == '=')
        return TRUE;
  
    return FALSE;
  }
  
  
  /**
   * Helper function to register an environment variable
   */
  static int registerenv(char * string, int can_overwrite)
  {
    int i;
    char ** overwritten;
  
    /* The first time: allocate the environ table */
    if (! environ)
      {
        environ = malloc(SOS_MAX_ENVVARS * sizeof(char*));
        if (! environ)
          return 0;
  
        memset(environ, 0x0, SOS_MAX_ENVVARS * sizeof(char*));
      }
  
    /* Walk the environment variables */
    overwritten = NULL;
    for (i = 0 ; i < SOS_MAX_ENVVARS ; i ++)
      {
        /* Reached end of list ? */
        if (! environ[i])
          break;
  
        /* Variable already present ? */
        if (equal_key(environ[i], string))
          overwritten = & environ[i];
      }
  
    if (overwritten)
      {
        /* Not allowed to overwrite it ! */
        if (! can_overwrite)
          return -1;
  
        /* Overwrite allowed: do it now */
        free(*overwritten);
        *overwritten = string;
        return 0;
      }
  
    /* Must add the variable */
  
    /* No place left ? */
    if (i >= SOS_MAX_ENVVARS)
      return -1;
  
    /* Ok, add it at the end */
    environ[i] = string;
    return 0;
  }
  
  
  /**
   * @return TRUE when the key of the "keyvalpair" pair is "key"
   */
  static int key_is(char * keyvalpair, const char * key,
                    char ** /*out*/value)
  {
    for ( ; keyvalpair && *keyvalpair && key && *key ; keyvalpair ++, key ++)
      if (*key != *keyvalpair)
        break;
  
    if (value)
      *value = keyvalpair + 1;
  
    return (keyvalpair && (*keyvalpair == '=') && key && (*key == '\0'));
  }
  
  
  int putenv(char * string)
  {
    char * str;
    if (! string)
      return -1;
  
    str = strdup(string);
    if (! str)
      return -1;
  
    return registerenv(string, TRUE);
  }
  
  
  int setenv(const char *name, const char *value, int overwrite)
  {
    char * str, * c;
    size_t sz_name, sz_value;
  
    if (!name || !value)
      return -1;
  
    /* Allocate space for the "name=value" string */
    sz_name = strlen(name);
    sz_value = strlen(value);
    str = malloc(sz_name + 1 + sz_value + 1);
    if (! str)
      return -1;
  
    /* sprintf(str, "%s=%s", name, value); */
    c = str;
    *c = '\0';
    strzcpy(c, name, sz_name+1); c += sz_name;
    strzcpy(c, "=", 2); c += 1;
    strzcpy(c, value, sz_value+1);
  
    return registerenv(str, overwrite);
  }
  
  
  char *getenv(const char *name)
  {
    int i;
  
    if (! environ)
      return NULL;
  
    for (i = 0 ; i < SOS_MAX_ENVVARS ; i ++)
      {
        char *value;
  
        /* Reached end of list ? */
        if (! environ[i])
          return NULL;
  
        /* Variable already present ? */
        if (key_is(environ[i], name, & value))
          return value;
      }
  
    return NULL;
  }
  
  
  void unsetenv(const char *name)
  {
    int i;
    char ** entry, ** last_entry;
  
    if (! environ)
      return;
  
    /* Walk the environment variables */
    entry = last_entry = NULL;
    for (i = 0 ; i < SOS_MAX_ENVVARS ; i ++)
      {
        /* Reached end of list ? */
        if (! environ[i])
          break;
  
        /* Variable already present ? */
        if (key_is(environ[i], name, NULL))
          entry = & environ[i];
        else if (entry)
          last_entry = & environ[i];
      }
  
    /* Found nothing ! */
    if (! entry)
      return;
  
    /* Found it: erase it... */
    free(*entry);
    *entry = NULL;
  
    /* ... and replace it with the last entry */
    if (last_entry)
      {
        *entry = *last_entry;
        *last_entry = NULL;
      }
  }
  
  
  int clearenv(void)
  {
    int i;
  
    if (! environ)
      return 0;
  
    for (i = 0 ; i < SOS_MAX_ENVVARS ; i ++)
      {
        if (! environ[i])
          break;
  
        free(environ[i]);
        environ[i] = NULL;
      }
  
    return 0;
  }
  
  
  
 int munmap(void * start, size_t length) int munmap(void * start, size_t length)
 { {
  
 

sos-code-article9.5.old/userland/libc.h (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/userland/libc.h (2006-02-26 19:39:42.000000000 +0100 )
Line 43 
Line 43 
  * Function to re-initialize the address space of the current process  * Function to re-initialize the address space of the current process
  * with that of the program 'progname'  * with that of the program 'progname'
  */  */
 int exec(const char *progname); int execve(const  char  *filename,
             char  *const argv [],
             char *const envp[]);
  int execv(const char  * filename,
            char  * const argv []);
  int execl(const  char  *path, ...);
  int execle(const  char  *path, ...);
  
  
  /**
   * Equivalent to execl(filename, filename);
   */
  int exec(char * const filename);
  
 int nanosleep(unsigned long int sec, int nanosleep(unsigned long int sec,
Line 54 
Line 66 
  
  
 /** /**
   * Environment variables management API
   */
  extern char **environ; /** Needed by execl */
  
  int putenv(char * string);
  int setenv(const char *name, const char *value, int overwrite);
  char *getenv(const char *name);
  void unsetenv(const char *name);
  int clearenv(void);
  
  
  /**
  * These flags (for mmap API) MUST be consistent with those defined in  * These flags (for mmap API) MUST be consistent with those defined in
  * paging.h and umem_vmm.h  * paging.h and umem_vmm.h
  */  */
  
 

sos-code-article9.5.old/userland/Makefile (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/userland/Makefile (2006-02-26 19:39:42.000000000 +0100 )
Line 29 
Line 29 
  
 -include .mkvars -include .mkvars
  
 PROGS := init myprog1 myprog2 myprog3 myprog4 myprog5 myprog6 \ PROGS := init myprog1 myprog2 myprog3 myprog4 myprog5 myprog6           \
          myprog7 myprog8 myprog9 myprog10 myprog11 myprog12   \          envtest myprog7 myprog8 myprog9 myprog10 myprog11 myprog12     \
  
 # Build dependencies of the programs # Build dependencies of the programs
Line 39 
Line 39 
 chartest: fstest_utils.o chartest: fstest_utils.o
 blktest: fstest_utils.o blktest: fstest_utils.o
 shell: fstest_utils.o shell: fstest_utils.o
 $(PROGS) : % : %.o crt.o libc.a $(PROGS) : % : %.o crt.o crt_asm.o libc.a
 PWD := $(shell pwd | sed 's/"/\\\"/g;s/\$$/\\\$$/g') PWD := $(shell pwd | sed 's/"/\\\"/g;s/\$$/\\\$$/g')
  
  
 

sos-code-article9.5.old/userland/shell.c (2006-01-22 12:48:31.000000000 +0100 )
sos-code-article9.5/userland/shell.c (2006-02-26 19:39:42.000000000 +0100 )
Line 303 
Line 303 
       printf("Could not fork (%d)\n", retval);       printf("Could not fork (%d)\n", retval);
       return -1;       return -1;
     }     }
   retval = exec(argv[1]);   {
      retval = execv(argv[1], & argv[1]);
    }
    exit(0);
   return 0;   return 0;
 } }
  
Line 605 
Line 608 
   char **argv;   char **argv;
  
   for (c = cmd; *c != '\0'; c++)   for (c = cmd; *c != '\0'; c++)
     if (*c == ' ')     {
       argc++;       if (*c == ' ')
          {
            /* Skip all spaces */
            while (*c && *c == ' ')
              c++;
  
            /* Reached the end of the command line ? */
            if (! *c)
              break;
   argv = malloc (argc * sizeof(char*));           argc++;
          }
      }
  
    argv = malloc ((argc+1) * sizeof(char*));
    argv[argc] = NULL; /* To be compatible with execv(e) */
     return;     return;
  
Line 619 
Line 635 
         c++;         c++;
       *c = '\0';       *c = '\0';
       c++;       c++;
        /* Skip spaces */
        while (*c && *c == ' ')
          c++;
     }     }
  
   if (! strcmp (argv[0], "uname"))   if (! strcmp (argv[0], "uname"))
Line 676 
Line 695 
     {     {
       shell_partdump (argc, argv);       shell_partdump (argc, argv);
     }     }
    else if (! strcmp(argv[0], "getenv"))
      {
        if (argc > 1)
          printf("%s\n", getenv(argv[1]));
        else
          printf("Variable name missing\n");
      }
    else if (! strcmp(argv[0], "setenv"))
      {
        if (argc > 2)
          printf("retval=%d\n",
                 setenv(argv[1], argv[2], TRUE));
        else
          printf("Variable name/value missing\n");
      }
    else if (! strcmp(argv[0], "unsetenv"))
      {
        if (argc > 1)
          unsetenv(argv[1]);
        else
          printf("Variable name missing\n");
      }
     printf ("Command not found\n");     printf ("Command not found\n");
  
  
 

sos-code-article9.5.old/userland/string.c (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/userland/string.c (2006-02-26 19:39:42.000000000 +0100 )
Line 18 
Line 18 
    USA.     USA. 
 */ */
 #include "string.h" #include "string.h"
  #include "libc.h"
  
 /* For an optimized version, see BSD sources ;) */ /* For an optimized version, see BSD sources ;) */
 void *memcpy(void *dst0, const void *src0, register unsigned int size) void *memcpy(void *dst0, const void *src0, register unsigned int size)
Line 115 
Line 116 
   return res;   return res;
 } }
  
  
  char *strndup(const char *s, size_t n)
  {
    char * result;
    n = strnlen(s, n);
    result = malloc(n+1);
    if (! result)
      return NULL;
  
    strzcpy(result, s, n+1);
    return result;
  }
  
  
  char *strdup(const char *s)
  {
    char * result;
    size_t n = strlen(s);
  
    result = malloc(n+1);
    if (! result)
      return NULL;
  
    strzcpy(result, s, n+1);
    return result;
  }
  
  
 int strcmp(register const char *s1, register const char *s2) int strcmp(register const char *s1, register const char *s2)
 { {
   while (*s1 == *s2++)   while (*s1 == *s2++)
Line 208 
Line 237 
 { {
   return strtol(nptr, NULL, 10);   return strtol(nptr, NULL, 10);
 } }
  
  
 

sos-code-article9.5.old/userland/string.h (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/userland/string.h (2006-02-26 19:39:42.000000000 +0100 )
Line 53 
Line 53 
  */  */
 char *strzcat (char *dest, const char *src, char *strzcat (char *dest, const char *src,
                const size_t len);                const size_t len);
  
  char *strndup(const char *s, size_t n);
  char *strdup(const char *s);
    
 int strcmp(register const char *s1, register const char *s2 ); int strcmp(register const char *s1, register const char *s2 );
 int strncmp(register const char *s1, register const char *s2, int strncmp(register const char *s1, register const char *s2,
             register int len );             register int len );
  
  
 #define isupper(c)  (('A' <= (c)) && ((c) <= 'Z')) #define isupper(c)  (('A' <= (c)) && ((c) <= 'Z'))
 #define isdigit(c)  (('0' <= (c)) && ((c) <= '9')) #define isdigit(c)  (('0' <= (c)) && ((c) <= '9'))
Line 72 
Line 74 
 long long atoll(const char *nptr); long long atoll(const char *nptr);
 long atol(const char *nptr); long atol(const char *nptr);
  
  
  
 

sos-code-article9.5.old/userland/types.h (2006-01-22 12:48:32.000000000 +0100 )
sos-code-article9.5/userland/types.h (2006-02-26 19:39:42.000000000 +0100 )
Line 25 
Line 25 
  
 typedef unsigned int size_t; typedef unsigned int size_t;
  
 typedef int pid_t; typedef unsigned int addr_t;
  typedef int pid_t;
 typedef signed long int off_t; typedef signed long int off_t;
 typedef signed long long int loff_t; typedef signed long long int loff_t;
  


Legend:
 
identical lines
Removed from old 
changed lines
 Added in new

File list:
    
sos-code-article9.5/drivers/mem.c
    sos-code-article9.5/extra/bootsect.S
    sos-code-article9.5/hwcore/paging.c
    sos-code-article9.5/hwcore/paging.h
    sos-code-article9.5/INSTALL
    sos-code-article9.5/sos/binfmt_elf32.c
    sos-code-article9.5/sos/main.c
    sos-code-article9.5/sos/process.c
    sos-code-article9.5/sos/syscall.c
    sos-code-article9.5/sos/syscall.h
    sos-code-article9.5/sos/thread.c
    sos-code-article9.5/sos/thread.h
    sos-code-article9.5/sos/uaccess.c
    sos-code-article9.5/sos/uaccess.h
    sos-code-article9.5/sos/umem_vmm.c
    sos-code-article9.5/sos/umem_vmm.h
    sos-code-article9.5/userland/crt_asm.S
    sos-code-article9.5/userland/crt.c
    sos-code-article9.5/userland/crt.h
    sos-code-article9.5/userland/envtest.c
    sos-code-article9.5/userland/fstest.c
    sos-code-article9.5/userland/ldscript.lds
    sos-code-article9.5/userland/libc.c
    sos-code-article9.5/userland/libc.h
    sos-code-article9.5/userland/Makefile
    sos-code-article9.5/userland/shell.c
    sos-code-article9.5/userland/string.c
    sos-code-article9.5/userland/string.h
    sos-code-article9.5/userland/types.h