-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache.c
More file actions
140 lines (116 loc) · 3.2 KB
/
cache.c
File metadata and controls
140 lines (116 loc) · 3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* Copyright Penguin Boost, 2016
* Author(s): Jan Glauber <jan.glauber@gmail.com>
*
* Caching layer based on pre-sorted lists.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stddef.h>
#include "nlmon.h"
#include "helper.h"
#include "rbtree.h"
struct rb_root cache_tree = RB_ROOT;
extern enum sort_options opt_sort;
int (*compare_fn) (struct taskstat_delta *t1, struct taskstat_delta *t2);
/* sost alphabetically by task name ignoring case */
static int compare_name(struct taskstat_delta *t1, struct taskstat_delta *t2)
{
return strncasecmp(t1->comm, t2->comm, 16);
}
/* sort by increasing tid */
static int compare_tid(struct taskstat_delta *t1, struct taskstat_delta *t2)
{
int a = t2->tid;
int b = t1->tid;
return (a < b) ? 1 : (a > b) ? -1 : 0;
}
/* sort be decreasing cpu time */
static int compare_time(struct taskstat_delta *t1, struct taskstat_delta *t2)
{
unsigned long long a = t1->utime + t1->stime;
unsigned long long b = t2->utime + t2->stime;
return (a < b) ? 1 : (a > b) ? -1 : 0;
}
/* sort by decreasing I/O */
static int compare_io(struct taskstat_delta *t1, struct taskstat_delta *t2)
{
unsigned long long a = t1->io_rd_bytes + t1->io_wr_bytes;
unsigned long long b = t2->io_rd_bytes + t2->io_wr_bytes;
return (a < b) ? 1 : (a > b) ? -1 : 0;
}
/* sort by decreasing RSS */
static int compare_mem(struct taskstat_delta *t1, struct taskstat_delta *t2)
{
int a = (t1->utime + t1->stime) ? t1->rss / (t1->utime + t1->stime) : 0;
int b = (t2->utime + t2->stime) ? t2->rss / (t2->utime + t2->stime) : 0;
return (a < b) ? 1 : (a > b) ? -1 : 0;
}
/*
* This implementation allows to have items with identical keys in tree,
* hopefully this does not break rbtrees.
*/
int cache_add(struct taskstat_delta *data)
{
struct rb_node **new = &(cache_tree.rb_node), *parent = NULL;
/* Figure out where to put new node */
while (*new) {
struct taskstat_delta *tmp = container_of(*new, struct taskstat_delta, node);
int result = compare_fn(data, tmp);
parent = *new;
if (result < 0)
new = &((*new)->rb_left);
else if (result >= 0)
new = &((*new)->rb_right);
}
/* Add new node and rebalance tree. */
rb_link_node(&data->node, parent, new);
rb_insert_color(&data->node, &cache_tree);
return 1;
}
void cache_init(void)
{
switch (opt_sort) {
case OPT_SORT_TID:
compare_fn = &compare_tid;
break;
case OPT_SORT_NAME:
compare_fn = &compare_name;
break;
case OPT_SORT_TIME:
compare_fn = &compare_time;
break;
case OPT_SORT_IO:
compare_fn = &compare_io;
break;
case OPT_SORT_MEM:
compare_fn = &compare_mem;
break;
default:
compare_fn = &compare_time;
}
}
struct taskstat_delta *cache_walk(struct taskstat_delta *last)
{
struct rb_node *node = (last) ? rb_next(&last->node) : rb_first(&cache_tree);
if (!node)
return NULL;
else
return rb_entry(node, struct taskstat_delta, node);
}
/* remove all elements after cycle is done */
void cache_flush(void)
{
struct taskstat_delta *data;
struct rb_node *node;
do {
node = rb_first(&cache_tree);
if (!node)
continue;
data = rb_entry(node, struct taskstat_delta, node);
rb_erase(&data->node, &cache_tree);
free(data);
} while (rb_first(&cache_tree) != NULL);
}