Statistics
| Branch: | Revision:

root / src / sim / cscheduler.cc @ a3d116e3

History | View | Annotate | Download (7.11 KB)

1
//=========================================================================
2
//  CSCHEDULER.CC - part of
3
//
4
//                  OMNeT++/OMNEST
5
//           Discrete System Simulation in C++
6
//
7
//  Author: Andras Varga, 2003
8
//
9
//=========================================================================
10

    
11
/*--------------------------------------------------------------*
12
  Copyright (C) 2003-2008 Andras Varga
13
  Copyright (C) 2006-2008 OpenSim Ltd.
14
  Monash University, Dept. of Electrical and Computer Systems Eng.
15
  Melbourne, Australia
16

17
  This file is distributed WITHOUT ANY WARRANTY. See the file
18
  `license' for details on this and other legal matters.
19
*--------------------------------------------------------------*/
20

    
21
#include "cscheduler.h"
22
#include "cmessage.h"
23
#include "csimulation.h"
24
#include "cmessageheap.h"
25
#include "globals.h"
26
#include "cenvir.h"
27
#include "cconfiguration.h"
28
#include "cconfigoption.h"
29
#include "platmisc.h" // usleep
30
#include "cbarriermessage.h"
31

    
32
USING_NAMESPACE
33

    
34
Register_GlobalConfigOption(CFGID_REALTIMESCHEDULER_SCALING, "realtimescheduler-scaling", CFG_DOUBLE, NULL, "When cRealTimeScheduler is selected as scheduler class: ratio of simulation time to real time. For example, scaling=2 will cause simulation time to progress twice as fast as runtime.");
35

    
36
cScheduler::cScheduler()
37
{
38
    sim = NULL;
39
}
40

    
41
cScheduler::~cScheduler()
42
{
43
}
44

    
45
void cScheduler::setSimulation(cSimulation *_sim)
46
{
47
    sim = _sim;
48
}
49

    
50
//-----
51

    
52
Register_Class(cSequentialScheduler);
53

    
54
cMessage *cSequentialScheduler::getNextEvent()
55
{
56
#ifdef NOBARRIER
57
    //
58
    // If we retrieve a valid msg from the queue, we return it:
59
    //
60
    cMessage *msg = sim->msgQueue.peekFirst();
61
    if (msg)
62
        return msg;
63

    
64
    //
65
    // if there is no event left and we don't use the threadpool, end the sim
66
    //
67
    if (!sim->threadPool)
68
        throw cTerminationException(eENDEDOK);
69

    
70
    //
71
    // If we did not get a valid msg from the queue, but there are still
72
    // barrier messages left, we wait:
73
    //
74
    while (sim->msgQueue.empty() && !sim->threadPool->barrierEmpty())
75
    {
76
        __asm__ ("pause");
77
    }
78
    msg = sim->msgQueue.peekFirst();
79

    
80
    //
81
    // If there is a msg now, we return it:
82
    //
83
    if (msg)
84
        return msg;
85

    
86
    //
87
    // If there is still no message in the queue, there are
88
    // also no barriers left (else we would have waited), and we quit:
89
    //
90
    else
91
        throw cTerminationException(eENDEDOK);
92

    
93
#else
94
    cMessage *msg = sim->msgQueue.peekFirst();
95
    if (!msg)
96
        throw cTerminationException(eENDEDOK);
97
    return msg;
98
#endif
99
}
100

    
101
//-----
102
Register_Class(cEEFScheduler)
103
;
104

    
105
cEEFScheduler::cEEFScheduler()
106
{
107
}
108
cEEFScheduler::~cEEFScheduler()
109
{
110
}
111

    
112
cMessage *cEEFScheduler::getNextEvent()
113
{
114
#ifdef NOBARRIER
115
    //
116
    // If we retrieve a valid msg from the queue, we return it:
117
    //
118
    cMessage *msg = sim->msgQueue.peekFirst();
119
    if (msg)
120
    return msg;
121

    
122
    //
123
    // if there is no event left and we don't use the threadpool, end the sim
124
    //
125
    if (!sim->threadPool)
126
    throw cTerminationException(eENDEDOK);
127

    
128
    //
129
    // If we did not get a valid msg from the queue, but there are still
130
    // barrier messages left, we wait:
131
    //
132
    while (sim->msgQueue.empty() && !sim->threadPool->barrierEmpty())
133
    {
134
        __asm__ ("pause");
135
    }
136
    msg = sim->msgQueue.peekFirst();
137

    
138
    //
139
    // If there is a msg now, we return it:
140
    //
141
    if (msg)
142
    return msg;
143

    
144
    //
145
    // If there is still no message in the queue, there are
146
    // also no barriers left (else we would have waited), and we quit:
147
    //
148

    
149
    else
150
    throw cTerminationException(eENDEDOK);
151

    
152
#else
153
    cMessage *msg;
154
    cBarrierMessage* barrier;
155
    while (!sim->msgQueue.empty())
156
    {
157
        msg = sim->msgQueue.peekFirst();
158
        barrier = dynamic_cast<cBarrierMessage*> (msg);
159
        if (barrier != NULL)
160
        {
161
            return independentEventsHeap.empty() ? msg
162
                    : independentEventsHeap.peekFirst();
163
        }
164
        independentEventsHeap.insert(sim->msgQueue.removeFirst());
165
    }
166
    if (independentEventsHeap.empty()) {
167
        throw cTerminationException(eENDEDOK);
168
    }
169
    return independentEventsHeap.peekFirst();
170
#endif
171
}
172

    
173
cMessage* cEEFScheduler::removeNextEvent() {
174
    printf ("Test");
175
    return independentEventsHeap.empty() ? sim->msgQueue.removeFirst() : independentEventsHeap.getFirst();
176
}
177

    
178
//-----
179
Register_Class(cRealTimeScheduler);
180

    
181
void cRealTimeScheduler::startRun()
182
{
183
    factor = ev.getConfig()->getAsDouble(CFGID_REALTIMESCHEDULER_SCALING);
184
    if (factor!=0)
185
        factor = 1/factor;
186
    doScaling = (factor!=0);
187

    
188
    gettimeofday(&baseTime, NULL);
189
}
190

    
191
void cRealTimeScheduler::endRun()
192
{
193
}
194

    
195
void cRealTimeScheduler::executionResumed()
196
{
197
    gettimeofday(&baseTime, NULL);
198
    baseTime = timeval_substract(baseTime, SIMTIME_DBL(doScaling ? factor*sim->getSimTime() : sim->getSimTime()));
199
}
200

    
201
bool cRealTimeScheduler::waitUntil(const timeval& targetTime)
202
{
203
    // if there's more than 200ms to wait, wait in 100ms chunks
204
    // in order to keep UI responsiveness by invoking ev.idle()
205
    timeval curTime;
206
    gettimeofday(&curTime, NULL);
207
    while (targetTime.tv_sec-curTime.tv_sec >=2 ||
208
           timeval_diff_usec(targetTime, curTime) >= 200000)
209
    {
210
        usleep(100000); // 100ms
211
        if (ev.idle())
212
            return false;
213
        gettimeofday(&curTime, NULL);
214
    }
215

    
216
    // difference is now at most 100ms, do it at once
217
    long usec = timeval_diff_usec(targetTime, curTime);
218
    if (usec>0)
219
        usleep(usec);
220
    return true;
221
}
222

    
223
cMessage *cRealTimeScheduler::getNextEvent()
224
{
225
#ifdef NOBARRIER
226
    //
227
    // If we retrieve a valid msg from the queue, we return it:
228
    //
229
    cMessage *msg = sim->msgQueue.peekFirst();
230
    if (msg)
231
        return msg;
232

    
233
    //
234
    // if there is no event left and we don't use the threadpool, end the sim
235
    //
236
    if (!sim->threadPool)
237
        throw cTerminationException(eENDEDOK);
238

    
239
    //
240
    // If we did not get a valid msg from the queue, but there are still
241
    // barrier messages left, we wait:
242
    //
243
    while (sim->msgQueue.empty() && !sim->threadPool->barrierEmpty())
244
    {
245
        __asm__ ("pause");
246
    }
247
    msg = sim->msgQueue.peekFirst();
248

    
249
    //
250
    // If there is a msg now, we return it:
251
    //
252
    if (msg)
253
        return msg;
254

    
255
    //
256
    // If there is still no message in the queue, there are
257
    // also no barriers left (else we would have waited), and we quit:
258
    //
259
    else
260
        throw cTerminationException(eENDEDOK);
261

    
262
#else
263
    cMessage *msg = sim->msgQueue.peekFirst();
264
    if (!msg)
265
        throw cTerminationException(eENDEDOK);
266

    
267
    // calculate target time
268
    simtime_t eventSimtime = msg->getArrivalTime();
269
    timeval targetTime = timeval_add(baseTime, SIMTIME_DBL(doScaling ? factor*eventSimtime : eventSimtime));
270

    
271
    // if needed, wait until that time arrives
272
    timeval curTime;
273
    gettimeofday(&curTime, NULL);
274
    if (timeval_greater(targetTime, curTime))
275
    {
276
        if (!waitUntil(targetTime))
277
            return NULL; // user break
278
    }
279
    else
280
    {
281
        // we're behind -- customized versions of this class may alert
282
        // if we're too much behind, or modify basetime to accept the skew
283
    }
284

    
285
    // ok, return the message
286
    return msg;
287
#endif
288
}
289

    
290

    
291