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.
35 void CmiPushImmediateMsg(void *msg
)
37 MACHSTATE(4,"pushing immediate message {");
38 /* This lock check needs portable access to comm_flag, which is tough:
39 MACHLOCK_ASSERT(_immRunning||comm_flag,"CmiPushImmediateMsg");
42 CmiLock(CsvAccess(NodeState
).immSendLock
);
43 CMIQueuePush(CsvAccess(NodeState
).immQ
, (char *)msg
);
44 CmiUnlock(CsvAccess(NodeState
).immSendLock
);
45 MACHSTATE(4,"} pushing immediate message");
48 /* In user's immediate handler, if the immediate message cannot be processed
49 due to failure to acquire locks, etc, user program can call this function
50 to postpone the immediate message. The immediate message will eventually
51 be re-inserted into the imm queue.
53 SMP: This routine must be called holding immRecvLock
55 void CmiDelayImmediate()
57 MACHLOCK_ASSERT(_immRunning
,"CmiDelayImmediate");
59 CQdCreate(CpvAccess(cQdState
),1);
60 MACHSTATE(5,"Actually delaying an immediate message");
61 CMIQueuePush(CsvAccess(NodeState
).delayedImmQ
, (char *)currentImmediateMsg
);
66 Handle an immediate message, using the handler table of
67 processor rank 0. We can't call CmiHandleMessage for
68 immediate messages, because of CpvAccess and tracing.
70 SMP: This routine must be called holding immRecvLock
72 void CmiHandleImmediateMessage(void *msg
) {
73 /* int handlerNo=CmiGetXHandler(msg); */
74 int handlerNo
=CmiImmediateHandler(msg
);
76 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
79 MACHSTATE2(4,"immediate message handler %d %d", CmiGetHandler(msg
), handlerNo
)
80 /* CmiHandlerInfo *h=&CpvAccessOther(CmiHandlerTable,0)[handlerNo]; */
81 h
= &CpvAccess(CmiHandlerTable
)[handlerNo
];
82 CmiAssert(h
&& h
->hdlr
);
84 MACHLOCK_ASSERT(_immRunning
,"CmiHandleImmediateMessage");
85 CQdProcess(CpvAccess(cQdState
),1);
86 (h
->hdlr
)(msg
,h
->userPtr
);
90 Check for queued immediate messages and handle them.
92 It is safe to call this routine from multiple threads, or from SIGIO.
94 SMP: This routine must be called holding no locks, not even the comm. lock.
96 void CmiHandleImmediate()
100 /* converse init hasn't finish */
101 if (!_immediateReady
) return;
103 /* If somebody else is checking the queue, we don't need to */
104 if (CmiTryLock(CsvAccess(NodeState
).immRecvLock
)!=0) return;
106 /* Make sure only one thread is running immediate messages:
107 CmiLock(CsvAccess(NodeState).immRecvLock);
110 MACHLOCK_ASSERT(!_immRunning
,"CmiHandleImmediate");
111 _immRunning
=1; /* prevents SIGIO reentrancy, and allows different send */
112 MACHSTATE(2,"Entered handleImmediate {")
114 /* Handle all pending immediate messages */
115 while (NULL
!=(msg
=CMIQueuePop(CsvAccess(NodeState
).immQ
)))
117 currentImmediateMsg
= msg
;
118 MACHSTATE(4,"calling immediate message handler {");
119 CmiHandleImmediateMessage(msg
);
120 MACHSTATE(4,"} calling immediate message handler");
123 /* Take care of delayed immediate messages, which we have to handle next time */
124 while (NULL
!=(msg
=CMIQueuePop(CsvAccess(NodeState
).delayedImmQ
)))
125 CmiPushImmediateMsg(msg
);
127 MACHSTATE(2,"} exiting handleImmediate")
130 CmiUnlock(CsvAccess(NodeState
).immRecvLock
);
132 CmiClearImmediateFlag();