diff options
Diffstat (limited to 'libpagemap/pm_memusage.c')
-rw-r--r-- | libpagemap/pm_memusage.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/libpagemap/pm_memusage.c b/libpagemap/pm_memusage.c index ea2a003c..70cfedec 100644 --- a/libpagemap/pm_memusage.c +++ b/libpagemap/pm_memusage.c @@ -14,10 +14,37 @@ * limitations under the License. */ +#include <stdlib.h> +#include <unistd.h> + #include <pagemap/pagemap.h> +#define SIMPLEQ_INSERT_SIMPLEQ_TAIL(head_a, head_b) \ + do { \ + if (!SIMPLEQ_EMPTY(head_b)) { \ + if ((head_a)->sqh_first == NULL) \ + (head_a)->sqh_first = (head_b)->sqh_first; \ + *(head_a)->sqh_last = (head_b)->sqh_first; \ + (head_a)->sqh_last = (head_b)->sqh_last; \ + } \ + } while (/*CONSTCOND*/0) + +/* We use an array of int to store the references to a given offset in the swap + 1 GiB swap means 512KiB size array: offset are the index */ +typedef unsigned short pm_pswap_refcount_t; +struct pm_proportional_swap { + unsigned int array_size; + pm_pswap_refcount_t *offset_array; +}; + void pm_memusage_zero(pm_memusage_t *mu) { mu->vss = mu->rss = mu->pss = mu->uss = mu->swap = 0; + mu->p_swap = NULL; + SIMPLEQ_INIT(&mu->swap_offset_list); +} + +void pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap) { + mu->p_swap = p_swap; } void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b) { @@ -26,4 +53,80 @@ void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b) { a->pss += b->pss; a->uss += b->uss; a->swap += b->swap; + SIMPLEQ_INSERT_SIMPLEQ_TAIL(&a->swap_offset_list, &b->swap_offset_list); +} + +pm_proportional_swap_t * pm_memusage_pswap_create(int swap_size) +{ + pm_proportional_swap_t *p_swap = NULL; + + p_swap = malloc(sizeof(pm_proportional_swap_t)); + if (p_swap == NULL) { + fprintf(stderr, "Error allocating proportional swap.\n"); + } else { + p_swap->array_size = swap_size / getpagesize(); + p_swap->offset_array = calloc(p_swap->array_size, sizeof(pm_pswap_refcount_t)); + if (p_swap->offset_array == NULL) { + fprintf(stderr, "Error allocating proportional swap offset array.\n"); + free(p_swap); + p_swap = NULL; + } + } + + return p_swap; +} + +void pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap) { + if (p_swap) { + free(p_swap->offset_array); + free(p_swap); + } +} + +void pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset) { + pm_swap_offset_t *soff; + + if (mu->p_swap == NULL) + return; + + if (offset > mu->p_swap->array_size) { + fprintf(stderr, "SWAP offset %d is out of swap bounds.\n", offset); + return; + } else { + if (mu->p_swap->offset_array[offset] == USHRT_MAX) { + fprintf(stderr, "SWAP offset %d ref. count if overflowing ushort type.\n", offset); + } else { + mu->p_swap->offset_array[offset]++; + } + } + + soff = malloc(sizeof(pm_swap_offset_t)); + if (soff) { + soff->offset = offset; + SIMPLEQ_INSERT_TAIL(&mu->swap_offset_list, soff, simpleqe); + } +} + +void pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su) { + + int pagesize = getpagesize(); + pm_swap_offset_t *elem; + + if (su == NULL) + return; + + su->proportional = su->unique = 0; + SIMPLEQ_FOREACH(elem, &mu->swap_offset_list, simpleqe) { + su->proportional += pagesize / mu->p_swap->offset_array[elem->offset]; + su->unique += mu->p_swap->offset_array[elem->offset] == 1 ? pagesize : 0; + } +} + +void pm_memusage_pswap_free(pm_memusage_t *mu) { + pm_swap_offset_t *elem = SIMPLEQ_FIRST(&mu->swap_offset_list); + while (elem) { + SIMPLEQ_REMOVE_HEAD(&mu->swap_offset_list, simpleqe); + free(elem); + elem = SIMPLEQ_FIRST(&mu->swap_offset_list); + } } |