blob: 70cfedecfacd6714a165dda8ec52da002ddd2be4 [file] [log] [blame]
The Android Open Source Projecte16cb842009-03-03 19:32:58 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Thierry Strudel08ea6e72015-11-20 18:07:15 -080017#include <stdlib.h>
18#include <unistd.h>
19
The Android Open Source Projecte16cb842009-03-03 19:32:58 -080020#include <pagemap/pagemap.h>
21
Thierry Strudel08ea6e72015-11-20 18:07:15 -080022#define SIMPLEQ_INSERT_SIMPLEQ_TAIL(head_a, head_b) \
23 do { \
24 if (!SIMPLEQ_EMPTY(head_b)) { \
25 if ((head_a)->sqh_first == NULL) \
26 (head_a)->sqh_first = (head_b)->sqh_first; \
27 *(head_a)->sqh_last = (head_b)->sqh_first; \
28 (head_a)->sqh_last = (head_b)->sqh_last; \
29 } \
30 } while (/*CONSTCOND*/0)
31
32/* We use an array of int to store the references to a given offset in the swap
33 1 GiB swap means 512KiB size array: offset are the index */
34typedef unsigned short pm_pswap_refcount_t;
35struct pm_proportional_swap {
36 unsigned int array_size;
37 pm_pswap_refcount_t *offset_array;
38};
39
The Android Open Source Projecte16cb842009-03-03 19:32:58 -080040void pm_memusage_zero(pm_memusage_t *mu) {
Colin Cross745b9642013-06-21 12:53:51 -070041 mu->vss = mu->rss = mu->pss = mu->uss = mu->swap = 0;
Thierry Strudel08ea6e72015-11-20 18:07:15 -080042 mu->p_swap = NULL;
43 SIMPLEQ_INIT(&mu->swap_offset_list);
44}
45
46void pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap) {
47 mu->p_swap = p_swap;
The Android Open Source Projecte16cb842009-03-03 19:32:58 -080048}
49
50void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b) {
51 a->vss += b->vss;
52 a->rss += b->rss;
53 a->pss += b->pss;
54 a->uss += b->uss;
Colin Cross745b9642013-06-21 12:53:51 -070055 a->swap += b->swap;
Thierry Strudel08ea6e72015-11-20 18:07:15 -080056 SIMPLEQ_INSERT_SIMPLEQ_TAIL(&a->swap_offset_list, &b->swap_offset_list);
57}
58
59pm_proportional_swap_t * pm_memusage_pswap_create(int swap_size)
60{
61 pm_proportional_swap_t *p_swap = NULL;
62
63 p_swap = malloc(sizeof(pm_proportional_swap_t));
64 if (p_swap == NULL) {
65 fprintf(stderr, "Error allocating proportional swap.\n");
66 } else {
67 p_swap->array_size = swap_size / getpagesize();
68 p_swap->offset_array = calloc(p_swap->array_size, sizeof(pm_pswap_refcount_t));
69 if (p_swap->offset_array == NULL) {
70 fprintf(stderr, "Error allocating proportional swap offset array.\n");
71 free(p_swap);
72 p_swap = NULL;
73 }
74 }
75
76 return p_swap;
77}
78
79void pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap) {
80 if (p_swap) {
81 free(p_swap->offset_array);
82 free(p_swap);
83 }
84}
85
86void pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset) {
87 pm_swap_offset_t *soff;
88
89 if (mu->p_swap == NULL)
90 return;
91
92 if (offset > mu->p_swap->array_size) {
93 fprintf(stderr, "SWAP offset %d is out of swap bounds.\n", offset);
94 return;
95 } else {
96 if (mu->p_swap->offset_array[offset] == USHRT_MAX) {
97 fprintf(stderr, "SWAP offset %d ref. count if overflowing ushort type.\n", offset);
98 } else {
99 mu->p_swap->offset_array[offset]++;
100 }
101 }
102
103 soff = malloc(sizeof(pm_swap_offset_t));
104 if (soff) {
105 soff->offset = offset;
106 SIMPLEQ_INSERT_TAIL(&mu->swap_offset_list, soff, simpleqe);
107 }
108}
109
110void pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su) {
111
112 int pagesize = getpagesize();
113 pm_swap_offset_t *elem;
114
115 if (su == NULL)
116 return;
117
118 su->proportional = su->unique = 0;
119 SIMPLEQ_FOREACH(elem, &mu->swap_offset_list, simpleqe) {
120 su->proportional += pagesize / mu->p_swap->offset_array[elem->offset];
121 su->unique += mu->p_swap->offset_array[elem->offset] == 1 ? pagesize : 0;
122 }
123}
124
125void pm_memusage_pswap_free(pm_memusage_t *mu) {
126 pm_swap_offset_t *elem = SIMPLEQ_FIRST(&mu->swap_offset_list);
127 while (elem) {
128 SIMPLEQ_REMOVE_HEAD(&mu->swap_offset_list, simpleqe);
129 free(elem);
130 elem = SIMPLEQ_FIRST(&mu->swap_offset_list);
131 }
The Android Open Source Projecte16cb842009-03-03 19:32:58 -0800132}