Rev 2265 | Rev 2315 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2265 | Rev 2309 | ||
---|---|---|---|
Line 41... | Line 41... | ||
41 | #include <synch/spinlock.h> |
41 | #include <synch/spinlock.h> |
42 | #include <time/delay.h> |
42 | #include <time/delay.h> |
43 | #include <panic.h> |
43 | #include <panic.h> |
44 | #include <print.h> |
44 | #include <print.h> |
45 | 45 | ||
46 | typedef struct { |
- | |
47 | uint32_t current_batch; |
- | |
48 | uint32_t completed_batch; |
- | |
49 | bool next_batch_waiting; |
- | |
50 | } rcu_global_t; |
46 | SPINLOCK_INITIALIZE(rcu_global_lock); |
51 | 47 | ||
52 | typedef struct rcu_callback_list { |
48 | typedef struct rcu_callback_list { |
53 | struct rcu_callback_list* next; |
49 | struct rcu_callback_list* next; |
54 | void (*func)(void*); |
50 | void (*func)(void*); |
55 | void* data; |
51 | void* data; |
56 | bool* cpu_mask; |
- | |
57 | } rcu_callback_list_t; |
52 | } rcu_callback_list_t; |
58 | 53 | ||
59 | - | ||
60 | typedef struct { |
54 | typedef struct { |
61 | uint32_t current_batch_number; |
55 | #ifdef CONFIG_SMP |
62 | uint32_t QS_passed; |
56 | bool* cpu_mask; |
63 | bool QS_pending; |
57 | #endif |
64 | rcu_callback_list_t* next_batch, *current_batch, *done_batch; |
58 | rcu_callback_list_t* next_batch, *current_batch, *done_batch; |
65 | } rcu_percpu_t; |
59 | } rcu_global_t; |
- | 60 | ||
66 | 61 | ||
67 | rcu_global_t _rcu_global; |
62 | rcu_global_t* _rcu_global; |
68 | rcu_percpu_t* _rcu_cpu_lists; |
63 | tasklet_descriptor_t* rcu_tasklet_desc; |
69 | 64 | ||
70 | void rcu_init(void) |
65 | void rcu_init(void) |
71 | { |
66 | { |
- | 67 | #ifdef CONFIG_SMP |
|
- | 68 | int i; |
|
- | 69 | #endif |
|
- | 70 | ||
72 | _rcu_cpu_lists = malloc(sizeof(rcu_percpu_t)*config.cpu_count,0); |
71 | _rcu_global = malloc(sizeof(rcu_global_t),0); |
73 | _rcu_global.completed_batch = -1; |
72 | _rcu_global->done_batch = NULL; |
74 | _rcu_global.current_batch = -1; |
73 | _rcu_global->current_batch = NULL; |
75 | _rcu_global.next_batch_waiting = -1; |
74 | _rcu_global->next_batch = NULL; |
- | 75 | spinlock_initialize(&rcu_global_lock, "rcu_global_lock"); |
|
- | 76 | ||
- | 77 | rcu_tasklet_desc = tasklet_register(&rcu_tasklet, NULL); |
|
- | 78 | tasklet_disable(rcu_tasklet_desc); |
|
- | 79 | ||
- | 80 | #ifdef CONFIG_SMP |
|
- | 81 | _rcu_global->cpu_mask = malloc (sizeof(bool)*config.cpu_count,0); |
|
- | 82 | for (i=0;i<config.cpu_count;i++) { |
|
- | 83 | _rcu_global->cpu_mask[i]=false; |
|
- | 84 | } |
|
- | 85 | #else |
|
- | 86 | tasklet_schedule(rcu_tasklet_desc); |
|
- | 87 | ||
- | 88 | #endif |
|
- | 89 | tasklet_enable(rcu_tasklet_desc); |
|
76 | } |
90 | } |
77 | 91 | ||
78 | void rcu_synchronize(void) |
92 | void rcu_synchronize(void) |
79 | { |
93 | { |
- | 94 | #ifdef CONFIG_SMP |
|
80 | waitq_t wq; |
95 | waitq_t *wq = malloc(sizeof(waitq_t),0); |
81 | waitq_initialize(&wq); |
96 | waitq_initialize(wq); |
82 | rcu_sync_callback(rcu_synchronize_callback_function, &wq); |
97 | rcu_sync_callback(&rcu_synchronize_callback_function, wq); |
- | 98 | printf("going to sleep\n"); |
|
83 | waitq_sleep(&wq); |
99 | waitq_sleep(wq); |
- | 100 | printf("woken up\n"); |
|
- | 101 | #endif |
|
84 | } |
102 | } |
85 | 103 | ||
- | 104 | #ifdef CONFIG_SMP |
|
86 | void rcu_synchronize_callback_function(void* waitq) |
105 | void rcu_synchronize_callback_function(void* waitq) |
87 | { |
106 | { |
- | 107 | printf("waking up\n"); |
|
88 | waitq_wakeup(((waitq_t*)waitq), true); |
108 | waitq_wakeup(((waitq_t*)waitq), WAKEUP_ALL_INC_MISSED); |
89 | } |
109 | } |
- | 110 | #endif |
|
90 | 111 | ||
91 | void rcu_sync_callback(void (*func)(void* data), void* data) |
112 | void rcu_sync_callback(void (*func)(void* data), void* data) |
92 | { |
113 | { |
- | 114 | #ifndef CONFIG_SMP |
|
- | 115 | func(data); |
|
- | 116 | #else |
|
93 | int i; |
117 | int i; |
94 | rcu_callback_list_t *rd; |
118 | rcu_callback_list_t *rd; |
95 | rd = malloc(sizeof(rcu_callback_list_t), 0); |
119 | rd = malloc(sizeof(rcu_callback_list_t), 0); |
96 | rd->func = func; |
120 | rd->func = func; |
97 | rd->data = data; |
121 | rd->data = data; |
98 | rd->next = NULL; |
122 | rd->next = NULL; |
- | 123 | printf("synccallback locking \n"); |
|
- | 124 | spinlock_lock(&rcu_global_lock); |
|
- | 125 | rd->next = _rcu_global->next_batch; |
|
- | 126 | _rcu_global->next_batch = rd; |
|
- | 127 | ||
- | 128 | if (_rcu_global->current_batch == NULL) { |
|
- | 129 | _rcu_global->current_batch = _rcu_global->next_batch; |
|
- | 130 | _rcu_global->next_batch = NULL; |
|
- | 131 | printf("setting callback %x as current\n",&rd->func); |
|
- | 132 | for (i=0;i<config.cpu_count;i++) |
|
- | 133 | _rcu_global->cpu_mask[i]=false; |
|
99 | 134 | ||
100 | rd->cpu_mask = malloc (sizeof(bool)*config.cpu_count,0); |
135 | //we've surely passed the quiescent point just by running this method |
101 | for (i=0;i<config.cpu_count;i++) |
- | |
102 | rd->cpu_mask[i]=false; |
136 | rcu_passQS(); |
103 | 137 | } |
|
104 | i = ++(_rcu_global.current_batch); |
- | |
105 | _rcu_global.next_batch_waiting = true; |
- | |
106 | - | ||
107 | rd->next = _rcu_cpu_lists[0].next_batch; |
- | |
108 | for (i=0;i<config.cpu_count;i++) { |
138 | for (i=0;i<config.cpu_count;i++) { |
- | 139 | tasklet_schedule_SMP(rcu_tasklet_desc, i); |
|
- | 140 | } |
|
- | 141 | spinlock_unlock(&rcu_global_lock); |
|
- | 142 | printf ("sync callback called,unlocking, state:%x \n",rcu_tasklet_desc->state); |
|
- | 143 | #endif |
|
- | 144 | } |
|
- | 145 | ||
- | 146 | //TODO: polishing, comments |
|
- | 147 | ||
- | 148 | void rcu_tasklet(void* data) |
|
- | 149 | { |
|
- | 150 | rcu_callback_list_t* rd; |
|
- | 151 | bool passed_all_QS; |
|
- | 152 | #ifdef CONFIG_SMP |
|
- | 153 | int i; |
|
- | 154 | #endif |
|
- | 155 | rcu_passQS(); |
|
- | 156 | passed_all_QS = true; |
|
- | 157 | printf("tasklet locking \n"); |
|
- | 158 | spinlock_lock(&rcu_global_lock); |
|
- | 159 | #ifdef CONFIG_SMP |
|
- | 160 | ||
- | 161 | for (i = 0; i < config.cpu_active; i++) |
|
- | 162 | passed_all_QS &= _rcu_global->cpu_mask[i]; |
|
- | 163 | #endif |
|
- | 164 | if (passed_all_QS) { |
|
109 | _rcu_cpu_lists[i].next_batch = rd; |
165 | if (_rcu_global->done_batch) { |
- | 166 | rd = _rcu_global->done_batch; |
|
- | 167 | while (rd->next) rd = rd->next; |
|
- | 168 | ||
- | 169 | //append the current list to done list |
|
- | 170 | rd->next = _rcu_global->current_batch; |
|
- | 171 | } else |
|
- | 172 | _rcu_global->done_batch = _rcu_global->current_batch; |
|
- | 173 | printf("setting callback %x as done\n",&_rcu_global->current_batch->func); |
|
110 | _rcu_cpu_lists[i].QS_pending = true; |
174 | _rcu_global->current_batch = NULL; |
111 | } |
175 | } |
112 | 176 | ||
- | 177 | _rcu_global->current_batch = _rcu_global->next_batch; |
|
- | 178 | _rcu_global->next_batch = NULL; |
|
- | 179 | ||
- | 180 | if (_rcu_global->current_batch == NULL) { |
|
- | 181 | //there are no rcu callbacks registered, there is no need to monitor QS |
|
- | 182 | printf("tasklet idle disabling \n"); |
|
113 | //TODO:tasklet, after_thread_ran, polishing |
183 | // tasklet_disable(rcu_tasklet_desc); |
- | 184 | spinlock_unlock(&rcu_global_lock); |
|
- | 185 | } else |
|
- | 186 | spinlock_unlock(&rcu_global_lock); |
|
- | 187 | printf("tasklet unlocking \n"); |
|
114 | } |
188 | } |
115 | 189 | ||
- | 190 | inline void rcu_passQS(void) |
|
- | 191 | { |
|
- | 192 | #ifdef CONFIG_SMP |
|
- | 193 | _rcu_global->cpu_mask[CPU->id] = true; |
|
- | 194 | #endif |
|
- | 195 | } |
|
- | 196 | ||
- | 197 | void rcu_run_callbacks(void) |
|
- | 198 | { |
|
- | 199 | rcu_callback_list_t* rd; |
|
- | 200 | rcu_passQS(); |
|
- | 201 | if (_rcu_global->done_batch) { |
|
- | 202 | printf("."); |
|
- | 203 | spinlock_lock(&rcu_global_lock); |
|
- | 204 | for (rd = _rcu_global->done_batch; rd; rd=rd->next) { |
|
- | 205 | printf("calling %x \n",&rd->func); |
|
- | 206 | rd->func(&rd->data); |
|
- | 207 | } |
|
- | 208 | _rcu_global->done_batch = NULL; |
|
- | 209 | spinlock_unlock(&rcu_global_lock); |
|
- | 210 | printf(":"); |
|
- | 211 | } |
|
- | 212 | } |
|
- | 213 | ||
- | 214 |