Fixed few more anomalies with threaded irqs.

There is a bug that causes the sleeping irq
thread to never wake up. Investigating.
This commit is contained in:
Bahadir Balban
2009-12-13 20:35:04 +02:00
parent 0c4bd69357
commit d85ccdb3fe
10 changed files with 66 additions and 12 deletions

View File

@@ -12,6 +12,7 @@
#include <l4/generic/tcb.h>
#include INC_GLUE(message.h)
#include <l4/lib/wait.h>
#include INC_SUBARCH(irq.h)
/*
* Default function that handles userspace
@@ -57,12 +58,13 @@ int irq_thread_notify(struct irq_desc *desc)
utcb = (struct utcb *)desc->task->utcb_address;
/* Atomic increment (See above comments) with no wraparound */
if (utcb->notify[desc->task_notify_slot] != TASK_NOTIFY_MAX)
if (utcb->notify[desc->task_notify_slot] != TASK_NOTIFY_MAXVALUE)
utcb->notify[desc->task_notify_slot]++;
/* Async wake up any waiter irq threads */
wake_up(&desc->task->wqh_notify, WAKEUP_ASYNC);
wake_up(&desc->wqh_irq, WAKEUP_ASYNC);
BUG_ON(!irqs_enabled());
return 0;
}
@@ -111,10 +113,13 @@ int irq_wait(l4id_t irq_index)
/* Wait until the irq changes slot value */
WAIT_EVENT(&desc->wqh_irq,
!utcb->notify[desc->task_notify_slot],
utcb->notify[desc->task_notify_slot] != 0,
ret);
return ret;
printk("Didn't sleep. utcb->notify[%d]=%d\n", desc->task_notify_slot, utcb->notify[desc->task_notify_slot]);
if (ret < 0)
return ret;
else
return l4_atomic_dest_readb(&utcb->notify[desc->task_notify_slot]);
}

View File

@@ -4,7 +4,7 @@
Import('env')
# The set of source files associated with this SConscript file.
src_local = ['mm.c', 'mmu_ops.S', 'mutex.S']
src_local = ['mm.c', 'mmu_ops.S', 'mutex.S', 'irq.S']
obj = env.Object(src_local)
Return('obj')

27
src/arch/arm/v5/irq.S Normal file
View File

@@ -0,0 +1,27 @@
#include INC_ARCH(asm.h)
/*
* r0 = unsigned long *state, stores current irq state.
*/
BEGIN_PROC(irq_local_disable_save)
mov r1, r0 @ Move address of state to r1
mrs r2, cpsr_fc @ Read cpsr
orr r3, r2, #0x80 @ Disable irq bit in cpsr
msr cpsr_fc, r3 @ Write to cpsr
str r2, [r1] @ Store original cpsr in r2 to state
mov pc, lr
END_PROC(irq_local_disable_save)
/*
* r0 = byte address to read from.
*/
BEGIN_PROC(l4_atomic_dest_readb)
mov r1, r0 @ Move byte address to r1
mov r2, #0 @ Move 0 to r2
swpb r0, r2, [r1] @ Write 0 to byte location, while reading its value to r0
mov pc, lr @ Return byte location value
END_PROC(l4_atomic_dest_readb)

View File

@@ -42,6 +42,9 @@ int irq_register(struct ktcb *task, int notify_slot, l4id_t irq_index)
this_desc->task = task;
this_desc->task_notify_slot = notify_slot;
/* Setup irq desc waitqueue */
waitqueue_head_init(&this_desc->wqh_irq);
/* Enable the irq */
irq_enable(irq_index);

View File

@@ -38,6 +38,7 @@ void sched_lock_runqueues(unsigned long *irqflags)
{
spin_lock_irq(&scheduler.sched_rq[0].lock, irqflags);
spin_lock(&scheduler.sched_rq[1].lock);
BUG_ON(irqs_enabled());
}
void sched_unlock_runqueues(unsigned long irqflags)

View File

@@ -165,7 +165,7 @@ void wake_up(struct waitqueue_head *wqh, unsigned int flags)
task_unset_wqh(sleeper);
if (flags & WAKEUP_INTERRUPT)
sleeper->flags |= TASK_INTERRUPTED;
//printk("(%d) Waking up (%d)\n", current->tid, sleeper->tid);
printk("(%d) Waking up (%d)\n", current->tid, sleeper->tid);
spin_unlock_irq(&wqh->slock, irqflags);
if (flags & WAKEUP_SYNC)