00001
00002
00011
00012
00013
00014
00015
00035
00036 #include <l4/env/errno.h>
00037 #include <l4/sys/syscalls.h>
00038 #include <l4/thread/thread.h>
00039 #include <l4/semaphore/semaphore.h>
00040 #include <l4/lock/lock.h>
00041
00042 #include <l4/dde_linux/dde.h>
00043
00044
00045 #include <linux/config.h>
00046 #include <linux/mm.h>
00047 #include <linux/kernel_stat.h>
00048 #include <linux/interrupt.h>
00049 #include <linux/smp_lock.h>
00050 #include <linux/init.h>
00051 #include <linux/tqueue.h>
00052
00053
00054 #include "internal.h"
00055 #include "__config.h"
00056
00068 static l4thread_t softirq_tid[SOFTIRQ_THREADS];
00069
00071 static l4semaphore_t softirq_sema = L4SEMAPHORE_LOCKED;
00072
00109 void __cpu_raise_softirq(unsigned cpu, int nr)
00110 {
00111 l4semaphore_up(&softirq_sema);
00112 }
00113
00122 void raise_softirq(int nr)
00123 {
00124
00125
00126 cli();
00127 __cpu_raise_softirq(0, nr);
00128 sti();
00129 }
00130
00172 static struct tasklet_head tasklet_vec[NR_CPUS];
00173
00176 static struct tasklet_head tasklet_hi_vec[NR_CPUS];
00177
00179 static void tasklet_action(void)
00180 {
00181 struct tasklet_struct *list;
00182
00183 LOGd(DEBUG_SOFTIRQ, "low prio tasklet exec entrance");
00184
00185 cli();
00186 list = tasklet_vec[0].list;
00187 tasklet_vec[0].list = NULL;
00188 sti();
00189
00190 while (list != NULL)
00191 {
00192 struct tasklet_struct *t = list;
00193
00194 list = list->next;
00195
00196 if (tasklet_trylock(t))
00197 {
00198 if (atomic_read(&t->count) == 0)
00199 {
00200 clear_bit(TASKLET_STATE_SCHED, &t->state);
00201
00202 t->func(t->data);
00203 tasklet_unlock(t);
00204 continue;
00205 }
00206 tasklet_unlock(t);
00207 }
00208 cli();
00209 t->next = tasklet_vec[0].list;
00210 tasklet_vec[0].list = t;
00211 __cpu_raise_softirq(0, TASKLET_SOFTIRQ);
00212 sti();
00213 }
00214 }
00215
00220 static int tasklet_hi_action(void)
00221 {
00222 struct tasklet_struct *list;
00223
00224 if (!tasklet_hi_vec[0].list)
00225
00226 return 0;
00227
00228 LOGd(DEBUG_SOFTIRQ, "hi prio tasklet exec entrance");
00229
00230 cli();
00231 list = tasklet_hi_vec[0].list;
00232 tasklet_hi_vec[0].list = NULL;
00233 sti();
00234
00235 while (list != NULL)
00236 {
00237 struct tasklet_struct *t = list;
00238
00239 list = list->next;
00240
00241 if (tasklet_trylock(t))
00242 {
00243 if (atomic_read(&t->count) == 0)
00244 {
00245 clear_bit(TASKLET_STATE_SCHED, &t->state);
00246
00247 t->func(t->data);
00248 tasklet_unlock(t);
00249 continue;
00250 }
00251 tasklet_unlock(t);
00252 }
00253 cli();
00254 t->next = tasklet_hi_vec[0].list;
00255 tasklet_hi_vec[0].list = t;
00256 __cpu_raise_softirq(0, HI_SOFTIRQ);
00257 sti();
00258 }
00259
00260 return !0;
00261 }
00262
00270 void tasklet_init(struct tasklet_struct *t,
00271 void (*func) (unsigned long), unsigned long data)
00272 {
00273 t->func = func;
00274 t->data = data;
00275 t->state = 0;
00276 atomic_set(&t->count, 0);
00277 }
00278
00284 void tasklet_kill(struct tasklet_struct *t)
00285 {
00286
00287
00288
00289 while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
00290 {
00291 #if 0
00292 current->state = TASK_RUNNING;
00293 do
00294 {
00295 current->policy |= SCHED_YIELD;
00296 schedule();
00297 }
00298 while (test_bit(TASKLET_STATE_SCHED, &t->state));
00299 #else
00300 do
00301 {
00302
00303 # if SCHED_YIELD_OPT
00304 l4thread_usleep(SCHED_YIELD_TO);
00305 # else
00306 l4_yield();
00307 # endif
00308 }
00309 while (test_bit(TASKLET_STATE_SCHED, &t->state));
00310 #endif
00311 }
00312 tasklet_unlock_wait(t);
00313 clear_bit(TASKLET_STATE_SCHED, &t->state);
00314 }
00315
00324 void tasklet_schedule(struct tasklet_struct *t)
00325 {
00326 if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
00327 {
00328 cli();
00329 t->next = tasklet_vec[0].list;
00330 tasklet_vec[0].list = t;
00331
00332
00333 if (!t->next)
00334 __cpu_raise_softirq(0, TASKLET_SOFTIRQ);
00335 sti();
00336 }
00337 }
00338
00339
00348
00349 void tasklet_hi_schedule(struct tasklet_struct *t)
00350 {
00351 if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
00352 {
00353 cli();
00354 t->next = tasklet_hi_vec[0].list;
00355 tasklet_hi_vec[0].list = t;
00356
00357
00358 if (!t->next)
00359 __cpu_raise_softirq(0, HI_SOFTIRQ);
00360 sti();
00361 }
00362 }
00363
00380 spinlock_t tqueue_lock = SPIN_LOCK_UNLOCKED;
00381
00387 void __run_task_queue(task_queue * list)
00388 {
00389 struct list_head head, *next;
00390 unsigned long flags;
00391
00392 spin_lock_irqsave(&tqueue_lock, flags);
00393 list_add(&head, list);
00394 list_del_init(list);
00395 spin_unlock_irqrestore(&tqueue_lock, flags);
00396
00397 next = head.next;
00398 while (next != &head)
00399 {
00400 void (*f) (void *);
00401 struct tq_struct *p;
00402 void *data;
00403
00404 p = list_entry(next, struct tq_struct, list);
00405 next = next->next;
00406 f = p->routine;
00407 data = p->data;
00408 wmb();
00409 p->sync = 0;
00410 if (f)
00411 f(data);
00412 }
00413 }
00414
00425 static void dde_softirq_thread(int num)
00426 {
00427 softirq_tid[num] = l4thread_myself();
00428
00429 if (l4dde_process_add_worker())
00430 Panic("l4dde_process_add_worker() failed");
00431
00432 ++local_bh_count(smp_processor_id());
00433
00434
00435 if (l4thread_started(NULL)<0)
00436 Panic("softirq thread startup failed!");
00437
00438 LOGd(DEBUG_MSG, "dde_softirq_thread[%d] "l4util_idfmt" running.", num,
00439 l4util_idstr(l4thread_l4_id(l4thread_myself())));
00440
00441
00442 while (1)
00443 {
00444
00445 l4semaphore_down(&softirq_sema);
00446
00447
00448 if (!tasklet_hi_action())
00449 tasklet_action();
00450 }
00451 }
00452
00462 int l4dde_softirq_init()
00463 {
00464 #if !(SOFTIRQ_THREADS == 1)
00465 #error SOFTIRQ_THREADS has to be 1
00466 #else
00467 int err;
00468
00469
00470 static int _initialized = 0;
00471
00472 if (_initialized)
00473 return 0;
00474
00475
00476 err = l4thread_create_long(L4THREAD_INVALID_ID,
00477 (l4thread_fn_t) dde_softirq_thread,
00478 ".softirq",
00479 L4THREAD_INVALID_SP,
00480 L4THREAD_DEFAULT_SIZE,
00481 L4THREAD_DEFAULT_PRIO,
00482 (void *) 0,
00483 L4THREAD_CREATE_SYNC);
00484
00485 if (err < 0)
00486 return err;
00487
00488 ++_initialized;
00489 return 0;
00490 #endif
00491 }