arch/util/immediate.c

Go to the documentation of this file.
00001 
00010 
00011 /*
00012   support immediate message in Converse
00013 */
00014 
00015 int _immediateReady = 0;
00016 
00017 int _immRunning=0; /* if set, somebody's inside an immediate message */
00018 
00019 /* _immediateLock and _immediateFlag declared in convcore.c 
00020    for machine layers with CMK_IMMEDIATE_MSG=0   */ 
00021 
00022 #if CMK_IMMEDIATE_MSG
00023 
00024 /* SMP: These variables are protected by immRecvLock. */
00025 static void *currentImmediateMsg=NULL; /* immediate message currently being executed */
00026 
00027 /*  push immediate messages into imm queue. Immediate messages can be pushed
00028     from both processor threads or comm. thread.
00029     
00030     The actual user handler is in Xhandler; the converse handler
00031     is still marked as the immediate message "handler".
00032 
00033 SMP:  This routine does its own locking.
00034 */
00035 void CmiPushImmediateMsg(void *msg)
00036 {
00037   MACHSTATE(4,"pushing immediate message {");
00038   /* This lock check needs portable access to comm_flag, which is tough:
00039      MACHLOCK_ASSERT(_immRunning||comm_flag,"CmiPushImmediateMsg");
00040   */
00041   
00042   CmiLock(CsvAccess(NodeState).immSendLock);
00043   PCQueuePush(CsvAccess(NodeState).immQ, (char *)msg);
00044   CmiUnlock(CsvAccess(NodeState).immSendLock);
00045   MACHSTATE(4,"} pushing immediate message");
00046 }
00047 
00048 /* In user's immediate handler, if the immediate message cannot be processed
00049    due to failure to acquire locks, etc, user program can call this function
00050    to postpone the immediate message. The immediate message will eventually
00051    be re-inserted into the imm queue.
00052 
00053 SMP: This routine must be called holding immRecvLock
00054 */
00055 void CmiDelayImmediate(void)
00056 {
00057   MACHLOCK_ASSERT(_immRunning,"CmiDelayImmediate");
00058 
00059   CQdCreate(CpvAccess(cQdState),1);
00060   MACHSTATE(5,"Actually delaying an immediate message");
00061   PCQueuePush(CsvAccess(NodeState).delayedImmQ, (char *)currentImmediateMsg);
00062 }
00063 
00064 
00065 /*
00066   Handle an immediate message, using the handler table of
00067   processor rank 0.  We can't call CmiHandleMessage for 
00068   immediate messages, because of CpvAccess and tracing.
00069 
00070 SMP: This routine must be called holding immRecvLock
00071  */
00072 void CmiHandleImmediateMessage(void *msg) {
00073 /*  int handlerNo=CmiGetXHandler(msg); */
00074   int handlerNo=CmiImmediateHandler(msg);
00075   MACHSTATE2(4,"immediate message handler %d %d", CmiGetHandler(msg), handlerNo)
00076 /*  CmiHandlerInfo *h=&CpvAccessOther(CmiHandlerTable,0)[handlerNo]; */
00077   CmiHandlerInfo *h = &CpvAccess(CmiHandlerTable)[handlerNo];
00078   CmiAssert(h && h->hdlr);
00079 
00080   MACHLOCK_ASSERT(_immRunning,"CmiHandleImmediateMessage");
00081   CQdProcess(CpvAccess(cQdState),1);
00082   (h->hdlr)(msg,h->userPtr);
00083 }
00084 
00085 /*
00086    Check for queued immediate messages and handle them.
00087    
00088    It is safe to call this routine from multiple threads, or from SIGIO.
00089 
00090 SMP: This routine must be called holding no locks, not even the comm. lock.
00091  */
00092 void CmiHandleImmediate()
00093 {
00094    void *msg;
00095 
00096    /* converse init hasn't finish */
00097    if (!_immediateReady) return;
00098   
00099    /* If somebody else is checking the queue, we don't need to */
00100    if (CmiTryLock(CsvAccess(NodeState).immRecvLock)!=0) return;
00101 
00102    /* Make sure only one thread is running immediate messages:
00103    CmiLock(CsvAccess(NodeState).immRecvLock);
00104    */
00105 
00106    MACHLOCK_ASSERT(!_immRunning,"CmiHandleImmediate");
00107    _immRunning=1; /* prevents SIGIO reentrancy, and allows different send */
00108    MACHSTATE(2,"Entered handleImmediate {")
00109 
00110    /* Handle all pending immediate messages */
00111    while (NULL!=(msg=PCQueuePop(CsvAccess(NodeState).immQ)))
00112    {
00113      currentImmediateMsg = msg;
00114      MACHSTATE(4,"calling immediate message handler {");
00115      CmiHandleImmediateMessage(msg);
00116      MACHSTATE(4,"} calling immediate message handler");
00117    }
00118    
00119    /* Take care of delayed immediate messages, which we have to handle next time */
00120    while (NULL!=(msg=PCQueuePop(CsvAccess(NodeState).delayedImmQ)))
00121         CmiPushImmediateMsg(msg);
00122    
00123    MACHSTATE(2,"} exiting handleImmediate")
00124    _immRunning = 0;
00125    
00126    CmiUnlock(CsvAccess(NodeState).immRecvLock);
00127 
00128    CmiClearImmediateFlag();
00129 }
00130 
00131 #endif
00132 

Generated on Sun Jun 29 13:29:06 2008 for Charm++ by  doxygen 1.5.1