2 * \brief Immediate message implementation
12 support immediate message in Converse
15 int _immediateReady = 0;
17 int _immRunning=0; /* if set, somebody's inside an immediate message */
19 /* _immediateLock and _immediateFlag declared in convcore.C
20 for machine layers with CMK_IMMEDIATE_MSG=0 */
24 /* SMP: These variables are protected by immRecvLock. */
25 static void *currentImmediateMsg=NULL; /* immediate message currently being executed */
27 /* push immediate messages into imm queue. Immediate messages can be pushed
28 from both processor threads or comm. thread.
30 The actual user handler is in Xhandler; the converse handler
31 is still marked as the immediate message "handler".
33 SMP: This routine does its own locking.
36 void CmiPushImmediateMsg(void *msg)
38 MACHSTATE(4,"pushing immediate message {");
39 /* This lock check needs portable access to comm_flag, which is tough:
40 MACHLOCK_ASSERT(_immRunning||comm_flag,"CmiPushImmediateMsg");
43 CmiLock(CsvAccess(NodeState).immSendLock);
44 CMIQueuePush(CsvAccess(NodeState).immQ, (char *)msg);
45 CmiUnlock(CsvAccess(NodeState).immSendLock);
46 MACHSTATE(4,"} pushing immediate message");
49 /* In user's immediate handler, if the immediate message cannot be processed
50 due to failure to acquire locks, etc, user program can call this function
51 to postpone the immediate message. The immediate message will eventually
52 be re-inserted into the imm queue.
54 SMP: This routine must be called holding immRecvLock
56 void CmiDelayImmediate(void)
58 MACHLOCK_ASSERT(_immRunning,"CmiDelayImmediate");
61 CQdCreate(CpvAccess(cQdState),1);
63 MACHSTATE(5,"Actually delaying an immediate message");
64 CMIQueuePush(CsvAccess(NodeState).delayedImmQ, (char *)currentImmediateMsg);
69 Handle an immediate message, using the handler table of
70 processor rank 0. We can't call CmiHandleMessage for
71 immediate messages, because of CpvAccess and tracing.
73 SMP: This routine must be called holding immRecvLock
75 void CmiHandleImmediateMessage(void *msg) {
76 /* int handlerNo=CmiGetXHandler(msg); */
77 int handlerNo=CmiImmediateHandler(msg);
79 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
82 MACHSTATE2(4,"immediate message handler %d %d", CmiGetHandler(msg), handlerNo)
83 /* CmiHandlerInfo *h=&CpvAccessOther(CmiHandlerTable,0)[handlerNo]; */
84 h = &CpvAccess(CmiHandlerTable)[handlerNo];
85 CmiAssert(h && h->hdlr);
87 MACHLOCK_ASSERT(_immRunning,"CmiHandleImmediateMessage");
89 CQdProcess(CpvAccess(cQdState),1);
91 (h->hdlr)(msg,h->userPtr);
95 Check for queued immediate messages and handle them.
97 It is safe to call this routine from multiple threads, or from SIGIO.
99 SMP: This routine must be called holding no locks, not even the comm. lock.
101 void CmiHandleImmediate(void)
105 /* converse init hasn't finish */
106 if (!_immediateReady) return;
108 /* If somebody else is checking the queue, we don't need to */
109 if (CmiTryLock(CsvAccess(NodeState).immRecvLock)!=0) return;
111 /* Make sure only one thread is running immediate messages:
112 CmiLock(CsvAccess(NodeState).immRecvLock);
115 MACHLOCK_ASSERT(!_immRunning,"CmiHandleImmediate");
116 _immRunning=1; /* prevents SIGIO reentrancy, and allows different send */
117 MACHSTATE(2,"Entered handleImmediate {")
119 /* Handle all pending immediate messages */
120 while (NULL!=(msg=CMIQueuePop(CsvAccess(NodeState).immQ)))
122 currentImmediateMsg = msg;
123 MACHSTATE(4,"calling immediate message handler {");
124 CmiHandleImmediateMessage(msg);
125 MACHSTATE(4,"} calling immediate message handler");
128 /* Take care of delayed immediate messages, which we have to handle next time */
129 while (NULL!=(msg=CMIQueuePop(CsvAccess(NodeState).delayedImmQ)))
130 CmiPushImmediateMsg(msg);
132 MACHSTATE(2,"} exiting handleImmediate")
135 CmiUnlock(CsvAccess(NodeState).immRecvLock);
137 CmiClearImmediateFlag();