Beispiel #1
0
/**
 *  Obtain the number of nodes, my node id, and consuming machine layer
 *  specific arguments
 */
static void MachineInitForLAPI(int *argc, char ***argv, int *numNodes, int *myNodeID) {

    lapi_info_t info;
    char **largv = *argv;

    memset(&info,0,sizeof(info));

    /* Register error handler (redundant?) -- added by Chao Mei*/
    info.err_hndlr = (LAPI_err_hndlr *)lapi_err_hndlr;

    /* Indicates the number of completion handler threads to create */
    /* The number of completion hndlr thds will affect the atomic PCQueue operations!! */
    /* NOTE: num_compl_hndlr_thr is obsolete now! --Chao Mei */
    /* info.num_compl_hndlr_thr = 1; */

    check_lapi(LAPI_Init,(&lapiContext, &info));

    /* It's a good idea to start with a fence,
       because packets recv'd before a LAPI_Init are just dropped. */
    check_lapi(LAPI_Gfence,(lapiContext));

    check_lapi(LAPI_Qenv,(lapiContext, TASK_ID, myNodeID));
    check_lapi(LAPI_Qenv,(lapiContext, NUM_TASKS, numNodes));

    /* Make polling as the default mode as real apps have better perf */
    CsvAccess(lapiInterruptMode) = 0;
    if (CmiGetArgFlag(largv,"+poll")) CsvAccess(lapiInterruptMode) = 0;
    if (CmiGetArgFlag(largv,"+nopoll")) CsvAccess(lapiInterruptMode) = 1;

    check_lapi(LAPI_Senv,(lapiContext, ERROR_CHK, lapiDebugMode));
    check_lapi(LAPI_Senv,(lapiContext, INTERRUPT_SET, CsvAccess(lapiInterruptMode)));

    if (*myNodeID == 0) {
        printf("Running lapi in interrupt mode: %d\n", CsvAccess(lapiInterruptMode));
        printf("Running lapi with %d completion handler threads.\n", info.num_compl_hndlr_thr);
    }

    /**
     *  Associate PumpMsgsBegin with var "lapiHeaderHandler". Then inside Xfer calls,
     *  lapiHeaderHandler could be used to indicate the callback
     *  instead of PumpMsgsBegin --Chao Mei
     */
    check_lapi(LAPI_Addr_set,(lapiContext,(void *)PumpMsgsBegin,lapiHeaderHandler));

    if (CmiGetArgFlag(largv,"++debug")) {  /*Pause so user has a chance to start and attach debugger*/
        printf("CHARMDEBUG> Processor %d has PID %d\n",*myNodeID,getpid());
        if (!CmiGetArgFlag(largv,"++debug-no-pause"))
            sleep(30);
    }

#if ENSURE_MSG_PAIRORDER
    cmplHdlrThdLock = CmiCreateLock();
#endif
}
Beispiel #2
0
CpmInvokable vars_set_cpv_and_csv(vars_chare c)
{
  CpvAccess(cpv1) = CmiMyPe();
  if (CmiMyRank() == 0)
    CsvAccess(csv1) = 0x12345678;
  Cpm_vars_ack(CpmSend(0), c);
}
Beispiel #3
0
static void MachinePostCommonInitForLAPI(int everReturn) {
    /**
         * In SMP, the machine layer usually has one comm thd, and it is
         * designed to be responsible for all network communication. So
         * if there's no dedicated processor for the comm thread, it has
         * to share a proc with a worker thread. In this scenario,
         * the worker thread needs to yield for some time to give CPU
         * time to comm thread. However, in current configuration, we
         * will always dedicate one proc for the comm thd, therefore,
         * such yielding scheme is not necessary.  Besides, avoiding
         * this yielding scheme improves performance because worker
         * thread doesn't need to yield and will be more responsive to
         * incoming messages. So, we will always use CmiNotifyIdle
         * instead.
         *
         * --Chao Mei
         */

    /* Not registering any Idle-state related functions right now!! */

#if 0 && CMK_SMP
    s=CmiNotifyGetState();
    CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
#else
    CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
#if !CMK_SMP || CMK_SMP_NO_COMMTHD
    /* If there's comm thread, then comm thd is responsible for advancing comm */
    if (!CsvAccess(lapiInterruptMode)) {
        CcdCallOnConditionKeep(CcdPERIODIC_10ms, (CcdVoidFn)AdvanceCommunicationForLAPI, NULL);
    }
#endif
#endif
}
Beispiel #4
0
static void handleOneBcastMsg(int size, char *msg) {
    CmiAssert(CMI_BROADCAST_ROOT(msg)!=0);
#if CMK_OFFLOAD_BCAST_PROCESS
    if (CMI_BROADCAST_ROOT(msg)>0) {
        CMIQueuePush(CsvAccess(procBcastQ), msg);
    } else {
#if CMK_NODE_QUEUE_AVAILABLE
        CMIQueuePush(CsvAccess(nodeBcastQ), msg);
#endif
    }
#else
    if (CMI_BROADCAST_ROOT(msg)>0) {
        processProcBcastMsg(size, msg);
    } else {
#if CMK_NODE_QUEUE_AVAILABLE
        processNodeBcastMsg(size, msg);
#endif
    }
#endif
}
Beispiel #5
0
CpmInvokable vars_check_cpv_and_csv(vars_chare c)
{
  if (CpvAccess(cpv1) != CmiMyPe()) {
    CmiPrintf("cpv privacy test failed.\n");
    exit(1);
  }
  if (CsvAccess(csv1) != 0x12345678) {
    CmiPrintf("csv sharing test failed.\n");
    exit(1);
  }
  Cpm_vars_ack(CpmSend(0), c);
}
Beispiel #6
0
static void processBcastQs() {
#if CMK_OFFLOAD_BCAST_PROCESS
    char *msg;
    do {
        msg = CMIQueuePop(CsvAccess(procBcastQ));
        if (!msg) break;
        MACHSTATE2(4, "[%d]: process a proc-level bcast msg %p begin{", CmiMyNode(), msg);
        processProcBcastMsg(CMI_MSG_SIZE(msg), msg);
        MACHSTATE2(4, "[%d]: process a proc-level bcast msg %p end}", CmiMyNode(), msg);
    } while (1);
#if CMK_NODE_QUEUE_AVAILABLE
    do {
        msg = CMIQueuePop(CsvAccess(nodeBcastQ));
        if (!msg) break;
        MACHSTATE2(4, "[%d]: process a node-level bcast msg %p begin{", CmiMyNode(), msg);
        processNodeBcastMsg(CMI_MSG_SIZE(msg), msg);
        MACHSTATE2(4, "[%d]: process a node-level bcast msg %p end}", CmiMyNode(), msg);
    } while (1);
#endif
#endif
}
Beispiel #7
0
void CmiMachineProgressImpl() {
    if (!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));

#if CMK_IMMEDIATE_MSG
    MACHSTATE1(2, "[%d] Handling Immediate Message begin {",CmiMyNode());
    CmiHandleImmediate();
    MACHSTATE1(2, "[%d] Handling Immediate Message end }",CmiMyNode());
#endif

#if CMK_SMP && !CMK_SMP_NO_COMMTHD && CMK_OFFLOAD_BCAST_PROCESS
    if (CmiMyRank()==CmiMyNodeSize()) processBcastQs(); /* FIXME ????????????????*/
#endif
}
Beispiel #8
0
static INLINE_KEYWORD void AdvanceCommunicationForLAPI(int idle) {
    /* What about CMK_SMP_NO_COMMTHD in the original implementation?? */
    /* It does nothing but sleep */
    if (!CsvAccess(lapiInterruptMode)) check_lapi(LAPI_Probe,(lapiContext));
}
Beispiel #9
0
/**
 * Returns 1 if this "msg" is an out-of-order message, or
 * this "msg" is a late message which triggers the process
 * of all buffered ooo msgs.
 * --Chao Mei
 */
static int checkMsgInOrder(char *msg, MsgOrderInfo *info) {
    int srcpe, destrank;
    int incomingSeqNo, expectedSeqNo;
    int curOffset, maxOffset;
    int i, curWinSize;
    void **destMsgBuffer = NULL;

    /* numMsg is the number of msgs to be processed in this buffer*/
    /* Reason to have this extra copy of msgs to be processed: Reduce the atomic granularity */
    void **toProcessMsgBuffer;
    int numMsgs = 0;

    srcpe = CMI_MSG_SRCPE(msg);
    destrank = CMI_DEST_RANK(msg);
    incomingSeqNo = CMI_MSG_SEQNO(msg);

    CmiLock(cmplHdlrThdLock);

    expectedSeqNo = getNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe);
    if (expectedSeqNo == incomingSeqNo) {
        /* Two cases: has ooo msg buffered or not */
        maxOffset = (info->oooMaxOffset)[srcpe];
        if (maxOffset>0) {
            MACHSTATE1(4, "Processing all buffered ooo msgs (maxOffset=%d) including the just recved begin {", maxOffset);
            curWinSize = info->CUR_WINDOW_SIZE[srcpe];
            toProcessMsgBuffer = malloc((curWinSize+1)*sizeof(void *));
            /* process the msg just recved */
            toProcessMsgBuffer[numMsgs++] = msg;
            /* process the buffered ooo msg until the first empty slot in the window */
            destMsgBuffer = (info->oooMsgBuffer)[srcpe];
            for (curOffset=0; curOffset<maxOffset; curOffset++) {
                char *curMsg = destMsgBuffer[curOffset];
                if (curMsg == NULL) {
                    CmiAssert(curOffset!=(maxOffset-1));
                    break;
                }
                toProcessMsgBuffer[numMsgs++] = curMsg;
                destMsgBuffer[curOffset] = NULL;
            }
            /* Update expected seqno, maxOffset and slide the window */
            if (curOffset < maxOffset) {
                int i;
                /**
                 * now, the seqno of the next to-be-recved msg should be
                 * "expectedSeqNo+curOffset+1" as the seqno of the just
                 * processed msg is "expectedSeqNo+curOffset. We need to slide
                 * the msg buffer window from "curOffset+1" because the first
                 * element of the buffer window should always points to the ooo
                 * msg that's 1 in terms of seqno ahead of the next to-be-recved
                 * msg. --Chao Mei
                 */

                /* moving [curOffset+1, maxOffset) to [0, maxOffset-curOffset-1) in the window */
                /* The following two loops could be combined --Chao Mei */
                for (i=0; i<maxOffset-curOffset-1; i++) {
                    destMsgBuffer[i] = destMsgBuffer[curOffset+i+1];
                }
                for (i=maxOffset-curOffset-1; i<maxOffset; i++) {
                    destMsgBuffer[i] = NULL;
                }
                (info->oooMaxOffset)[srcpe] = maxOffset-curOffset-1;
                setNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe, expectedSeqNo+curOffset);
            } else {
                /* there's no remaining buffered ooo msgs */
                (info->oooMaxOffset)[srcpe] = 0;
                setNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe, expectedSeqNo+maxOffset);
            }

            CmiUnlock(cmplHdlrThdLock);

            /* Process the msgs */
            for (i=0; i<numMsgs; i++) {
                char *curMsg = toProcessMsgBuffer[i];
                if (CMI_BROADCAST_ROOT(curMsg)>0) {

#if CMK_OFFLOAD_BCAST_PROCESS
                    PCQueuePush(CsvAccess(procBcastQ), curMsg);
#else
                    processProcBcastMsg(CMI_MSG_SIZE(curMsg), curMsg);
#endif
                } else {
                    CmiPushPE(CMI_DEST_RANK(curMsg), curMsg);
                }
            }

            free(toProcessMsgBuffer);

            MACHSTATE1(4, "Processing all buffered ooo msgs (actually processed %d) end }", curOffset);
            /**
             * Since we have processed all buffered ooo msgs including
             * this just recved one, 1 should be returned so that this
             * msg no longer needs processing
             */
            return 1;
        } else {
            /* An expected msg recved without any ooo msg buffered */
            MACHSTATE1(4, "Receiving an expected msg with seqno=%d\n", incomingSeqNo);
            setNextExpectedMsgSeqNo(info->expectedMsgSeqNo, srcpe, expectedSeqNo);

            CmiUnlock(cmplHdlrThdLock);
            return 0;
        }
    }

    MACHSTATE2(4, "Receiving an out-of-order msg with seqno=%d, but expect seqno=%d", incomingSeqNo, expectedSeqNo);
    curWinSize = info->CUR_WINDOW_SIZE[srcpe];
    if ((info->oooMsgBuffer)[srcpe]==NULL) {
        (info->oooMsgBuffer)[srcpe] = malloc(curWinSize*sizeof(void *));
        memset((info->oooMsgBuffer)[srcpe], 0, curWinSize*sizeof(void *));
    }
    destMsgBuffer = (info->oooMsgBuffer)[srcpe];
    curOffset = incomingSeqNo - expectedSeqNo;
    maxOffset = (info->oooMaxOffset)[srcpe];
    if (curOffset<0) {
        /* It's possible that the seqNo starts with another round (exceeding MAX_MSG_SEQNO) with 1 */
        curOffset += MAX_MSG_SEQNO;
    }
    if (curOffset > curWinSize) {
        int newWinSize;
        if (curOffset > MAX_WINDOW_SIZE) {
            CmiAbort("Exceeding the MAX_WINDOW_SIZE!\n");
        }
        newWinSize = ((curOffset/curWinSize)+1)*curWinSize;
        /*CmiPrintf("[%d]: WARNING: INCREASING WINDOW SIZE FROM %d TO %d\n", CmiMyPe(), curWinSize, newWinSize);*/
        (info->oooMsgBuffer)[srcpe] = malloc(newWinSize*sizeof(void *));
        memset((info->oooMsgBuffer)[srcpe], 0, newWinSize*sizeof(void *));
        memcpy((info->oooMsgBuffer)[srcpe], destMsgBuffer, curWinSize*sizeof(void *));
        info->CUR_WINDOW_SIZE[srcpe] = newWinSize;
        free(destMsgBuffer);
        destMsgBuffer = (info->oooMsgBuffer)[srcpe];
    }
    CmiAssert(destMsgBuffer[curOffset-1] == NULL);
    destMsgBuffer[curOffset-1] = msg;
    if (curOffset > maxOffset) (info->oooMaxOffset)[srcpe] = curOffset;

    CmiUnlock(cmplHdlrThdLock);
    return 1;
}