void handle_usb(u32 clkn) { u8 epstat; /* write queued packets to USB if possible */ epstat = USBHwEPGetStatus(BULK_IN_EP); if (!(epstat & EPSTAT_B1FULL)) { dequeue_send(clkn); } if (!(epstat & EPSTAT_B2FULL)) { dequeue_send(clkn); } /* polled "interrupt" */ USBHwISR(); }
/* Send an IPC to another thread. */ NORETURN void sys_ipc_recv(word_t src_thread, word_t operation) { /* Ensure the thread exists. */ if (EXPECT_FALSE(src_thread >= max_tcbs && src_thread != IPC_WAIT_ANY)) { syscall_return_error(IPC_ERROR, EINVAL); } spin_lock(&ipc_lock); /* Get first thread on send queue. */ tcb_t *src = current_tcb->ipc_send_head; /* If there are no threads, go to sleep. */ if (src == NULL) { current_tcb->ipc_waiting_for = src; tcb_t *next = deactivate_self_schedule(THREAD_STATE_WAIT_IPC_RECV); spin_unlock(&ipc_lock); switch_to(next); } /* Otherwise, dequeue the thread. */ dequeue_send(current_tcb, src); /* Copy the message across and wake up the sender. */ copy_message(src, current_tcb); /* Is the sender performing a call? */ if (src->thread_state == THREAD_STATE_WAIT_IPC_CALL) { /* Move it into receive phase. 'ipc_waiting_for' should already be set * to us. */ word_t tid = src->tid; ASSERT(src->ipc_waiting_for == current_tcb); src->thread_state = THREAD_STATE_WAIT_IPC_RECV; spin_unlock(&ipc_lock); syscall_return_success(tid); /* NOTREACHED */ } /* If the sender was not performing a call, wake them up. */ src->ipc_waiting_for = NULL; set_syscall_return_val_success(src, 0); set_syscall_return_val_success(current_tcb, src->tid); tcb_t *next = activate_schedule(src); spin_unlock(&ipc_lock); switch_to(next); /* NOTREACHED */ }