Changeset 68f11ddc in mainline for kernel/generic/src/mm/as.c


Ignore:
Timestamp:
2018-12-03T16:54:22Z (5 years ago)
Author:
Jiri Svoboda <jiri@…>
Parents:
a0765f6
git-author:
Jiri Svoboda <jiri@…> (2018-12-03 16:53:27)
git-committer:
Jiri Svoboda <jiri@…> (2018-12-03 16:54:22)
Message:

Use ordered dictionary for pagemap instead of B+tree

At the same time we add a little bit more abstraction around the pagemap.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/mm/as.c

    ra0765f6 r68f11ddc  
    8989as_operations_t *as_operations = NULL;
    9090
    91 /** Slab for as_t objects.
    92  *
    93  */
     91/** Cache for as_t objects */
    9492static slab_cache_t *as_cache;
     93
     94/** Cache for as_page_mapping_t objects */
     95static slab_cache_t *as_page_mapping_cache;
    9596
    9697/** ASID subsystem lock.
     
    138139        as_cache = slab_cache_create("as_t", sizeof(as_t), 0,
    139140            as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
     141
     142        as_page_mapping_cache = slab_cache_create("as_page_mapping_t",
     143            sizeof(as_page_mapping_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED);
    140144
    141145        AS_KERNEL = as_create(FLAG_AS_KERNEL);
     
    524528}
    525529
     530/** Get key function for pagemap ordered dictionary.
     531 *
     532 * The key is the virtual address of the page (as_page_mapping_t.vaddr)
     533 *
     534 * @param odlink Link to as_pagemap_t.map ordered dictionary
     535 * @return Pointer to virtual address cast as @c void *
     536 */
     537static void *as_pagemap_getkey(odlink_t *odlink)
     538{
     539        as_page_mapping_t *mapping;
     540
     541        mapping = odict_get_instance(odlink, as_page_mapping_t, lpagemap);
     542        return (void *) &mapping->vaddr;
     543}
     544
     545/** Comparison function for pagemap ordered dictionary.
     546 *
     547 * @param a Pointer to virtual address cast as @c void *
     548 * @param b Pointer to virtual address cast as @c void *
     549 * @return <0, =0, >0 if virtual address a is less than, equal to, or
     550 *         greater-than b, respectively.
     551 */
     552static int as_pagemap_cmp(void *a, void *b)
     553{
     554        uintptr_t va = *(uintptr_t *)a;
     555        uintptr_t vb = *(uintptr_t *)b;
     556
     557        return va - vb;
     558}
     559
     560/** Initialize pagemap.
     561 *
     562 * @param pagemap Pagemap
     563 */
     564NO_TRACE void as_pagemap_initialize(as_pagemap_t *pagemap)
     565{
     566        odict_initialize(&pagemap->map, as_pagemap_getkey, as_pagemap_cmp);
     567}
     568
     569/** Finalize pagemap.
     570 *
     571 * Destroy any entries in the pagemap.
     572 *
     573 * @param pagemap Pagemap
     574 */
     575NO_TRACE void as_pagemap_finalize(as_pagemap_t *pagemap)
     576{
     577        as_page_mapping_t *mapping = as_pagemap_first(pagemap);
     578        while (mapping != NULL) {
     579                as_pagemap_remove(mapping);
     580                mapping = as_pagemap_first(pagemap);
     581        }
     582        odict_finalize(&pagemap->map);
     583}
     584
     585/** Get first page mapping.
     586 *
     587 * @param pagemap Pagemap
     588 * @return First mapping or @c NULL if there is none
     589 */
     590NO_TRACE as_page_mapping_t *as_pagemap_first(as_pagemap_t *pagemap)
     591{
     592        odlink_t *odlink;
     593
     594        odlink = odict_first(&pagemap->map);
     595        if (odlink == NULL)
     596                return NULL;
     597
     598        return odict_get_instance(odlink, as_page_mapping_t, lpagemap);
     599}
     600
     601/** Get next page mapping.
     602 *
     603 * @param cur Current mapping
     604 * @return Next mapping or @c NULL if @a cur is the last one
     605 */
     606NO_TRACE as_page_mapping_t *as_pagemap_next(as_page_mapping_t *cur)
     607{
     608        odlink_t *odlink;
     609
     610        odlink = odict_next(&cur->lpagemap, &cur->pagemap->map);
     611        if (odlink == NULL)
     612                return NULL;
     613
     614        return odict_get_instance(odlink, as_page_mapping_t, lpagemap);
     615}
     616
     617/** Find frame by virtual address.
     618 *
     619 * @param pagemap Pagemap
     620 * @param vaddr Virtual address of page
     621 * @param rframe Place to store physical frame address
     622 * @return EOK on succcess or ENOENT if no mapping found
     623 */
     624NO_TRACE errno_t as_pagemap_find(as_pagemap_t *pagemap, uintptr_t vaddr,
     625    uintptr_t *rframe)
     626{
     627        odlink_t *odlink;
     628        as_page_mapping_t *mapping;
     629
     630        odlink = odict_find_eq(&pagemap->map, &vaddr, NULL);
     631        if (odlink == NULL)
     632                return ENOENT;
     633
     634        mapping = odict_get_instance(odlink, as_page_mapping_t, lpagemap);
     635        *rframe = mapping->frame;
     636        return EOK;
     637}
     638
     639/** Insert new page mapping.
     640 *
     641 * This function can block to allocate kernel memory.
     642 *
     643 * @param pagemap Pagemap
     644 * @param vaddr Virtual page address
     645 * @param frame Physical frame address
     646 */
     647NO_TRACE void as_pagemap_insert(as_pagemap_t *pagemap, uintptr_t vaddr,
     648    uintptr_t frame)
     649{
     650        as_page_mapping_t *mapping;
     651
     652        mapping = slab_alloc(as_page_mapping_cache, 0);
     653        mapping->pagemap = pagemap;
     654        odlink_initialize(&mapping->lpagemap);
     655        mapping->vaddr = vaddr;
     656        mapping->frame = frame;
     657        odict_insert(&mapping->lpagemap, &pagemap->map, NULL);
     658}
     659
     660/** Remove page mapping.
     661 *
     662 * @param mapping Mapping
     663 */
     664NO_TRACE void as_pagemap_remove(as_page_mapping_t *mapping)
     665{
     666        odict_remove(&mapping->lpagemap);
     667        slab_free(as_page_mapping_cache, mapping);
     668}
     669
    526670/** Remove reference to address space area share info.
    527671 *
     
    545689                 * reference from all frames found there.
    546690                 */
    547                 list_foreach(sh_info->pagemap.leaf_list, leaf_link,
    548                     btree_node_t, node) {
    549                         btree_key_t i;
    550 
    551                         for (i = 0; i < node->keys; i++)
    552                                 frame_free((uintptr_t) node->value[i], 1);
     691                as_page_mapping_t *mapping = as_pagemap_first(&sh_info->pagemap);
     692                while (mapping != NULL) {
     693                        frame_free(mapping->frame, 1);
     694                        mapping = as_pagemap_next(mapping);
    553695                }
    554696
     
    561703                            sh_info->backend_shared_data);
    562704                }
    563                 btree_destroy(&sh_info->pagemap);
     705                as_pagemap_finalize(&sh_info->pagemap);
    564706                free(sh_info);
    565707        }
     
    665807                si->backend_shared_data = NULL;
    666808                si->backend = backend;
    667                 btree_create(&si->pagemap);
     809                as_pagemap_initialize(&si->pagemap);
    668810
    669811                area->sh_info = si;
Note: See TracChangeset for help on using the changeset viewer.