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
|
#include <litmus/way_tracker.h>
#include <asm/io.h>
#include <litmus/color.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/kgdb.h>
#include <litmus/litmus.h>
#include <litmus/color.h>
static raw_spinlock_t lock;
static unsigned long *ways;
static int peek_next_way(unsigned int color)
{
int ret;
BUG_ON(color > color_cache_info.nr_colors);
ret = find_first_bit(&ways[color], sizeof(unsigned long)*8);
if (ret == sizeof(unsigned long)*8) {
return -1;
} else {
return ret;
}
}
static int take_next_way(unsigned int color)
{
int idx;
raw_spin_lock(&lock);
idx = peek_next_way(color);
if (idx != -1) {
clear_bit(idx, &ways[color]);
TRACE("Took, now %lu free of color %d\n", hweight_long(ways[color]), color);
} else {
printk(KERN_WARNING "Vury bad\n");
/* Seriously bad. */
#ifdef CONFIG_KGDB
kgdb_breakpoint();
#endif
BUG();
}
raw_spin_unlock(&lock);
return idx;
}
static void release_way(unsigned int color, int way)
{
BUG_ON(way < 0 || way > color_cache_info.ways);
raw_spin_lock(&lock);
__set_bit(way, &ways[color]);
TRACE("Released, now %lu free of color %d\n", hweight_long(ways[color]), color);
raw_spin_unlock(&lock);
}
void color_page_info_take_ways(struct task_struct *t)
{
struct color_page_info *cur;
list_for_each_entry(cur, &tsk_rt(t)->color_page_info_list, list) {
cur->way = take_next_way(cur->color);
TRACE_TASK(t, "assign color %d way %d for info %p\n",
cur->color, cur->way, cur);
}
}
void color_page_info_release_ways(struct task_struct *t)
{
struct color_page_info *cur;
list_for_each_entry(cur, &tsk_rt(t)->color_page_info_list, list) {
release_way(cur->color, cur->way);
TRACE_TASK(t, "release color %d way %d for info %p\n",
cur->color, cur->way, cur);
}
}
void reset_way_tracker(void)
{
int color, unused;
for (color = 0; color < color_cache_info.nr_colors; ++color) {
unused = sizeof(unsigned long)*8 - color_cache_info.ways;
ways[color] = ULONG_MAX >> unused;
}
}
static int __init init_way_tracker(void)
{
int size;
BUG_ON(!color_cache_info.nr_colors);
BUG_ON(color_cache_info.ways > sizeof(unsigned long)*8);
printk(KERN_INFO "Starting way tracker\n");
size = sizeof(unsigned long) * color_cache_info.nr_colors;
ways = kmalloc(size, GFP_ATOMIC);
reset_way_tracker();
raw_spin_lock_init(&lock);
return 0;
}
module_init(init_way_tracker);
|