Project

General

Profile

Revision 0e7ff5c8

ID0e7ff5c845cc8caa56f4ed6f37b2918b84466d7e

Added by Simon Tenbusch almost 9 years ago

[nullduration] moved asyncModuleLocks to earlier position and added getProcessingDelay return value that makes the event get handled sequentially:
We have to lock before getProcessingDelay is called, and must only be released, once the corresponding event has been handled. This is because in the meantime, other events could alter the module and therefore change the outcome of getProcessingDelay nondeterministically.

Also in the sequential case, we still have to lock because it could be the case that a parallel event on the same module is active while we try to execute a sequential one.

The locking is now taking place in cMessage::getEventDuration, which calls getProcessingDelay. Unlocking takes now place both after sequential and parallel execution.

If SimTime::simTimeSequentialExecution is returned by getProcessingDelay, the event is handled sequentially with duration 0 (useful for management events)

View differences:

include/simtime.h
99 99
    static const int SCALEEXP_FS = -15;
100 100
    static const int SCALEEXP_UNINITIALIZED = 0xffff;
101 101
    static const SimTime simTimeZero;
102
    static const double simTimeSequentialExecution;
103
    static const double simTimeUninitialized;
102 104

  
103 105
    /**
104 106
     * Constructor initializes to zero.
src/sim/casyncmodule.cc
142 142

  
143 143
void cAsyncModule::setMessageMetaData(cMessage* msg)
144 144
{
145
    msg->setEventDuration(-1);
145
    msg->setEventDuration(SimTime::simTimeUninitialized);
146 146
    msg->setSchedulingOrderId(scheduledMessageCount++);
147 147
    msg->setParentExecutionOrderId(executionOrderId);
148 148
    msg->setParentStartTime(now);
src/sim/cmessage.cc
84 84
    heapindex = -1;
85 85
    prev_event_num = -1;
86 86

  
87
    duration = -1;
87
    duration = SimTime::simTimeUninitialized;
88 88
    msgtreeid = msgid = AO_fetch_and_add1(&next_id);
89 89
    AO_fetch_and_add1(&total_msgs);
90 90
    AO_fetch_and_add1(&live_msgs);
......
373 373
}
374 374

  
375 375
simtime_t cMessage::getEventDuration() {
376
    if (duration < 0) {
376
    if (duration == SimTime::simTimeUninitialized) {
377 377
        cSimpleModule* mod = (cSimpleModule*) simulation.getModule(getArrivalModuleId());
378 378
        if (mod && mod->isAsyncModule()) {
379
            // block if another thread is busy inside this module
380
            // then set the module to busy
381
            // this must only be unset after the corresponding event has been processed,
382
            // since otherwise the return value of getProcessingDelay is not deterministically determined
383
            // (in the mean time there may have been other events, changing the outcome of getProcessingDelay)
384
            ((cAsyncModule*) mod)->waitIfBusy();
385
            ((cAsyncModule*) mod)->setBusy();
379 386
            duration = ((cAsyncModule*) mod)->getProcessingDelay(this);
380 387
        }
381 388
    }
src/sim/cscheduler.cc
125 125
    {
126 126
        cAsyncModule* aMod = (cAsyncModule*) mod;
127 127
        simtime_t duration = msg->getEventDuration();
128
        if (aMod->mayParallelize(msg, duration) && sim->threadPool)
128
        if (duration != SimTime::simTimeSequentialExecution && aMod->mayParallelize(msg, duration) && sim->threadPool)
129 129
        {
130 130
            //
131 131
            // create a new barrier and schedule it
src/sim/csimulation.cc
682 682
            cAsyncModule* aMod = (cAsyncModule*) mod;
683 683

  
684 684
            simtime_t duration = msg->getEventDuration();
685
            bool sequentialExecution = (duration == SimTime::simTimeSequentialExecution);
686

  
687
            if (sequentialExecution)
688
                duration = SimTime::simTimeZero;
689

  
685 690
            if (duration < SimTime::simTimeZero)
686 691
            {
687 692
                throw cRuntimeError("negative event duration not allowed.");
......
689 694

  
690 695
            bool mayPar = aMod->mayParallelize(msg, duration);
691 696
            // execute this event in parallel
692
            if (mayPar && threaded)
697
            if (mayPar && threaded && !sequentialExecution)
693 698
            {
694
                // block if another thread is busy inside this module
695
                // then set the module to busy
696
                aMod->waitIfBusy();
697
                aMod->setBusy();
698 699
                //printf("Offloading: %s\n",mod->getName());
699 700
                threadPool->insertTask(msg, duration);
701
                // the threadpool unsets the module busy after it finishes the event
700 702
            }
701 703
            else
702 704
            {
......
705 707
                setContextType(CTX_EVENT);
706 708
                // take ownership in callHandleMessage after concurrency check
707 709
                aMod->callHandleMessage(msg);
710
                // unset busy to release module for further events
711
                aMod->unsetBusy();
708 712
            }
709 713
        }
710 714
        else
src/sim/simtime.cc
29 29
double SimTime::invfscale;
30 30
const SimTime SimTime::simTimeZero = SimTime();
31 31

  
32
//Used as return value for getProcessingDelay
33
const double SimTime::simTimeSequentialExecution = -2;
34
//Used in cMessage::getEventDuration
35
const double SimTime::simTimeUninitialized = -1;
36

  
32 37
void SimTime::setScaleExp(int e)
33 38
{
34 39
    if (e == scaleexp)

Also available in: Unified diff