Changeset 26250

Show
Ignore:
Timestamp:
07/04/08 12:35:50 (5 months ago)
Author:
bonefish
Message:

* Renamed VMCache::virtual_size to virtual_end to avoid confusion.
* Added cache type argument to VMCache::Init(). The type is no longer

set by the one creating the cache.

* VMCache::Commit() is passed the actual size to be committed, now, not

virtual_end.

* Added VMCache::Delete(), moved the cleanup code from the destructor

there, and used it in all places instead of the destructor.

* Added VMCache::MergeStore(). It is called when a cache is merged with

its only consumer.

* Implemented VMAnonymousCache::MergeStore(). The remaining cache takes

over the memory commitment of its source that is going to be deleted.
This does at least improve the situation, that after fork() + exec*()
the parent's RAM areas caches don't have any memory commitment
anymore. We definitely need a more consistent commitment strategy,
particularly for CoW.

* vm_resize_area(): when growing the area, resize the cache first, since

that can fail. Resize the cache back on error.

Location:
haiku/branches/developer/bonefish/vm
Files:
12 modified

Legend:

Unmodified
Added
Removed
  • haiku/branches/developer/bonefish/vm/headers/private/kernel/vm_types.h

    r26175 r26250  
    172172        virtual ~VMCache(); 
    173173 
    174         status_t Init(); 
     174        status_t Init(uint32 cacheType); 
     175 
     176        virtual void            Delete(); 
    175177 
    176178        // backing store operations 
     
    184186 
    185187        virtual status_t        Fault(struct vm_address_space *aspace, off_t offset); 
     188 
     189        virtual void            MergeStore(VMCache* source); 
    186190 
    187191        virtual status_t        AcquireUnreferencedStoreRef(); 
     
    199203        VMCache                         *source; 
    200204        off_t                           virtual_base; 
    201         off_t                           virtual_size; 
    202                 // the size is absolute, and independent from virtual_base 
     205        off_t                           virtual_end; 
    203206        off_t                           committed_size; 
    204207                // TODO: Remove! 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/cache/file_cache.cpp

    r26175 r26250  
    374374                        + vecs[vecCount - 1].iov_len - B_PAGE_SIZE; 
    375375 
    376                 if (offset + pageOffset + bufferSize == ref->cache->virtual_size) { 
     376                if (offset + pageOffset + bufferSize == ref->cache->virtual_end) { 
    377377                        // the space in the page after this write action needs to be cleaned 
    378378                        memset((void *)(last + lastPageOffset), 0, 
     
    552552        file_cache_ref *ref = (file_cache_ref *)_cacheRef; 
    553553        vm_cache *cache = ref->cache; 
    554         off_t fileSize = cache->virtual_size; 
     554        off_t fileSize = cache->virtual_end; 
    555555        bool useBuffer = buffer != 0; 
    556556 
     
    768768        file_cache_ref *ref = (struct file_cache_ref *) 
    769769                ((vnode_store *)cache->store)->file_cache_ref; 
    770         off_t fileSize = cache->virtual_size; 
     770        off_t fileSize = cache->virtual_end; 
    771771 
    772772        if (size > fileSize) 
     
    860860                file_cache_ref *ref = ((VMVnodeCache*)cache)->FileCacheRef(); 
    861861                if (ref != NULL) 
    862                         size = cache->virtual_size; 
     862                        size = cache->virtual_end; 
    863863        } 
    864864 
     
    950950                goto err1; 
    951951 
    952         ref->cache->virtual_size = size; 
     952        ref->cache->virtual_end = size; 
    953953        ((VMVnodeCache*)ref->cache)->SetFileCacheRef(ref); 
    954954        return ref; 
     
    987987        MutexLocker _(ref->cache->lock); 
    988988 
    989         off_t offset = ref->cache->virtual_size; 
     989        off_t offset = ref->cache->virtual_end; 
    990990        off_t size = newSize; 
    991991        if (offset > newSize) { 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/cache/vnode_store.cpp

    r26175 r26250  
    1717VMVnodeCache::Init(struct vnode *vnode) 
    1818{ 
    19         status_t error = VMCache::Init(); 
     19        status_t error = VMCache::Init(CACHE_TYPE_VNODE); 
    2020        if (error != B_OK) 
    2121                return error; 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/fs/vfs.cpp

    r26160 r26250  
    27952795 
    27962796                kprintf("%p%4ld%10Ld %p %8Ld%8ld\n", vnode, vnode->device, vnode->id, 
    2797                         vnode->cache, (vnode->cache->virtual_size + B_PAGE_SIZE - 1) 
     2797                        vnode->cache, (vnode->cache->virtual_end + B_PAGE_SIZE - 1) 
    27982798                                / B_PAGE_SIZE, vnode->cache->page_count); 
    27992799        } 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm.cpp

    r26175 r26250  
    13951395 
    13961396                mutex_lock(&newCache->lock); 
    1397                 newCache->type = CACHE_TYPE_RAM; 
    13981397                newCache->temporary = 1; 
    13991398                newCache->scan_skip = cache->scan_skip; 
    14001399                newCache->virtual_base = offset; 
    1401                 newCache->virtual_size = offset + size; 
     1400                newCache->virtual_end = offset + size; 
    14021401 
    14031402                vm_cache_add_consumer_locked(cache, newCache); 
     
    14061405        } 
    14071406 
    1408         status = vm_cache_set_minimal_commitment_locked(cache, offset + size); 
     1407        status = vm_cache_set_minimal_commitment_locked(cache, size); 
    14091408        if (status != B_OK) 
    14101409                goto err2; 
     
    16291628 
    16301629        cache->temporary = 1; 
    1631         cache->type = CACHE_TYPE_RAM; 
    1632         cache->virtual_size = size; 
     1630        cache->virtual_end = size; 
    16331631 
    16341632        switch (wiring) { 
     
    18451843        // tell the page scanner to skip over this area, it's pages are special 
    18461844        cache->scan_skip = 1; 
    1847         cache->type = CACHE_TYPE_DEVICE; 
    1848         cache->virtual_size = size; 
     1845        cache->virtual_end = size; 
    18491846 
    18501847        mutex_lock(&cache->lock); 
     
    19191916        // tell the page scanner to skip over this area, no pages will be mapped here 
    19201917        cache->scan_skip = 1; 
    1921         cache->type = CACHE_TYPE_NULL; 
    1922         cache->virtual_size = size; 
     1918        cache->virtual_end = size; 
    19231919 
    19241920        mutex_lock(&cache->lock); 
     
    19441940*/ 
    19451941status_t 
    1946 vm_create_vnode_cache(struct vnode *vnode, struct VMCache **_cache) 
    1947 { 
    1948         // create a vnode cache 
    1949         vm_cache* cache; 
    1950         status_t status = VMCacheFactory::CreateVnodeCache(cache, vnode); 
    1951         if (status != B_OK) 
    1952                 return status; 
    1953  
    1954         cache->type = CACHE_TYPE_VNODE; 
    1955  
    1956         *_cache = cache; 
    1957         return B_OK; 
     1942vm_create_vnode_cache(struct vnode *vnode, struct VMCache **cache) 
     1943{ 
     1944        return VMCacheFactory::CreateVnodeCache(*cache, vnode); 
    19581945} 
    19591946 
     
    23002287        mutex_lock(&upperCache->lock); 
    23012288 
    2302         upperCache->type = CACHE_TYPE_RAM; 
    23032289        upperCache->temporary = 1; 
    23042290        upperCache->scan_skip = lowerCache->scan_skip; 
    23052291        upperCache->virtual_base = lowerCache->virtual_base; 
    2306         upperCache->virtual_size = lowerCache->virtual_size; 
     2292        upperCache->virtual_end = lowerCache->virtual_end; 
    23072293 
    23082294        // transfer the lower cache areas to the upper cache 
     
    24752461                                // into account that really are in this cache. 
    24762462 
    2477                                 status = cache->Commit( 
    2478                                         cache->virtual_base + cache->page_count * B_PAGE_SIZE); 
     2463                                status = cache->Commit(cache->page_count * B_PAGE_SIZE); 
    24792464 
    24802465                                // ToDo: we may be able to join with our source cache, if count == 0 
     
    24942479                        if (cache->source != NULL && cache->temporary) { 
    24952480                                // the cache's commitment must contain all possible pages 
    2496                                 status = cache->Commit(cache->virtual_size); 
     2481                                status = cache->Commit(cache->virtual_end 
     2482                                        - cache->virtual_base); 
    24972483                        } 
    24982484 
     
    31103096        kprintf("%p: type: %s, base: %lld, size: %lld, pages: %lu", cache, 
    31113097                cache_type_to_string(cache->type), cache->virtual_base, 
    3112                 cache->virtual_size, cache->page_count); 
     3098                cache->virtual_end, cache->page_count); 
    31133099 
    31143100        if (level == 0) 
     
    32393225        kprintf("  type:         %s\n", cache_type_to_string(cache->type)); 
    32403226        kprintf("  virtual_base: 0x%Lx\n", cache->virtual_base); 
    3241         kprintf("  virtual_size: 0x%Lx\n", cache->virtual_size); 
     3227        kprintf("  virtual_end:  0x%Lx\n", cache->virtual_end); 
    32423228        kprintf("  temporary:    %ld\n", cache->temporary); 
    32433229        kprintf("  scan_skip:    %ld\n", cache->scan_skip); 
     
    48334819                for (vm_area* current = cache->areas; current != NULL; 
    48344820                                current = current->cache_next) { 
    4835                         if (current->address_space_next 
    4836                                 && current->address_space_next->base <= (current->base 
    4837                                         + newSize)) { 
     4821                        vm_area *next = current->address_space_next; 
     4822                        if (next != NULL && next->base <= (current->base + newSize)) { 
    48384823                                // If the area was created inside a reserved area, it can 
    48394824                                // also be resized in that area 
    48404825                                // ToDo: if there is free space after the reserved area, it could be used as well... 
    4841                                 vm_area *next = current->address_space_next; 
    48424826                                if (next->id == RESERVED_AREA_ID 
    48434827                                        && next->cache_offset <= current->base 
     
    48524836        // Okay, looks good so far, so let's do it 
    48534837 
     4838        if (oldSize < newSize) { 
     4839                // Growing the cache can fail, so we do it first. 
     4840                status = vm_cache_resize(cache, newSize); 
     4841                if (status != B_OK) 
     4842                        return status; 
     4843        } 
     4844 
    48544845        for (vm_area* current = cache->areas; current != NULL; 
    48554846                        current = current->cache_next) { 
    4856                 if (current->address_space_next 
    4857                         && current->address_space_next->base <= (current->base + newSize)) { 
    4858                         vm_area *next = current->address_space_next; 
     4847                vm_area *next = current->address_space_next; 
     4848                if (next != NULL && next->base <= (current->base + newSize)) { 
    48594849                        if (next->id == RESERVED_AREA_ID 
    48604850                                && next->cache_offset <= current->base 
     
    48704860                                } 
    48714861                        } else { 
     4862                                panic("resize situation for area %p has changed although we " 
     4863                                        "should have the address space lock", current); 
    48724864                                status = B_ERROR; 
    48734865                                break; 
     
    48844876        } 
    48854877 
    4886         if (status == B_OK) 
     4878        // shrinking the cache can't fail, so we do it now 
     4879        if (status == B_OK && newSize < oldSize) 
    48874880                status = vm_cache_resize(cache, newSize); 
    48884881 
     
    48934886                        current->size = oldSize; 
    48944887                } 
     4888 
     4889                vm_cache_resize(cache, oldSize); 
    48954890        } 
    48964891 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_cache.cpp

    r26175 r26250  
    127127                        : 
    128128                        VMCacheTraceEntry(cache), 
    129                         fOldSize(cache->virtual_size), 
     129                        fOldSize(cache->virtual_end), 
    130130                        fSize(size) 
    131131                { 
     
    437437        } 
    438438 
     439        // merge the backing store 
     440        consumer->MergeStore(cache); 
     441 
    439442        // The remaining consumer has got a new source. 
    440443        if (cache->source != NULL) { 
     
    536539        // delete this cache 
    537540 
    538         delete cache; 
     541        cache->Delete(); 
    539542} 
    540543 
     
    685688{ 
    686689        TRACE(("vm_cache_resize(cache %p, newSize %Ld) old size %Ld\n", 
    687                 cache, newSize, cache->virtual_size)); 
     690                cache, newSize, cache->virtual_end)); 
    688691        ASSERT_LOCKED_MUTEX(&cache->lock); 
    689692 
    690693        T(Resize(cache, newSize)); 
    691694 
    692         status_t status = cache->Commit(newSize); 
     695        status_t status = cache->Commit(newSize - cache->virtual_base); 
    693696        if (status != B_OK) 
    694697                return status; 
    695698 
    696         uint32 oldPageCount = (uint32)((cache->virtual_size + B_PAGE_SIZE - 1) 
     699        uint32 oldPageCount = (uint32)((cache->virtual_end + B_PAGE_SIZE - 1) 
    697700                >> PAGE_SHIFT); 
    698701        uint32 newPageCount = (uint32)((newSize + B_PAGE_SIZE - 1) >> PAGE_SHIFT); 
     
    732735        } 
    733736 
    734         cache->virtual_size = newSize; 
     737        cache->virtual_end = newSize; 
    735738        return B_OK; 
    736739} 
     
    848851 
    849852VMCache::~VMCache() 
     853{ 
     854        mutex_destroy(&lock); 
     855} 
     856 
     857 
     858status_t 
     859VMCache::Init(uint32 cacheType) 
     860{ 
     861        mutex_init(&lock, "vm_cache"); 
     862        list_init_etc(&consumers, offsetof(VMCache, consumer_link)); 
     863        areas = NULL; 
     864        ref_count = 1; 
     865        source = NULL; 
     866        virtual_base = 0; 
     867        virtual_end = 0; 
     868        committed_size = 0; 
     869        temporary = 0; 
     870        scan_skip = 0; 
     871        page_count = 0; 
     872        busy = false; 
     873        type = cacheType; 
     874 
     875#if DEBUG_CACHE_LIST 
     876        mutex_lock(&sCacheListLock); 
     877 
     878        if (gDebugCacheList) 
     879                gDebugCacheList->debug_previous = this; 
     880        debug_previous = NULL; 
     881        debug_next = gDebugCacheList; 
     882        gDebugCacheList = this; 
     883 
     884        mutex_unlock(&sCacheListLock); 
     885#endif 
     886 
     887        return B_OK; 
     888} 
     889 
     890 
     891void 
     892VMCache::Delete() 
    850893{ 
    851894        if (areas != NULL) 
     
    893936        mutex_unlock(&sCacheListLock); 
    894937 
    895         mutex_destroy(&lock); 
    896 } 
    897  
    898  
    899 status_t 
    900 VMCache::Init() 
    901 { 
    902         mutex_init(&lock, "vm_cache"); 
    903         list_init_etc(&consumers, offsetof(VMCache, consumer_link)); 
    904         areas = NULL; 
    905         ref_count = 1; 
    906         source = NULL; 
    907         virtual_base = 0; 
    908         virtual_size = 0; 
    909         committed_size = 0; 
    910         temporary = 0; 
    911         scan_skip = 0; 
    912         page_count = 0; 
    913         busy = false; 
    914  
    915 #if DEBUG_CACHE_LIST 
    916         mutex_lock(&sCacheListLock); 
    917  
    918         if (gDebugCacheList) 
    919                 gDebugCacheList->debug_previous = this; 
    920         debug_previous = NULL; 
    921         debug_next = gDebugCacheList; 
    922         gDebugCacheList = this; 
    923  
    924         mutex_unlock(&sCacheListLock); 
    925 #endif 
    926  
    927         return B_OK; 
     938        delete this; 
    928939} 
    929940 
     
    940951VMCache::HasPage(off_t offset) 
    941952{ 
    942         return offset >= virtual_base && offset <= virtual_size; 
     953        return offset >= virtual_base && offset <= virtual_end; 
    943954} 
    944955 
     
    964975{ 
    965976        return B_BAD_ADDRESS; 
     977} 
     978 
     979 
     980void 
     981VMCache::MergeStore(VMCache* source) 
     982{ 
    966983} 
    967984 
     
    10091026                numGuardPages); 
    10101027        if (error != B_OK) { 
    1011                 delete cache; 
     1028                cache->Delete(); 
    10121029                return error; 
    10131030        } 
     
    10271044        status_t error = cache->Init(vnode); 
    10281045        if (error != B_OK) { 
    1029                 delete cache; 
     1046                cache->Delete(); 
    10301047                return error; 
    10311048        } 
     
    10451062        status_t error = cache->Init(baseAddress); 
    10461063        if (error != B_OK) { 
    1047                 delete cache; 
     1064                cache->Delete(); 
    10481065                return error; 
    10491066        } 
     
    10631080        status_t error = cache->Init(); 
    10641081        if (error != B_OK) { 
    1065                 delete cache; 
     1082                cache->Delete(); 
    10661083                return error; 
    10671084        } 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_page.cpp

    r26175 r26250  
    13981398{ 
    13991399        return vm_page_write_modified_page_range(cache, 0, 
    1400                 (cache->virtual_size + B_PAGE_SIZE - 1) >> PAGE_SHIFT, fsReenter); 
     1400                (cache->virtual_end + B_PAGE_SIZE - 1) >> PAGE_SHIFT, fsReenter); 
    14011401} 
    14021402 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_store_anonymous_noswap.cpp

    r26175 r26250  
    4444                "at %p\n", canOvercommit ? "yes" : "no", numGuardPages, store)); 
    4545 
    46         status_t error = VMCache::Init(); 
     46        status_t error = VMCache::Init(CACHE_TYPE_RAM); 
    4747        if (error != B_OK) 
    4848                return error; 
     
    6060VMAnonymousCache::Commit(off_t size) 
    6161{ 
    62         size -= virtual_base; 
    63                 // anonymous stores don't need to span over their whole source 
    64  
    6562        // if we can overcommit, we don't commit here, but in anonymous_fault() 
    6663        if (fCanOvercommit) { 
     
    151148        return B_BAD_HANDLER; 
    152149} 
     150 
     151 
     152void 
     153VMAnonymousCache::MergeStore(VMCache* source) 
     154{ 
     155        if (source->type != CACHE_TYPE_RAM) { 
     156                panic("VMAnonymousCache::MergeStore(): merge with non-RAM cache " 
     157                        "requested", source); 
     158                return; 
     159        } 
     160 
     161        // take over the source' committed size 
     162        committed_size += source->committed_size; 
     163        source->committed_size = 0; 
     164 
     165        off_t actualSize = virtual_end - virtual_base; 
     166        if (committed_size > actualSize) { 
     167                vm_unreserve_memory(committed_size - actualSize); 
     168                committed_size = actualSize; 
     169        } 
     170} 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_store_anonymous_noswap.h

    r26175 r26250  
    3030        virtual status_t        Fault(struct vm_address_space *aspace, off_t offset); 
    3131 
     32        virtual void            MergeStore(VMCache* source); 
     33 
    3234private: 
    3335        bool    fCanOvercommit; 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_store_device.cpp

    r26175 r26250  
    1414{ 
    1515        fBaseAddress = baseAddress; 
    16         return VMCache::Init(); 
     16        return VMCache::Init(CACHE_TYPE_DEVICE); 
    1717} 
    1818 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_store_null.cpp

    r26175 r26250  
    66#include "vm_store_null.h" 
    77 
    8 // TODO: Remove! 
     8 
     9status_t 
     10VMNullCache::Init() 
     11{ 
     12        return VMCache::Init(CACHE_TYPE_NULL); 
     13} 
  • haiku/branches/developer/bonefish/vm/src/system/kernel/vm/vm_store_null.h

    r26175 r26250  
    1414 
    1515<