Revision a3be1d55

View differences:

include/cscheduler.h
89 89
    virtual void executionResumed()  {}
90 90

  
91 91
    /**
92
     * The scheduler function -- it should return the next event
93
     * to be processed. Normally (with sequential execution) it just
94
     * returns msgQueue.peekFirst(). With parallel and/or real-time
95
     * simulation, it is also the scheduler's task to synchronize
96
     * with real time and/or with other partitions.
97
     *
98
     * If there is no more event, it throws cTerminationException.
99
     *
100
     * A NULL return value means that there is no error but execution
101
     * was stopped by the user (e.g. with STOP button on the GUI)
102
     * while getNextEvent() was waiting for external synchronization.
92
     * Returns the next Event to be processed from the FES according to the Scheduling policy.
93
     * The Event is removed from the FES.
94
     * Never returns NULL
95
     * throws cTerminationException(eENDEDOK), when no Event is left to return (the simulation is done)
96
     * This should only be called by doOneEvent() in the Simulation
103 97
     */
104 98
    virtual cMessage *getNextEvent() = 0;
105 99
};
src/sim/cscheduler.cc
86 86
    // If there is still no message in the queue, there are
87 87
    // also no barriers left (else we would have waited), and we quit:
88 88
    //
89

  
89 90
    else
90
        throw cTerminationException(eENDEDOK);
91
    throw cTerminationException(eENDEDOK);
91 92

  
92 93
#else
94
    cMessage *msg = NULL;
95
    cBarrierMessage* barrier = NULL;
93 96

  
94
    cMessage *msg = sim->msgQueue.removeFirst();
95
    if (!msg)
96
        throw cTerminationException(eENDEDOK);
97
    while (msg == NULL)
98
    {
99
        msg = sim->msgQueue.removeFirst();
100
        if (!msg)
101
            throw cTerminationException(eENDEDOK);
102
        /*
103
         * If we have a Barriermsg, we wait
104
         */
105
        barrier = dynamic_cast<cBarrierMessage*> (msg);
106
        if (barrier != NULL)
107
        {
108
            // wait for the task to complete
109
            barrier->wait();
110
            delete barrier;
111
            msg = NULL;
112
        }
113
    }
97 114

  
98
    cBarrierMessage* barrier = dynamic_cast<cBarrierMessage*> (msg);
99
            if (barrier != NULL)
100
            {
101
                return msg;
102
            }
103 115
    cSimpleModule* mod = (cSimpleModule*) sim->getModule(msg->getArrivalModuleId());
104
    cAsyncModule* aMod = NULL;
105 116
    if (mod->isAsyncModule())
106 117
    {
107
        aMod = (cAsyncModule*) mod;
108
        simtime_t now = cThreadPool::getSimTime();
118
        cAsyncModule* aMod = (cAsyncModule*) mod;
119
        simtime_t now = msg->getArrivalTime();
109 120
        simtime_t duration = aMod->getProcessingDelay(msg);
110
        if(aMod->mayParallelize(msg,duration)) {
121

  
122
        if (aMod->mayParallelize(msg, duration))
123
        {
111 124
            msg->setEventDuration(duration);
112 125
            // create a new barrier and schedule it
113 126
            cBarrierMessage* barrier = new cBarrierMessage();
......
117 130
            sim->msgQueue.insert(barrier);
118 131
        }
119 132
    }
120

  
121 133
    return msg;
122 134
#endif
123 135
}
......
175 187
    throw cTerminationException(eENDEDOK);
176 188

  
177 189
#else
190

  
191
    //TODO: Optimize to save state when the IES has to be emptied
192

  
178 193
    cMessage *msg;
179 194
    cBarrierMessage* barrier;
195
    cSimpleModule* mod;
196
    cAsyncModule* aMod;
180 197
    /*
181 198
     * Fill up independent event heap
182 199
     */
......
188 205
        {
189 206
            /*
190 207
             * if we hit a barrier, we are done and return the first independent msg
191
             * or the barrier if no such event exists
208
             * or we have wait at the barrier if no independent event exists
192 209
             */
193
            if (independentEventsHeap.empty()) {
194
                return msg;
195
            } else {
210
            if (independentEventsHeap.empty())
211
            {
212
                barrier->wait();
213
                delete barrier;
214
                continue;
215
            }
216
            else
217
            {
196 218
                sim->msgQueue.insert(msg);
197 219
                return independentEventsHeap.getFirst();
198 220
            }
199

  
200 221
        }
201
        cSimpleModule* mod = (cSimpleModule*) sim->getModule(msg->getArrivalModuleId());
202
        cAsyncModule* aMod = NULL;
222

  
223
        mod = (cSimpleModule*) sim->getModule(msg->getArrivalModuleId());
224
        aMod = NULL;
203 225
        if (mod->isAsyncModule())
204 226
        {
205 227
            aMod = (cAsyncModule*) mod;
206
        }
207
        if (aMod == NULL)
208
        {
209
            if (independentEventsHeap.empty()) {
210
                return msg;
211
            } else {
212
                sim->msgQueue.insert(msg);
213
                return independentEventsHeap.getFirst();
214
            }
215
        }
216
        else
217
        {
218
            simtime_t now = cThreadPool::getSimTime();
228
            simtime_t now = msg->getArrivalTime();
219 229
            simtime_t duration = aMod->getProcessingDelay(msg);
220 230
            msg->setEventDuration(duration);
221 231

  
222
            if(!aMod->mayParallelize(msg,duration)) {
223
                if (independentEventsHeap.empty()) {
232
            if (!aMod->mayParallelize(msg, duration))
233
            {
234
                if (independentEventsHeap.empty())
235
                {
224 236
                    return msg;
225
                } else {
237
                }
238
                else
239
                {
226 240
                    sim->msgQueue.insert(msg);
227 241
                    return independentEventsHeap.getFirst();
228 242
                }
229 243
            }
230

  
231

  
232 244
            // create a new barrier and schedule it
233 245
            cBarrierMessage* barrier = new cBarrierMessage();
234 246
            barrier->setArrival(aMod, -1, now + duration);
235 247
            msg->setBarrier(barrier);
236 248
            // insert user supplied message in task queue.
237 249
            sim->msgQueue.insert(barrier);
238
            printf("adding to IEH: %s, tend= %f, now First in IEH: ",((cSimpleModule*)sim->getModule(msg->getArrivalModuleId()))->getName(),SIMTIME_DBL(msg->getTend()));
250

  
251
            printf(
252
                    "adding to IEH: %s, tend= %f, now First in IEH: ",
253
                    ((cSimpleModule*) sim->getModule(msg->getArrivalModuleId()))->getName(),
254
                    SIMTIME_DBL(msg->getTend()));
255

  
239 256
            independentEventsHeap.insert(msg);
240
            printf("%s, length=%i\n", ((cSimpleModule*)sim->getModule(independentEventsHeap.peekFirst()->getArrivalModuleId()))->getName(), independentEventsHeap.length());
241 257

  
242
        }
258
            printf(
259
                    "%s, length=%i\n",
260
                    ((cSimpleModule*) sim->getModule(
261
                            independentEventsHeap.peekFirst()->getArrivalModuleId()))->getName(),
262
                    independentEventsHeap.length());
243 263

  
244
    }
264
        }
265
        else //Not a AsyncModule
266
        {
267
            if (independentEventsHeap.empty())
268
            {
269
                return msg;
270
            }
271
            else
272
            {
273
                sim->msgQueue.insert(msg);
274
                return independentEventsHeap.getFirst();
275
            }
276
        }
245 277

  
246
    /*
247
     * the big queue is empty
248
     * check if the independent event set is also empty
249
     */
250
    if (independentEventsHeap.empty()) {
251
        throw cTerminationException(eENDEDOK);
252
    }
253
    return independentEventsHeap.getFirst();
278
    } // while (!(sim->msgQueue.empty()))
279
/*
280
 * the FES is empty
281
 * check if the independent event set is also empty
282
 */
283
if (independentEventsHeap.empty())
284
{
285
    throw cTerminationException(eENDEDOK);
286
}
287
return independentEventsHeap.getFirst();
254 288
#endif
255 289
}
256 290

  
src/sim/csimulation.cc
645 645
#ifdef NOBARRIER
646 646
        //TODO move to scheduler?
647 647
        // Do we have to wait for a barrier?
648
        if(threaded) {
648
        if(threaded)
649
        {
649 650
            barrierMin = threadPool->waitAtBarrier(barrierMin, &msgQueue);
650 651
        }
651 652
#endif
......
653 654
        msg = schedulerp->getNextEvent();
654 655

  
655 656
        //Advance Simulation Time
656
        //TODO Move to scheduler? (only in case of barrier)
657 657
        cThreadPool::setSimTime(msg->getArrivalTime());
658 658

  
659
#ifndef NOBARRIER
660
        //TODO: move to scheduler
661
        // check if this is an barrier message indicating the end of an event
662
        cBarrierMessage* barrier = dynamic_cast<cBarrierMessage*> (msg);
663
        if (barrier != NULL) {
664
            // wait for the task to complete
665
            barrier->wait();
666
            delete barrier;
667

  
668
            //It was a Barrier Message, after waiting, we are done and can return
669
            setGlobalContext();
670
            event_num++;
671
            return;
672
        }
673
#endif
674 659
        // Update mod pointer:
675 660
        mod = (cSimpleModule*) simulation.vect[msg->getArrivalModuleId()];
676 661
        // notify the environment about the event (writes eventlog, etc.)
......
679 664
        // sequence chart tool if the message doesn't get immediately deleted or
680 665
        // sent out again
681 666
        msg->setPreviousEventNumber(event_num);
682

  
683 667
        // check if this module supports parallel execution
684
        if (mod->isAsyncModule()) {
668
        if (mod->isAsyncModule())
669
        {
685 670
            // yes, it does. Next, check if this event should be executed
686 671
            // in parallel
687 672
            cAsyncModule* aMod = (cAsyncModule*) mod;
688 673

  
689 674
            simtime_t duration = aMod->getProcessingDelay(msg);
690

  
691
            if (duration < SimTime::simTimeZero) {
675
            if (duration < SimTime::simTimeZero)
676
            {
692 677
                throw cRuntimeError("negative event duration not allowed.");
693 678
            }
694 679
            msg->setEventDuration(duration);
695 680

  
696 681
            bool mayPar = aMod->mayParallelize(msg, duration);
697 682
            // execute this event in parallel
698
            if (mayPar && threaded) {
683
            if (mayPar && threaded)
684
            {
699 685
                // block if another thread is busy inside this module
700 686
                // then set the module to busy
701 687
                aMod->waitIfBusy();
702 688
                aMod->setBusy();
703 689
                //printf("Offloading: %s\n",mod->getName());
704 690
                barrierMin = threadPool->insertTask(msg, duration, barrierMin);
705
            } else {
691
            }
692
            else
693
            {
706 694
                // set the context for sequential execution
707 695
                setContext(mod);
708 696
                setContextType(CTX_EVENT);
709 697
                // take ownership in callHandleMessage after concurrency check
710

  
711 698
                aMod->callHandleMessage(msg);
712 699
            }
713

  
714
            //We have handled the Message / offloaded it. We can return
715
            setGlobalContext();
716
            event_num++;
717
            return;
718 700
        }
719

  
720
        //The module is no cAsyncModule
721
        // set the context for sequential execution
722
        setContext(mod);
723
        setContextType(CTX_EVENT);
724
        // take owner here: no danger of a race condition since
725
        // simple modules are only called from here
726
        mod->take(msg);
727
        // if there was an error during simulation, handleMessage()
728
        // will come back with an exception
729
        mod->handleMessage(msg);
730

  
701
        else
702
        { //The module is not a cAsyncModule
703

  
704
            // set the context for sequential execution
705
            setContext(mod);
706
            setContextType(CTX_EVENT);
707
            // take owner here: no danger of a race condition since
708
            // simple modules are only called from here
709
            mod->take(msg);
710
            // if there was an error during simulation, handleMessage()
711
            // will come back with an exception
712
            mod->handleMessage(msg);
713
        }
731 714

  
732 715
        //We have handled the Message, return
733 716
        setGlobalContext();
734 717
        event_num++;
735 718
        return;
736

  
737 719
    }
738 720
    catch (cDeleteModuleException& e)
739 721
    {

Also available in: Unified diff