Rev 2330 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2330 | Rev 2430 | ||
|---|---|---|---|
| Line 28... | Line 28... | ||
| 28 | */ |
28 | */ |
| 29 | 29 | ||
| 30 | /** @addtogroup genericddi |
30 | /** @addtogroup genericddi |
| 31 | * @{ |
31 | * @{ |
| 32 | */ |
32 | */ |
| 33 | /** @file |
33 | /** @file tasklet.c |
| - | 34 | * @brief Tasklet implementation |
|
| 34 | */ |
35 | */ |
| 35 | 36 | ||
| 36 | #include <arch.h> |
37 | #include <arch.h> |
| 37 | #include <config.h> |
38 | #include <config.h> |
| 38 | #include <arch/types.h> |
39 | #include <arch/types.h> |
| Line 89... | Line 90... | ||
| 89 | void tasklet_run_tasklet_thread(task_t * kernel_task) |
90 | void tasklet_run_tasklet_thread(task_t * kernel_task) |
| 90 | { |
91 | { |
| 91 | //create the tasklet_thread, it's wired to the current cpu, we'll migrate it ourselves |
92 | //create the tasklet_thread, it's wired to the current cpu, we'll migrate it ourselves |
| 92 | thread_t* t= thread_create(&tasklet_thread, NULL, kernel_task, THREAD_FLAG_WIRED, "tasklet_thread", false); |
93 | thread_t* t= thread_create(&tasklet_thread, NULL, kernel_task, THREAD_FLAG_WIRED, "tasklet_thread", false); |
| 93 | if (t==NULL) { |
94 | if (t==NULL) { |
| 94 | //wtf? |
- | |
| 95 | panic_printf("tasklet thread not created\n"); |
95 | panic_printf("tasklet thread not created\n"); |
| 96 | } else { |
96 | } else { |
| 97 | spinlock_lock(&t->lock); |
97 | spinlock_lock(&t->lock); |
| - | 98 | //we'll default on the first CPU |
|
| 98 | t->cpu = &cpus[0]; |
99 | t->cpu = &cpus[0]; |
| 99 | t->priority = TASKLET_THREAD_PRIORITY; |
100 | t->priority = TASKLET_THREAD_PRIORITY; |
| 100 | spinlock_unlock(&t->lock); |
101 | spinlock_unlock(&t->lock); |
| 101 | thread_ready(t); |
102 | thread_ready(t); |
| 102 | } |
103 | } |
| Line 112... | Line 113... | ||
| 112 | cpu_t *cpu; |
113 | cpu_t *cpu; |
| 113 | #endif |
114 | #endif |
| 114 | waitq_t wq; |
115 | waitq_t wq; |
| 115 | waitq_initialize(&wq); |
116 | waitq_initialize(&wq); |
| 116 | 117 | ||
| - | 118 | //the infinite loop |
|
| 117 | while (true) { |
119 | while (true) { |
| - | 120 | //execute any scheduled tasklets |
|
| 118 | tasklet_do(); |
121 | tasklet_do(); |
| 119 | #ifdef CONFIG_SMP |
122 | #ifdef CONFIG_SMP |
| - | 123 | //check whether other CPUs have tasklets to execute |
|
| 120 | if (config.cpu_active>1) { |
124 | if (config.cpu_active>1) { |
| 121 | current_cpu = CPU->id; |
125 | current_cpu = CPU->id; |
| 122 | //find the first cpu with nonempty tasklet_list |
126 | //find the first cpu with nonempty tasklet_list |
| 123 | for (new_cpu = (current_cpu + 1) % config.cpu_active; new_cpu!=current_cpu && tasklet_list[new_cpu]==0 && cpus[new_cpu].active; |
127 | for (new_cpu = (current_cpu + 1) % config.cpu_count; new_cpu!=current_cpu && tasklet_list[new_cpu]==0 ; |
| 124 | new_cpu=(new_cpu + 1)% config.cpu_active); |
128 | new_cpu=(new_cpu + 1)% config.cpu_count); |
| 125 | 129 | ||
| - | 130 | //if we found a CPU with unsatisfied tasklet schedule to run there. It must be active! |
|
| 126 | if (new_cpu!=current_cpu) { |
131 | if (new_cpu!=current_cpu && cpus[new_cpu].active) { |
| 127 | //we need to migrate this thread to CPU with id new_cpu |
132 | //we need to migrate this thread to CPU with id new_cpu |
| 128 | cpu = &cpus[new_cpu]; |
133 | cpu = &cpus[new_cpu]; |
| 129 | 134 | ||
| 130 | spinlock_lock(&THREAD->lock); |
135 | spinlock_lock(&THREAD->lock); |
| 131 | //put tasklet_thread on the new_cpu |
136 | //move tasklet_thread on the new_cpu |
| 132 | THREAD->cpu = cpu; |
137 | THREAD->cpu = cpu; |
| 133 | spinlock_unlock(&THREAD->lock); |
138 | spinlock_unlock(&THREAD->lock); |
| 134 | } |
139 | } |
| 135 | } |
140 | } |
| 136 | #endif |
141 | #endif |
| Line 201... | Line 206... | ||
| 201 | } |
206 | } |
| 202 | 207 | ||
| 203 | 208 | ||
| 204 | 209 | ||
| 205 | 210 | ||
| 206 | /** Executes scheduled enabled tasklets on current CPU */ |
211 | /** Executes scheduled enabled tasklets on current CPU |
| - | 212 | * this function could be called from other parts of kernel */ |
|
| 207 | void tasklet_do(void) |
213 | void tasklet_do(void) |
| 208 | { |
214 | { |
| 209 | spinlock_lock(&tasklet_lock); |
215 | spinlock_lock(&tasklet_lock); |
| 210 | tasklet_descriptor_t* t = tasklet_list[CPU->id]; |
216 | tasklet_descriptor_t* t = tasklet_list[CPU->id]; |
| 211 | //printf("."); |
- | |
| 212 | if (t) { |
217 | if (t) { |
| 213 | //empty the tasklet_list |
218 | //empty the tasklet_list |
| 214 | tasklet_list[CPU->id]=0; |
219 | tasklet_list[CPU->id]=0; |
| 215 | spinlock_unlock(&tasklet_lock); |
220 | spinlock_unlock(&tasklet_lock); |
| 216 | do { |
221 | do { |
| 217 | if (!(t->state & TASKLET_STATE_DISABLED)) { |
222 | if (!(t->state & TASKLET_STATE_DISABLED)) { |
| 218 | if (t->func) { |
223 | if (t->func) { |
| 219 | t->state = TASKLET_STATE_RUNNING; |
224 | t->state = TASKLET_STATE_RUNNING; |
| 220 | t->func(t->data); |
225 | t->func(t->data); |
| 221 | //clear running flag, set not active - the tasklet can disable itself |
226 | //clear running flag, set not active |
| 222 | //thats why we don't just set it as not active |
- | |
| 223 | t->state &= ~TASKLET_STATE_RUNNING; |
227 | t->state &= ~TASKLET_STATE_RUNNING; |
| 224 | t->state |= TASKLET_STATE_NOTACTIVE; |
228 | t->state |= TASKLET_STATE_NOTACTIVE; |
| 225 | } else |
229 | } else |
| 226 | panic_printf("tasklet func NULL\n"); |
230 | panic_printf("tasklet func NULL\n"); |
| 227 | } else { |
231 | } else { |
| Line 238... | Line 242... | ||
| 238 | else |
242 | else |
| 239 | spinlock_unlock(&tasklet_lock); |
243 | spinlock_unlock(&tasklet_lock); |
| 240 | } |
244 | } |
| 241 | 245 | ||
| 242 | /** Frees the tasklet structure when no longer needed. The function doesn't provide |
246 | /** Frees the tasklet structure when no longer needed. The function doesn't provide |
| 243 | * any synchronization, the caller must be sure, the tasklet is not scheduled. |
247 | * any synchronization, the caller must be sure, that the tasklet is not scheduled. |
| 244 | * |
248 | * |
| 245 | * @param tasklet to be freed |
249 | * @param tasklet to be freed |
| 246 | */ |
250 | */ |
| 247 | void tasklet_free(tasklet_descriptor_t* t) |
251 | void tasklet_free(tasklet_descriptor_t* t) |
| 248 | { |
252 | { |