1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/* 2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License. 6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at 7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * 10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and 14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License. 15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */ 16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 1708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel#include <stdlib.h> 1808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel#include <unistd.h> 1908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pagemap/pagemap.h> 21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 2208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel#define SIMPLEQ_INSERT_SIMPLEQ_TAIL(head_a, head_b) \ 2308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel do { \ 2408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (!SIMPLEQ_EMPTY(head_b)) { \ 2508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if ((head_a)->sqh_first == NULL) \ 2608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel (head_a)->sqh_first = (head_b)->sqh_first; \ 2708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel *(head_a)->sqh_last = (head_b)->sqh_first; \ 2808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel (head_a)->sqh_last = (head_b)->sqh_last; \ 2908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } \ 3008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } while (/*CONSTCOND*/0) 3108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 3208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel/* We use an array of int to store the references to a given offset in the swap 3308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 1 GiB swap means 512KiB size array: offset are the index */ 3408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudeltypedef unsigned short pm_pswap_refcount_t; 3508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelstruct pm_proportional_swap { 3608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel unsigned int array_size; 3708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel pm_pswap_refcount_t *offset_array; 3808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel}; 3908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectvoid pm_memusage_zero(pm_memusage_t *mu) { 41745b964daeacf44350db14bc343d53e319e696b8Colin Cross mu->vss = mu->rss = mu->pss = mu->uss = mu->swap = 0; 4208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel mu->p_swap = NULL; 4308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel SIMPLEQ_INIT(&mu->swap_offset_list); 4408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel} 4508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 4608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelvoid pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap) { 4708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel mu->p_swap = p_swap; 48e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project 50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectvoid pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b) { 51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project a->vss += b->vss; 52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project a->rss += b->rss; 53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project a->pss += b->pss; 54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project a->uss += b->uss; 55745b964daeacf44350db14bc343d53e319e696b8Colin Cross a->swap += b->swap; 5608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel SIMPLEQ_INSERT_SIMPLEQ_TAIL(&a->swap_offset_list, &b->swap_offset_list); 5708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel} 5808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 5908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelpm_proportional_swap_t * pm_memusage_pswap_create(int swap_size) 6008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel{ 6108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel pm_proportional_swap_t *p_swap = NULL; 6208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 6308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel p_swap = malloc(sizeof(pm_proportional_swap_t)); 6408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (p_swap == NULL) { 6508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel fprintf(stderr, "Error allocating proportional swap.\n"); 6608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } else { 6708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel p_swap->array_size = swap_size / getpagesize(); 6808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel p_swap->offset_array = calloc(p_swap->array_size, sizeof(pm_pswap_refcount_t)); 6908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (p_swap->offset_array == NULL) { 7008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel fprintf(stderr, "Error allocating proportional swap offset array.\n"); 7108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel free(p_swap); 7208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel p_swap = NULL; 7308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 7408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 7508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 7608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel return p_swap; 7708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel} 7808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 7908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelvoid pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap) { 8008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (p_swap) { 8108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel free(p_swap->offset_array); 8208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel free(p_swap); 8308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 8408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel} 8508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 8608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelvoid pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset) { 8708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel pm_swap_offset_t *soff; 8808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 8908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (mu->p_swap == NULL) 9008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel return; 9108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 9298a20cd1283b6ee029e871c0876815300475c40aNick Desaulniers if (offset >= mu->p_swap->array_size) { 9308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel fprintf(stderr, "SWAP offset %d is out of swap bounds.\n", offset); 9408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel return; 9598a20cd1283b6ee029e871c0876815300475c40aNick Desaulniers } 9698a20cd1283b6ee029e871c0876815300475c40aNick Desaulniers 9798a20cd1283b6ee029e871c0876815300475c40aNick Desaulniers if (mu->p_swap->offset_array[offset] == USHRT_MAX) { 9898a20cd1283b6ee029e871c0876815300475c40aNick Desaulniers fprintf(stderr, "SWAP offset %d ref. count if overflowing ushort type.\n", offset); 9908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } else { 10098a20cd1283b6ee029e871c0876815300475c40aNick Desaulniers mu->p_swap->offset_array[offset]++; 10108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 10208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 10308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel soff = malloc(sizeof(pm_swap_offset_t)); 10408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (soff) { 10508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel soff->offset = offset; 10608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel SIMPLEQ_INSERT_TAIL(&mu->swap_offset_list, soff, simpleqe); 10708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 10808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel} 10908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 11008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelvoid pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su) { 11108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 11208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel int pagesize = getpagesize(); 11308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel pm_swap_offset_t *elem; 11408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 11508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel if (su == NULL) 11608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel return; 11708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 11808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel su->proportional = su->unique = 0; 11908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel SIMPLEQ_FOREACH(elem, &mu->swap_offset_list, simpleqe) { 12008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel su->proportional += pagesize / mu->p_swap->offset_array[elem->offset]; 12108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel su->unique += mu->p_swap->offset_array[elem->offset] == 1 ? pagesize : 0; 12208ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 12308ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel} 12408ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel 12508ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudelvoid pm_memusage_pswap_free(pm_memusage_t *mu) { 12608ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel pm_swap_offset_t *elem = SIMPLEQ_FIRST(&mu->swap_offset_list); 12708ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel while (elem) { 12808ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel SIMPLEQ_REMOVE_HEAD(&mu->swap_offset_list, simpleqe); 12908ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel free(elem); 13008ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel elem = SIMPLEQ_FIRST(&mu->swap_offset_list); 13108ea6e722b1f2d6359f54fe39c6bed82f524291cThierry Strudel } 132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project} 133