void sendSignal(notification_t *ntfnPtr, word_t badge) { switch (notification_ptr_get_state(ntfnPtr)) { case NtfnState_Idle: { tcb_t *tcb = (tcb_t*)notification_ptr_get_ntfnBoundTCB(ntfnPtr); /* Check if we are bound and that thread is waiting for a message */ if (tcb) { if (thread_state_ptr_get_tsType(&tcb->tcbState) == ThreadState_BlockedOnReceive) { /* Send and start thread running */ cancelIPC(tcb); setThreadState(tcb, ThreadState_Running); setRegister(tcb, badgeRegister, badge); switchIfRequiredTo(tcb); } else { ntfn_set_active(ntfnPtr, badge); } } else { ntfn_set_active(ntfnPtr, badge); } break; } case NtfnState_Waiting: { tcb_queue_t ntfn_queue; tcb_t *dest; ntfn_queue = ntfn_ptr_get_queue(ntfnPtr); dest = ntfn_queue.head; /* Haskell error "WaitingNtfn Notification must have non-empty queue" */ assert(dest); /* Dequeue TCB */ ntfn_queue = tcbEPDequeue(dest, ntfn_queue); ntfn_ptr_set_queue(ntfnPtr, ntfn_queue); /* set the thread state to idle if the queue is empty */ if (!ntfn_queue.head) { notification_ptr_set_state(ntfnPtr, NtfnState_Idle); } setThreadState(dest, ThreadState_Running); setRegister(dest, badgeRegister, badge); switchIfRequiredTo(dest); break; } case NtfnState_Active: { word_t badge2; badge2 = notification_ptr_get_ntfnMsgIdentifier(ntfnPtr); badge2 |= badge; notification_ptr_set_ntfnMsgIdentifier(ntfnPtr, badge2); break; } } }
void sendSignal(notification_t *ntfnPtr, word_t badge) { switch (notification_ptr_get_state(ntfnPtr)) { case NtfnState_Idle: { tcb_t *tcb = (tcb_t *)notification_ptr_get_ntfnBoundTCB(ntfnPtr); /* Check if we are bound and that thread is waiting for a message */ if (tcb) { if (thread_state_ptr_get_tsType(&tcb->tcbState) == ThreadState_BlockedOnReceive) { /* Send and start thread running */ cancelIPC(tcb); setThreadState(tcb, ThreadState_Running); setRegister(tcb, badgeRegister, badge); possibleSwitchTo(tcb); #ifdef CONFIG_VTX } else if (thread_state_ptr_get_tsType(&tcb->tcbState) == ThreadState_RunningVM) { #ifdef ENABLE_SMP_SUPPORT if (tcb->tcbAffinity != getCurrentCPUIndex()) { ntfn_set_active(ntfnPtr, badge); doRemoteVMCheckBoundNotification(tcb->tcbAffinity, tcb); } else #endif /* ENABLE_SMP_SUPPORT */ { setThreadState(tcb, ThreadState_Running); setRegister(tcb, badgeRegister, badge); Arch_leaveVMAsyncTransfer(tcb); possibleSwitchTo(tcb); } #endif /* CONFIG_VTX */ } else { /* In particular, this path is taken when a thread * is waiting on a reply cap since BlockedOnReply * would also trigger this path. I.e, a thread * with a bound notification will not be awakened * by signals on that bound notification if it is * in the middle of an seL4_Call. */ ntfn_set_active(ntfnPtr, badge); } } else { ntfn_set_active(ntfnPtr, badge); } break; } case NtfnState_Waiting: { tcb_queue_t ntfn_queue; tcb_t *dest; ntfn_queue = ntfn_ptr_get_queue(ntfnPtr); dest = ntfn_queue.head; /* Haskell error "WaitingNtfn Notification must have non-empty queue" */ assert(dest); /* Dequeue TCB */ ntfn_queue = tcbEPDequeue(dest, ntfn_queue); ntfn_ptr_set_queue(ntfnPtr, ntfn_queue); /* set the thread state to idle if the queue is empty */ if (!ntfn_queue.head) { notification_ptr_set_state(ntfnPtr, NtfnState_Idle); } setThreadState(dest, ThreadState_Running); setRegister(dest, badgeRegister, badge); possibleSwitchTo(dest); break; } case NtfnState_Active: { word_t badge2; badge2 = notification_ptr_get_ntfnMsgIdentifier(ntfnPtr); badge2 |= badge; notification_ptr_set_ntfnMsgIdentifier(ntfnPtr, badge2); break; } } }
static inline void ntfn_set_active(notification_t *ntfnPtr, word_t badge) { notification_ptr_set_state(ntfnPtr, NtfnState_Active); notification_ptr_set_ntfnMsgIdentifier(ntfnPtr, badge); }