diff --git a/kernel-src/include/kernel/dpc.h b/kernel-src/include/kernel/dpc.h index a7e6a879..1d14bdbe 100644 --- a/kernel-src/include/kernel/dpc.h +++ b/kernel-src/include/kernel/dpc.h @@ -15,7 +15,8 @@ typedef struct _dpc_t { dpcarg_t arg; } dpc_t; -void dpc_enqueue(dpc_t *dpc, dpcfn_t, dpcarg_t); +void dpc_prepare(dpc_t *dpc, dpcfn_t fn); +void dpc_enqueue(dpc_t *dpc, dpcarg_t arg); void dpc_dequeue(dpc_t *dpc); void dpc_init(); diff --git a/kernel-src/include/kernel/timer.h b/kernel-src/include/kernel/timer.h index 46cebc68..77a388e6 100644 --- a/kernel-src/include/kernel/timer.h +++ b/kernel-src/include/kernel/timer.h @@ -11,9 +11,8 @@ typedef struct timerentry_t { struct timerentry_t *next; time_t absolutetick; time_t repeatus; - dpcfn_t fn; - dpcarg_t arg; dpc_t dpc; + dpcarg_t arg; bool fired; } timerentry_t; diff --git a/kernel-src/io/block/ahci.c b/kernel-src/io/block/ahci.c index f66aed5f..02fa12c1 100644 --- a/kernel-src/io/block/ahci.c +++ b/kernel-src/io/block/ahci.c @@ -204,7 +204,7 @@ void ahci_dpc(context_t *, dpcarg_t arg) { } // notify waiters about command completion - while (port_data->waiters[port_data->command_waiting] && + while (port_data->waiters[port_data->command_waiting] && (port_data->ahci->ports[port].ci & (1 << port_data->command_waiting)) == 0) { thread_t *thread = port_data->waiters[port_data->command_waiting]; port_data->waiters[port_data->command_waiting] = NULL; @@ -230,7 +230,7 @@ void ahci_isr(isr_t *isr, context_t *) { if (ahci->port_data[i] == NULL) continue; - dpc_enqueue(&ahci->port_data[i]->dpc, ahci_dpc, ahci->port_data[i]); + dpc_enqueue(&ahci->port_data[i]->dpc, ahci->port_data[i]); ports_pending &= ~(1 << i); ahci->ports[i].is = ahci->ports[i].is; @@ -413,7 +413,7 @@ static void init_port(ahci_t *ahci, int port) { return; } - ahci->port_data[port]->sector_count = (uint64_t)identify->lba48_size[0] | ((uint64_t)identify->lba48_size[1] << 16) | + ahci->port_data[port]->sector_count = (uint64_t)identify->lba48_size[0] | ((uint64_t)identify->lba48_size[1] << 16) | ((uint64_t)identify->lba48_size[2] << 32) | ((uint64_t)identify->lba48_size[3] << 48); printf("ahci%dp%d: ATA drive with %lu sectors\n", ahci->id, port, ahci->port_data[port]->sector_count); @@ -549,7 +549,6 @@ static void init_controller(pcienum_t *pci_enum) { continue; } - // program command list base void *cmd_ptr = (void *)((uintptr_t)command_slot_mem + command_slot_offset); memset(MAKE_HHDM(cmd_ptr), 0, 1024); @@ -609,6 +608,7 @@ static void init_controller(pcienum_t *pci_enum) { port_data->command_list = MAKE_HHDM(cmd_ptr); SPINLOCK_INIT(port_data->command_lock); SEMAPHORE_INIT(&port_data->command_semaphore, ahci->command_slot_count); + dpc_prepare(&port_data->dpc, ahci_dpc); ahci->port_data[i] = port_data; } diff --git a/kernel-src/io/block/nvme.c b/kernel-src/io/block/nvme.c index f545c81f..7225ec79 100644 --- a/kernel-src/io/block/nvme.c +++ b/kernel-src/io/block/nvme.c @@ -299,7 +299,7 @@ static void nvme_dpc(context_t *, dpcarg_t arg) { static void nvme_irq(isr_t *isr, context_t *context) { queuepair_t *pair = isr->priv; - dpc_enqueue(&pair->dpc, nvme_dpc, pair); + dpc_enqueue(&pair->dpc, pair); } static isr_t *msixnewisrforqueue(queuepair_t *queuepair) { @@ -458,6 +458,7 @@ static int createiosubqueue(nvmecontroller_t *controller, queuedesc_t *desc, siz } static void newioqueuepair(nvmecontroller_t *controller, queuepair_t *pair, int id) { + dpc_prepare(&pair->dpc, nvme_dpc); __assert(createiocompqueue(controller, &pair->completion, QUEUEPAIR_ENTRY_COUNT, id, id, 0) == 0); __assert(createiosubqueue(controller, &pair->submission, QUEUEPAIR_ENTRY_COUNT, id, id, 0) == 0); pair->controller = controller; @@ -813,6 +814,8 @@ static void initcontroller(pcienum_t *e) { controller->adminqueue.completion.doorbell = GET_DOORBELL(controller->bar0, 0, 1, controller->dbstride); controller->adminqueue.completion.phase = 1; + dpc_prepare(&controller->adminqueue.dpc, nvme_dpc); + SPINLOCK_INIT(controller->adminqueue.lock); SEMAPHORE_INIT(&controller->adminqueue.entrysem, QUEUEPAIR_ENTRY_COUNT); diff --git a/kernel-src/io/block/vioblk.c b/kernel-src/io/block/vioblk.c index 63799169..da0f5b02 100644 --- a/kernel-src/io/block/vioblk.c +++ b/kernel-src/io/block/vioblk.c @@ -54,7 +54,7 @@ static void vioblk_dpc(context_t *context, dpcarg_t arg) { static void vioblk_irq(isr_t *isr, context_t *context) { vioblkdev_t *blkdev = isr->priv; - dpc_enqueue(&blkdev->queuedpc, vioblk_dpc, blkdev); + dpc_enqueue(&blkdev->queuedpc, blkdev); } // driver and device are physical addresses @@ -176,6 +176,7 @@ int vioblk_newdevice(viodevice_t *viodevice) { // initialize device object vioblkdev_t *blkdev = alloc(sizeof(vioblkdev_t)); __assert(blkdev); + dpc_prepare(&blkdev->queuedpc, vioblk_dpc); static int id = 0; volatile blkdevconfig_t *blkconfig = viodevice->devconfig; diff --git a/kernel-src/io/net/loopback.c b/kernel-src/io/net/loopback.c index 7086170f..3def9a03 100644 --- a/kernel-src/io/net/loopback.c +++ b/kernel-src/io/net/loopback.c @@ -43,7 +43,8 @@ static int loopback_sendpacket(netdev_t *netdev, netdesc_t desc, mac_t targetmac memcpy(desc.address, ðframe, sizeof(ethframe_t)); dpc_t dpc = {0}; - dpc_enqueue(&dpc, rx_dpc, desc.address); + dpc_prepare(&dpc, rx_dpc); + dpc_enqueue(&dpc, desc.address); return 0; } diff --git a/kernel-src/io/net/rtl8169.c b/kernel-src/io/net/rtl8169.c index 726276e8..2d0900c9 100644 --- a/kernel-src/io/net/rtl8169.c +++ b/kernel-src/io/net/rtl8169.c @@ -152,10 +152,10 @@ static void rtl8169_isr(isr_t *self, context_t *) { outw(dev->bar.address + REGISTER_IRQ_STATUS, status); if (status & (REGISTER_IRQ_STATUS_TX_OK | REGISTER_IRQ_STATUS_TX_ERROR)) - dpc_enqueue(&dev->tx_dpc, rtl8169_dpc_tx, dev); + dpc_enqueue(&dev->tx_dpc, dev); if (status & (REGISTER_IRQ_STATUS_RX_OK | REGISTER_IRQ_STATUS_RX_ERROR)) - dpc_enqueue(&dev->rx_dpc, rtl8169_dpc_rx, dev); + dpc_enqueue(&dev->rx_dpc, dev); status = inw(dev->bar.address + REGISTER_IRQ_STATUS); } @@ -311,7 +311,7 @@ static void init_controller(pcienum_t *pci_enum) { outb(pci_bar.address + REGISTER_COMMAND, REGISTER_COMMAND_TX_ENABLE); outd(pci_bar.address + REGISTER_TX_CONFIG, REGISTER_TX_CONFIG_DMA_BURST_UNLIMITED | REGISTER_TX_CONFIG_IFG_NORMAL); - + outw(pci_bar.address + REGISTER_RX_MAX_SIZE, 1518); // 128 * 0xc, enough for an ethernet MTU (while 0xb would be enough, the datasheet says that it must be larger than the max size) outb(pci_bar.address + REGISTER_TX_MAX_SIZE, 0xc); @@ -337,6 +337,9 @@ static void init_controller(pcienum_t *pci_enum) { SEMAPHORE_INIT(&netdev->tx_semaphore, TX_DESCRIPTOR_COUNT); SPINLOCK_INIT(netdev->tx_lock); + dpc_prepare(&netdev->tx_dpc, rtl8169_dpc_tx); + dpc_prepare(&netdev->rx_dpc, rtl8169_dpc_rx); + isr->priv = netdev; char name[10]; diff --git a/kernel-src/io/net/vionet.c b/kernel-src/io/net/vionet.c index 1d45d05e..9d10c277 100644 --- a/kernel-src/io/net/vionet.c +++ b/kernel-src/io/net/vionet.c @@ -54,7 +54,7 @@ static void rx_dpc(context_t *context, dpcarg_t arg) { static void rx_irq(isr_t *isr, context_t *context) { vionetdev_t *netdev = isr->priv; - dpc_enqueue(&netdev->rxdpc, rx_dpc, netdev); + dpc_enqueue(&netdev->rxdpc, netdev); } static void tx_dpc(context_t *context, dpcarg_t arg) { @@ -75,7 +75,7 @@ static void tx_dpc(context_t *context, dpcarg_t arg) { static void tx_irq(isr_t *isr, context_t *context) { vionetdev_t *netdev = isr->priv; - dpc_enqueue(&netdev->txdpc, tx_dpc, netdev); + dpc_enqueue(&netdev->txdpc, netdev); } #define PREFIX_SIZE (sizeof(ethframe_t) + sizeof(vioframe_t)) @@ -178,6 +178,8 @@ int vionet_newdevice(viodevice_t *viodevice) { netdev->netdev.allocdesc = vionet_allocdesc; netdev->netdev.freedesc = vionet_freedesc; __assert(hashtable_init(&netdev->netdev.arpcache, 30) == 0); + dpc_prepare(&netdev->rxdpc, rx_dpc); + dpc_prepare(&netdev->txdpc, tx_dpc); // initialize queues size_t rxsize = min(QUEUE_MAX_SIZE, virtio_queuesize(viodevice, 0)); diff --git a/kernel-src/sys/dpc.c b/kernel-src/sys/dpc.c index cae40170..a7701074 100644 --- a/kernel-src/sys/dpc.c +++ b/kernel-src/sys/dpc.c @@ -39,13 +39,19 @@ static void isrfn(isr_t *self, context_t *context) { } } -void dpc_enqueue(dpc_t *dpc, dpcfn_t fn, dpcarg_t arg) { +void dpc_prepare(dpc_t *dpc, dpcfn_t fn) { + dpc->fn = fn; + dpc->enqueued = false; + dpc->next = NULL; + dpc->prev = NULL; +} + +void dpc_enqueue(dpc_t *dpc, dpcarg_t arg) { bool entrystate = interrupt_set(false); if (dpc->enqueued) goto cleanup; - dpc->fn = fn; dpc->arg = arg; dpc->enqueued = true; insert(dpc); diff --git a/kernel-src/sys/scheduler/scheduler.c b/kernel-src/sys/scheduler/scheduler.c index e34027b4..3e4b4e6d 100644 --- a/kernel-src/sys/scheduler/scheduler.c +++ b/kernel-src/sys/scheduler/scheduler.c @@ -22,7 +22,7 @@ static __attribute__((noreturn)) void switch_thread(thread_t *thread) { thread_t* current = current_thread(); sched_thread_running_callback(thread); - + current_cpu()->thread = thread; if(current == NULL || thread->vmmctx != current->vmmctx) @@ -230,7 +230,7 @@ static void dopreempt() { switch_thread(next); } -static void preempt_dpc(context_t *context, dpcarg_t arg) { +static void sched_reschedule_dpc(context_t *context, dpcarg_t arg) { thread_t* current = current_thread(); interrupt_set(false); @@ -250,18 +250,18 @@ static void preempt_dpc(context_t *context, dpcarg_t arg) { // IPL_DPC static void reschedule_timer_dpc(context_t *context, dpcarg_t arg) { - dpc_enqueue(¤t_cpu()->reschedule_dpc, preempt_dpc, NULL); + dpc_enqueue(¤t_cpu()->reschedule_dpc, NULL); } // IPL_MAX static void reschedule_ipi(isr_t *, context_t *) { - dpc_enqueue(¤t_cpu()->reschedule_dpc, preempt_dpc, NULL); + dpc_enqueue(¤t_cpu()->reschedule_dpc, NULL); } void sched_preempt_cpu(cpu_t *cpu) { long ipl = interrupt_raiseipl(IPL_DPC); if (cpu == current_cpu()) { - dpc_enqueue(&cpu->reschedule_dpc, preempt_dpc, NULL); + dpc_enqueue(&cpu->reschedule_dpc, NULL); } else { arch_smp_send_ipi(cpu, cpu->reschedule_isr, ARCH_SMP_IPI_TARGET, false); } @@ -347,6 +347,7 @@ void sched_load_balancer(context_t *, dpcarg_t); void sched_ap_entry() { SPINLOCK_INIT(current_cpu()->sched_lock); + dpc_prepare(¤t_cpu()->reschedule_dpc, sched_reschedule_dpc); set_up_bitmaps(); current_cpu()->schedulerstack = vmm_map(NULL, SCHEDULER_STACK_SIZE, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, NULL); @@ -374,7 +375,8 @@ void sched_init() { SPINLOCK_INIT(current_cpu()->sched_lock); SPINLOCK_INIT(sched_idle_cpu_bitmap_lock); - + + dpc_prepare(¤t_cpu()->reschedule_dpc, sched_reschedule_dpc); set_up_bitmaps(); __assert(bitmap_init(&sched_idle_cpu_bitmap, arch_smp_get_cpu_count()) == 0); diff --git a/kernel-src/sys/timer.c b/kernel-src/sys/timer.c index a7ecbe2f..e0d4617d 100644 --- a/kernel-src/sys/timer.c +++ b/kernel-src/sys/timer.c @@ -60,7 +60,7 @@ static void timercheck(timer_t *timer) { else entry->fired = true; - dpc_enqueue(&entry->dpc, entry->fn, entry->arg); + dpc_enqueue(&entry->dpc, entry->arg); } } @@ -87,7 +87,7 @@ void timer_isr(timer_t *timer, context_t *context) { else oldentry->fired = true; - dpc_enqueue(&oldentry->dpc, oldentry->fn, oldentry->arg); + dpc_enqueue(&oldentry->dpc, oldentry->arg); leave: timercheck(timer); @@ -143,9 +143,9 @@ void timer_insert(timer_t *timer, timerentry_t *entry, dpcfn_t fn, dpcarg_t arg, memset(entry, 0, sizeof(timerentry_t)); entry->repeatus = repeating ? us : 0; - entry->fn = fn; - entry->arg = arg; entry->fired = false; + entry->arg = arg; + dpc_prepare(&entry->dpc, fn); insert(timer, entry, us); if (timer->running) {