break: zero space on allocation rather than doing it all on exec
authorAlan Cox <alan@linux.intel.com>
Thu, 4 Jun 2015 17:17:39 +0000 (18:17 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 4 Jun 2015 17:17:39 +0000 (18:17 +0100)
Allows the fast fork() handling to work correctly, and fixes the behaviour
of a negative sbrk, followed by a positive one failing to clear the space.

Tidy up the types involved.

Kernel/include/kernel.h
Kernel/syscall_exec16.c
Kernel/syscall_proc.c

index 4220b58..d3b1d5b 100644 (file)
@@ -369,7 +369,7 @@ typedef struct u_data {
     uint16_t    u_page2;        /* Process page data (equal to u_ptab->p_page2) */
     bool        u_insys;        /* True if in kernel */
     uint8_t     u_callno;       /* sys call being executed. */
-    void *      u_syscall_sp;   /* Stores SP when process makes system call */
+    uaddr_t     u_syscall_sp;   /* Stores SP when process makes system call */
     susize_t    u_retval;       /* Return value from sys call */
     int16_t     u_error;        /* Last error number */
     void *      u_sp;           /* Stores SP when process is switchped */
index 6575c15..cdb046c 100644 (file)
@@ -194,9 +194,9 @@ arg_t _execve(void)
                progptr += bin_size;
        }
 
-       /* Should be smarter on the uzero: bank align the clearance */
-       // zero all remaining process memory above the last block loaded.
-       uzero((uint8_t *)progptr, top - progptr);
+       /* Wipe the memory in the BSS. We don't wipe the memory above
+          that on 8bit boxes, but defer it to brk/sbrk() */
+       uzero((uint8_t *)progptr, progptr + bss);
 
        udata.u_break = (int) progptr + bss;    //  Set initial break for program
 
index 307a59e..418fa1a 100644 (file)
@@ -213,21 +213,29 @@ arg_t _times(void)
 brk (addr)                       Function 30
 char *addr;
 ********************************************/
-#define addr (char *)udata.u_argn
+#define addr (uaddr_t)udata.u_argn
 
 arg_t _brk(void)
 {
-       /* FIXME: when we start building binaries with the stack embedded in them
-          they will need a different test.. */
-       /* Don't allow break to be set past user's stack pointer */
-    /*** St. Nitschke allow min. of 512 bytes for Stack ***/
-       if (addr >= (char *) brk_limit()) {
+       /* Don't allow break to be set outside of the range the platform
+          permits. For most platforms this is within 512 bytes of the
+          stack pointer
+
+          FIXME: if we get more complex mapping rule types then we may
+          need to make this something like  if (brk_valid(addr)) so we
+          can keep it portable */
+
+       if (addr >= brk_limit()) {
                kprintf("%d: out of memory\n", udata.u_ptab->p_pid);
                udata.u_error = ENOMEM;
-               return (-1);
+               return -1;
        }
-       udata.u_break = (uaddr_t) addr;
-       return (0);
+       /* If we have done a break that gives us more room we must zero
+          the extra as we no longer guarantee it is clear already */
+       if (addr > udata.u_break)
+               uzero(udata.u_break, addr - udata.u_break);
+       udata.u_break = addr;
+       return 0;
 }
 
 #undef addr