static void sys_brk(TrapFrame *tf) { tf->eax = 0; #ifdef IA32_PAGE if (tf->ebx) { mm_brk(tf->ebx); } else { tf->eax = mm_brk(0); } #endif printk("brk(0x%08x) = 0x%08x\n", tf->ebx, tf->eax); }
// do_brk - adjust(increase/decrease) the size of process heap, align with page size // NOTE: will change the process vma int do_brk(uintptr_t *brk_store) { struct mm_struct *mm = current->mm; if (mm == NULL) { panic("kernel thread call sys_brk!!.\n"); } if (brk_store == NULL) { return -E_INVAL; } uintptr_t brk; lock_mm(mm); if (!copy_from_user(mm, &brk, brk_store, sizeof(uintptr_t), 1)) { unlock_mm(mm); return -E_INVAL; } if (brk < mm->brk_start) { goto out_unlock; } uintptr_t newbrk = ROUNDUP(brk, PGSIZE), oldbrk = mm->brk; assert(oldbrk % PGSIZE == 0); if (newbrk == oldbrk) { goto out_unlock; } if (newbrk < oldbrk) { if (mm_unmap(mm, newbrk, oldbrk - newbrk) != 0) { goto out_unlock; } } else { if (find_vma_intersection(mm, oldbrk, newbrk + PGSIZE) != NULL) { goto out_unlock; } if (mm_brk(mm, oldbrk, newbrk - oldbrk) != 0) { goto out_unlock; } } mm->brk = newbrk; out_unlock: copy_to_user (mm, brk_store, &mm->brk, sizeof (uintptr_t)); unlock_mm(mm); return 0; }
/* poring from linux */ int do_linux_brk(uintptr_t brk) { uint32_t newbrk, oldbrk, retval; struct mm_struct *mm = current->mm; uint32_t min_brk; if (!mm) { panic("kernel thread call sys_brk!!.\n"); } lock_mm(mm); min_brk = mm->brk_start; if (brk < min_brk) goto out_unlock; newbrk = ROUNDUP(brk, PGSIZE); oldbrk = ROUNDUP(mm->brk, PGSIZE); if (oldbrk == newbrk) goto set_brk; if (brk <= mm->brk) { if (!mm_unmap(mm, newbrk, oldbrk - newbrk)) goto set_brk; goto out_unlock; } if (find_vma_intersection(mm, oldbrk, newbrk + PGSIZE)) goto out_unlock; /* set the brk */ if (mm_brk(mm, oldbrk, newbrk - oldbrk)) goto out_unlock; set_brk: mm->brk = brk; out_unlock: retval = mm->brk; unlock_mm(mm); return retval; }
/* from x86 bionic porting */ int do_linux_brk(uintptr_t brk) { struct mm_struct *mm = current->mm; if (mm == NULL) { panic("kernel thread call sys_brk!!.\n"); } if (brk == 0) { return mm->brk_start; } lock_mm(mm); if (brk < mm->brk_start) { goto out_unlock; } uintptr_t newbrk = ROUNDUP(brk, PGSIZE), oldbrk = mm->brk; assert(oldbrk % PGSIZE == 0); if (newbrk == oldbrk) { goto out_unlock; } if (newbrk < oldbrk) { if (mm_unmap(mm, newbrk, oldbrk - newbrk) != 0) { goto out_unlock; } } else { if (find_vma_intersection(mm, oldbrk, newbrk + PGSIZE) != NULL) { goto out_unlock; } if (mm_brk(mm, oldbrk, newbrk - oldbrk) != 0) { goto out_unlock; } } mm->brk = newbrk; out_unlock: unlock_mm(mm); return newbrk; }
static void sys_brk(TrapFrame *tf) { #ifdef IA32_PAGE mm_brk(tf->ebx); #endif tf->eax = 0; }