| [1] | 1 | /* | 
|---|
|  | 2 | * kern/sys_madvise.c - process memory management related advises | 
|---|
|  | 3 | * | 
|---|
|  | 4 | * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless | 
|---|
|  | 5 | * Copyright (c) 2011,2012 UPMC Sorbonne Universites | 
|---|
|  | 6 | * | 
|---|
|  | 7 | * This file is part of ALMOS-kernel. | 
|---|
|  | 8 | * | 
|---|
|  | 9 | * ALMOS-kernel is free software; you can redistribute it and/or modify it | 
|---|
|  | 10 | * under the terms of the GNU General Public License as published by | 
|---|
|  | 11 | * the Free Software Foundation; version 2.0 of the License. | 
|---|
|  | 12 | * | 
|---|
|  | 13 | * ALMOS-kernel is distributed in the hope that it will be useful, but | 
|---|
|  | 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
|  | 16 | * General Public License for more details. | 
|---|
|  | 17 | * | 
|---|
|  | 18 | * You should have received a copy of the GNU General Public License | 
|---|
|  | 19 | * along with ALMOS-kernel; if not, write to the Free Software Foundation, | 
|---|
|  | 20 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
|  | 21 | */ | 
|---|
|  | 22 |  | 
|---|
|  | 23 | #include <types.h> | 
|---|
|  | 24 | #include <errno.h> | 
|---|
|  | 25 | #include <bits.h> | 
|---|
|  | 26 | #include <vmm.h> | 
|---|
|  | 27 | #include <thread.h> | 
|---|
|  | 28 | #include <task.h> | 
|---|
|  | 29 | #include <cluster.h> | 
|---|
|  | 30 | #include <page.h> | 
|---|
|  | 31 | #include <ppm.h> | 
|---|
|  | 32 | #include <pmm.h> | 
|---|
|  | 33 |  | 
|---|
|  | 34 | /* TODO: don't use locks to lookup region as if address has been accessed it must be in kyesdb */ | 
|---|
|  | 35 | static error_t check_args(struct vmm_s *vmm, uint_t start, uint_t len, struct vm_region_s **reg) | 
|---|
|  | 36 | { | 
|---|
|  | 37 | error_t err; | 
|---|
|  | 38 | struct vm_region_s *region; | 
|---|
|  | 39 |  | 
|---|
|  | 40 | err = 0; | 
|---|
|  | 41 | rwlock_rdlock(&vmm->rwlock); | 
|---|
|  | 42 |  | 
|---|
|  | 43 | region = vmm->last_region; | 
|---|
|  | 44 |  | 
|---|
|  | 45 | if((start >= region->vm_limit) || (start < region->vm_start)) | 
|---|
|  | 46 | { | 
|---|
|  | 47 | region = vm_region_find(vmm, start); | 
|---|
|  | 48 |  | 
|---|
|  | 49 | if((region == NULL) || (start < region->vm_start)) | 
|---|
|  | 50 | err = EINVAL; | 
|---|
|  | 51 | } | 
|---|
|  | 52 |  | 
|---|
|  | 53 | if((err == 0) && ((start + len) >= region->vm_limit)) | 
|---|
|  | 54 | err = EINVAL; | 
|---|
|  | 55 |  | 
|---|
|  | 56 | rwlock_unlock(&vmm->rwlock); | 
|---|
|  | 57 |  | 
|---|
|  | 58 | *reg = region; | 
|---|
|  | 59 | return 0; | 
|---|
|  | 60 | } | 
|---|
|  | 61 |  | 
|---|
|  | 62 |  | 
|---|
|  | 63 | /* TODO: compute other advices */ | 
|---|
|  | 64 | int sys_madvise(void *start, size_t length, uint_t advice) | 
|---|
|  | 65 | { | 
|---|
|  | 66 | error_t err; | 
|---|
|  | 67 | struct vmm_s *vmm; | 
|---|
|  | 68 | struct vm_region_s *region; | 
|---|
|  | 69 | struct thread_s *this; | 
|---|
|  | 70 |  | 
|---|
|  | 71 | err = 0; | 
|---|
|  | 72 | this = current_thread; | 
|---|
|  | 73 |  | 
|---|
|  | 74 | if((start == NULL) || ((uint_t)start & PMM_PAGE_MASK)) | 
|---|
|  | 75 | { | 
|---|
|  | 76 | err = EINVAL; | 
|---|
|  | 77 | goto SYS_MADVISE_ERR; | 
|---|
|  | 78 | } | 
|---|
|  | 79 |  | 
|---|
|  | 80 | if(NOT_IN_USPACE((uint_t)start + length)) | 
|---|
|  | 81 | { | 
|---|
|  | 82 | err = EPERM; | 
|---|
|  | 83 | goto SYS_MADVISE_ERR; | 
|---|
|  | 84 | } | 
|---|
|  | 85 |  | 
|---|
|  | 86 | vmm = &this->task->vmm; | 
|---|
|  | 87 | err = check_args(vmm, (uint_t)start, length, ®ion); | 
|---|
|  | 88 |  | 
|---|
|  | 89 | if(err) goto SYS_MADVISE_ERR; | 
|---|
|  | 90 |  | 
|---|
|  | 91 | if((region->vm_flags & VM_REG_DEV) || (region->vm_flags & VM_REG_SHARED)) | 
|---|
|  | 92 | return 0; | 
|---|
|  | 93 |  | 
|---|
|  | 94 | switch(advice) | 
|---|
|  | 95 | { | 
|---|
|  | 96 | case MADV_NORMAL: | 
|---|
|  | 97 | case MADV_RANDOM: | 
|---|
|  | 98 | case MADV_SEQUENTIAL: | 
|---|
|  | 99 | case MADV_WILLNEED: | 
|---|
|  | 100 | err = vmm_madvise_willneed(vmm, (uint_t)start, (uint_t)length); | 
|---|
|  | 101 | break; | 
|---|
|  | 102 | case MADV_DONTNEED: | 
|---|
|  | 103 | return 0; | 
|---|
|  | 104 |  | 
|---|
|  | 105 | case MADV_MIGRATE: | 
|---|
|  | 106 | err = vmm_madvise_migrate(vmm, (uint_t)start, (uint_t)length); | 
|---|
|  | 107 | break; | 
|---|
|  | 108 |  | 
|---|
|  | 109 | default: | 
|---|
|  | 110 | err = EINVAL; | 
|---|
|  | 111 | } | 
|---|
|  | 112 |  | 
|---|
|  | 113 | SYS_MADVISE_ERR: | 
|---|
|  | 114 | this->info.errno = err; | 
|---|
|  | 115 | return err; | 
|---|
|  | 116 | } | 
|---|