COURSE:
49411- REAL TIME SYSTEMS-PROJECT
Dynamic Priority Scheduler using UPPAAL
STUDENTS:
OPREA CATALIN GABRIEL <[email protected]>
YIDE CAO <[email protected]>
Abstract
This project is about how to implement real time systems (including modeling
, specifying and verifying).
The tools of UPPAAL
are used to construct abstract models of a real-time system, to simulate
its dynamically
behavior, to specify and verify its safety and bounded liveness properties
in terms of its model.
This data is also available at :http://www.ebar.dtu.dk/~c974446/telephone.html
Contents:
2. Dynamic Priority Scheduling
4 Dedicated (Hotline) Communication System and LANs subnetworks communication
protocol
- An example of real time scheduling .
5 -Our model of dynamic scheduling communication system.
7. Discussion, Conclusions,Remarks
We used the specification language UPPAAL to prove timing properties of
our scheduling system. Our modeled system consists of a number of
users (tasks) which want to access simultaneously the same shared resource.
For instance one can imagine a the timed execution of a telephone
net system or a connection among multiple LAN-s where multiple users
of telephones or computers want to communicate with the same other user
in the same time. This thing is impossible and in order to manage this
situation one needs to implement a scheduler for this purpose. A good example
could be two LAN-s or local telephone exchange for multiple local users
which want to communicate only by a single cable. We implemented the model
of telephone systems in UPPAAL by constructing a model with imposed timing
requirements on the transitions and dynamic priority.
This is done in two steps. First, in Section 2, we reviewed the concept
of dynamic priority scheduling.
Then , we considered
our real-time systems and showed how these concepts can be used in
our model. These issues are interpreted
in the following part.
Appendix 1 serves as an overview of UPPAAL.
2. Dynamic Priority Scheduling
Dynamic scheduling of a real-time program has three basic steps: feasibility checking, schedule construction and dispatching.
Feasibility analysis
With fixed priority scheduling, feasibility analysis is typically done
statically, before the program is executed. Dynamic systems perform feasibility
checking on-line, as tasks arrive.
There are two approaches to scheduling in dynamic real-time systems:
1. Dynamic planning-based approach
2. Dynamic best effort approaches
Because a dynamic scheduling algorithm takes decisions without prior knowledge of the tasks, the total value is not predictable and the algorithm must attempt to maximize the value accrued from tasks that complete on time.
Schedule construction
Schedule construction is the process of ordering the tasks to be executed and storing this in a form that can be used by the dispatching step.
Dispatching
Dispatching is the process of deciding which task to execute next.
Priority assignment for tasks
A task t is the unit for scheduling; it is characterized by its arrival time AT , its absolute deadline D, its value V, its worst-case computation time C and its resource requirements {RR}. EST is the earliest start time at which the task can begin execution (EST is calculated when scheduling decisions are made).
The following condition relates AT, D,C,EST and the current time T:
AT<= EST<= D-C
Let Pr(t) be the priority of task t, and assume that the smaller the value
of Pr(t), the higher the priority. There are a number of possible priority
assignment policies.
1. Smallest arrival time first, or first-come-first served(FCFS)
2. Minimum processing time first(Min_C): Pr(t) =C
3. Minimum(or earliest)deadline first(Min_D):Pr(t)=D
4.Minimum earliest start time first (Min_S):Pr(t)=EST.
5.Minimum laxity first (Min_L):Pr(t)=D-(EST+C)
6.Minimum value first (Min_V):Pr(t)=V
7.Minimum value density first (Min_VD):Pr(t)= Tv/C
8.Min_D+Min_C:Pr(t)=D+W1*C
9.Min_D+Min_S:Pr(t)=D+W1*EST
10.Min_D+Min_S+Min_VD:Pr(t)=D+W1*Est+W2*V/C
In our implementation we chosen a policy which combine all the above
concepts. In our policy the priority is a dynamic one. Thus initially each
user (task) has a different static priority. After that the priority is
dynamically changed using a criteria that could be explained in the following
expression:
Pd_x:=Ps_x+Meet_Deadline_x*value_x*C_x / (deadline_x+timer_x);
where :
x=1, 2 or 3 is the
indices of the user
Ps_x=the static priority (initial priority)
of the user x
Meet_Deadline_x=1 if the process x
(call x) meets its deadline and zero otherwise.
Value_x=the importance of the process
x. As one knows the concept of the value of a process is very relative.
Basically a process is important before its deadline. However there are
many examples of real time processes that are still important after the
deadline. This depends very much by the specific application. For instance
in a telephony call If a VIP person try to connect another one for a VIP
message then this call should have the highest priority. The value of this
is depending of the fact that the caller accessed or no the other. After
connection the value of the call is sill important but not so high than
before the connection. in the time of connection the value is continuously
decreasing until the conversation is finished. However in LAN could be
processes which constant high value until the end or with the highest value
at the end. In our example due to the strong limitations of UPPAAL we chosen
3 levels of value for a call. These are :
2 if the user is in waiting for connection,
1 if the user is in speaking (connected) with
someone
0 if the user meted the deadline or if it
finished its speech and voluntarily cancel the speech !
C_x is the maximum computational time (speech time ) for user
x.
Hence ours concepts could be scratched in the following criteria's:
- a process with a higher computational time should have a higher priority.
- a process with a higher value should have a higher priority.
- a process with a lower deadline should have a higher
priority.
- a process which is waiting for connection has a continuously increasing
priority.
- a process which is connected has a continuously decreasing
priority.
- a disconnected or finished process has a null or very low priority.
3
.Timing of the planning
As the number of tasks increases, so does the cost of planning and there
is less time available for planning.This is the main reason for poor performance
of planning schemes during overloads. So when a system overload is anticipated
, use of a method that controls scheduling overheads is essential. There
are two simple approaches:
When
a task arrives, attempt to plan its execution along with previously scheduled
tasks:this is scheduling-at-arrival-time and all tasks that have not yet
executed are considered for planning when a new task arrives.
Postpone
the feasibility check until a task is chosen for execution: this is scheduling-at-dispatch-time
and can be done very quickly for non-pre-emptive task execution by checking
whether the new task will finish by its deadline.
The second approach is less flexible and announces task rejection very
late.Consequently, it does not provide sufficient lead time for considering
alternative actions when a task cannot meet its timing-constraints. Both
of them avoid resource wastage as a task does not begin execution unless
it is known that is will complete before its deadline.
To minimize scheduling overheads while giving enough lead time to choose
alternatives, instead of scheduling tasks when they arrive or when they
are dispatched, they should be scheduled somewhere in between- at the most
opportune time. If they can be scheduled at some punctual point, this can
limit the number of tasks to be considered for scheduling and avoids unnecessary
scheduling(or rescheduling) of tasks that have no effect on the order of
tasks early in the schedule.
Choice of the punctual point must take into account the fact that the larger
the mean laxity and the higher the load, the more tasks are ready to run
. The increasing number of tasks imposes growing scheduling overheads for
all except a scheduler with constant overheads. The punctual point is the
minimum laxity value, i.e. the value to which a task's laxity must drop'
before it becomes eligible for scheduling.In other words, the guarantee
of a task with laxity larger that the punctual point is postponed at most
until its laxity reaches the punctual point. Of course, if the system is
empty a task becomes eligible for scheduling by default. By postponing
scheduling decisions, the number of tasks scheduled at any time is kept
under control, reducing the scheduling overheads and potentially improving
the overall performance.
The main benefit of scheduling using punctual points is the reduced scheduling
overheads when compared to scheduling at arrival time. This is due to the
smaller number of relevant tasks(the tasks with laxities smaller than or
equal to the punctual point) that are scheduled at any given time. Clearly,
when the computational complexity of a scheduling algorithm is higher than
the complexity of maintaining the list of relevant tasks, the separation
into relevant tasks reduces the overall scheduling cost; that is, the scheduling
becomes more efficient.
Scheduling
at the opportune time ensures that a scheduling decision is made earlier
than when scheduling at arrival time. Consequently, the lead time for alternative
actions is adjustable and is based on design and run time parameters. Scheduling
at an opportune time (i.e. at the punctual point ) is more flexible , more
effective and more tolerant of timing errors than scheduling at dispatch
time, primarily due to its early warning characteristics. Hence, ways of
finding the punctual point for different system characteristics are required.
A
more experimental way to limit the number of scheduled tasks is to have
a Hit queue and a miss queue: the number of scheduled tasks in the Hit
queue is continuously adjusted according to the ratio of tasks that complete
on time (the 'hit' ratio). This method is adaptive , handles deadlines
and values and is easy to implement. However, it is not define a punctual
point.
The weakness of both these approaches is the lack of analytical methods
to adjust the number of scheduled tasks. The parameters that control the
number of scheduable tasks must be obtained through simulation and a newly
arrived task can miss its deadline before it gets considered for execution.
By contrast, if the punctual point is derived analytically, it can be ensured
that every task that arrives will be considered for execution.
The
number of scheduable tasks must be controlled using timing-constraints,
rather than by explicitly limiting the number of scheduable tasks; this
ensures that every task is considered for scheduling when its laxity reaches
the most opportune moment, the punctual point. The approach is especially
beneficial for systems where tasks have widely differing ,values, and rejecting
a task without considering it for scheduling might result in a large value
loss, something that can happen easily when the number of scheduable tasks
is fixed. Finally, the features of a 'well-timed scheduling framework'
are summarized below:
Newly arrived tasks are classified as relevant or irrelevant, depending
on their laxity.
Irrelevant
tasks are stored in a D-queue (the delay queue ), where they are delayed
until their laxity becomes equal with the punctual point, at which time
they become relevant. Relevant tasks are stored in an S-pool (the scheduling
pool ) as tasks eligible for immediate scheduling. When a task is put into
the S pool , a feasibility cheek is performed ; if this is satisfied, it
is transferred into the current feasible schedule. The separation of relevant
and irrelevant tasks apart from reducing the scheduling cost also contributes
to reducing the scheduling overheads due to queue handling operations.
4
Dedicated (Hotline) Communication System and LANs subnetworks communication
protocol-An example of real time scheduling .
A call controller object supports a dedicated bi-directional "hot-line"
service between two telephones.
The system consist of 2 local area network telephones
connected only by one cable between them. The cable can support only a
small amount of call between both local LANs. In our example we consider
that the cable can support only one connection. The real time conflict
is when more than 2 user want to communicate through that cable. The
actual sequence of events when a call is made is as follows:
1. Receiver lifted at caller's telephone, initiating call. The message
is sent to the local controller for processing.
2. The caller receive a temporary signal for network busy. If the cable
is not busy then the controller 1 send a request to the other
controller that its caller want to communicate with its subscriber. The
latter controller will test if the desired user phone is free and if it
so it will initiate the connection among them sending a ring message toward
callee and via controller 1 to the caller. During that time of processing
command the caller will receive a message as "call divert on ". The reason
is that in the network the phones could have different static priorities
and that their dynamic priorities could be different even conversely depending
on the time. For instance if a user is calling for a long time and its
deadline is very close to be met then its dynamic priority could be larger.
The implementation of the protocol should take into account the static
priority but it should try as much as possible to avoid that any
call meets its deadline. So both controllers should do their best effort
in assigning a dynamic
priority chosen in
such way that always a red phone call for instance will never be discarded
as it meets the deadline, but on the other side that system should try
to make an intelligent scheduling in order to avoid discarding of any calls
even they are of a lower importance (value).
2. Callee's telephone rings for a pre-determined length of time -that is
the meaning of deadline.
3. If the handset is lifted at the callee's telephone while it is still
ringing, the two telephones are connected by the call controller until
the call completes. Otherwise, the controller will stop the callee's telephone
ringing when a predetermined "ring-time" expires and disconnect both sides
of the call .
4. If a call is successfully connected, it continues until such time as
one (or both) of the parties hangs up. If only one of the participants
clears the call in this way, a "Call Disconnected" signal is sent to the
other telephone.
5. If, for some reason, a caller hangs up just as a callee responds, the
call is cleared by the controller and the "Call Disconnected" signal is
sent to the callee's telephone.
6. Finally, when a call is cleared by the controller(for example because
it was not answered quickly enough), the "Call-Disconnected" signal is
sent to both telephones to ensure that both parties replace their receivers.
We tried to implement this using UPPAAL. Actually
we was able to design a system with its behavior very close to a real user
and his/her cellular phone. We set up 2 channel (the equivalent for transmission
radio frequency and reception radio frequency ) with some convention about
the values for the data which flow through it. For instance one can make
the convention that these channels in a UPPAAL simulations could be as
integer variable x and y that carry the following conventions that are
very similar to the real voice signal modulation with DTMF.
x or y is:
1....N means the Id of one of the telephones (phone number).
0 means that the phone is free.
-1 means speech voice.
-2 means ring tone
-3 means busy phone
-4 means cancel call
-5 means network busy (call divert on)
-6 means handset picked up,
and so on .
We meet difficulties in implementation of the controllers, due to the limitations of UPPAAL but the ideas are correct and the system could be implemented in a larger time. The main drawback is that its complexity will be huge because UPPAAL doesn't support arrays and different variables in assignment. our work in this topic could be fond here or here in a ghostview format. We would need at least one month to implement that and the verification will be very difficult for the system as due to its complexity (could take several days).
5 -Our model of dynamic scheduling communication system.
Our model follows in detail the concept mentioned above.As mentioned before
we tried in the beginning to implement a real telephone with both voice,
alert tones, signaling etc., but due to the complexity of such system and
due to the strong limitations of UPPAL we given up. One of this strong
drawbacks of UPPAAL is that it doesn't permit us to assign different variables
even if they are of the same type. The other one is that in UPPAL
is forbidden division, clock assignment and array operations.
In our example we don't use the queues for relevant and irrelevant calls.
We use a very fair dynamic priority assignment. In order to do that we
consider that the importance (value) of a task is larger than the user
is waiting to be connected than in the moment that it is connected. That
is as in real life the most important information is delivered at the beginning
of conversation and after that its quality becomes cool. We take in account
all the concepts mentioned in previous chapters and we think that our dynamic
priority meets all the practical events: predictive and unpredivtive behavior
on a real time system. This is why we chosen to change periodically the
values of the processes, the deadlines and the computational time. In the
real life we can't predict what kind of parameters our processes will have
but we could know the interval span of them (half predicting).
We all these limitations we implemented our system as a block which consist
of the following parts Users and a Scheduller:
Users: User_1, User_2,
User_3 - they are
3 autonomous automata which send requests to the scheduler saying that
they want to be connected (request_x==1) or not (request_x==0) with the
specific user. The scheduler reads these messages and depending on the
above parameters constructs a dynamic priority. If more than one user wants
to communicate with an unic receiver from the user part then the scheduler
will connect the one who has the highest priority.
In order to do this
the Scheduler sends a message to the highest priority user saying that
this is connected (message_x:=1) and inform all the other users that the
line (bus ) is busy and ask them to wait or to disconnect (message_x:=0).
The user read this messages and makes decisions relate to them. If a user
is connected the then it send an message in the network informing the scheduler
about that (conect_x=1. The scheduler implementation it id very simle.It
is a binary decision tree which queued tasks according with these priorities.
As we said due to the strong limitations of UPPAAL concerning to
computing expressions with different variables and due to the fact that
comparison of different variables it is forbidden we decided to calculate
the priorities inside each user. This should not be seen as a restriction
of the generality as this computations are independent of the direct user
decisions(transitions ) and only the scheduler can make decision about
them. For instance we put the shared variables x12,x13,x23 variables which
are incremented at each probability changing inside of the
specific user. For instance if the priority Pd_1:=Pd1+6 then x12:=x12+6.
On the other side if the priority of Pd2:=Pd2+6 then x12:=x12-6,x13:=x13-6.
In this case it is easy to see that through that shared variables x12,x13,x23
we can signaling to the scheduler which process has a higher priory. Thus
if x12(t)<0 then Pd1<Pd2,x13()>0 means that Pd3<Pd1 and
so on. These variables could be only written by the user and the decider
is only the scheduler. Even that our model looks complicate , it is very
simple and one could easily understand it by following the graph and our
explanations. All defionitions of data that we used in our
system is defined in Config
Box.
The User and Scheduler work as follows:
In the initial state it assign values to its static priority, it makes
no request and it set its computational time, deadline and set the
values x12,x13 and x23 to 0 when it is waiting for a signal from the scheduler.
Then the states Ux_1 and Ux_3 simulate the flip-flop during
the time that the user wait to be connected. if in t<=Deadline the user
is connected (it receive message_x==1 from the scheduler) then the user
goes in Ux_4 state, otherwise it return again in U2_x and makes a new request
in a new Deadline. We chose that periodically the computational time and
the deadlines for these processes to be changed (but off course that not
in the active periods:waiting for connection or when speaking,) in the
passive periods(in transition following the meeting of deadline of after
the process voluntarily finishes a connection). The purpose for this is
that we want to simulate a very real behavior when users can change
their mind during the time relate to their needs. The Ux_4 and Ux_5 states
are for simulating of connexion time. As one can see during to this flip-flop
from one state to another the value of process is changing , the computational
time is checked and this behavior could be leaded if the user voluntarily
finishes the call (it consumed its time for call stored in C_x (timer_X>=C_x))
or if the scheduler find out a higher priority process that is waiting
to be connected and it disconnect it. The variable timer_x is so used both
to compute the time waiting for connection and the time spending in connection.
Please note that the timer_x is reset when a process meets its deadline
or when a transition to the connected state Ux_4 is made or when the connection
is finished so timer_x always measures what actually should measure ! The
same note is for value_x, C_x and Deadline_x. If a process finished in
a voluntarily mode then it change the next computational time and deadline.
This is the reason for the state Ux_2. If a process meets its deadline
then this importance will be very low and value_x:=0. I hope that our graph
is enough expressive in order to avoid suplimentarily details.
As we have seen the UPPAAL doesn't allow us to compare different variables.
However we did this by using that trick with the shared variables
x12,x13,x23. Their purpose is only to dinamically compare the values of
Pd1,Pd2 and Pd3 (Pdx means the dynamically priority of the process number;
x=1,2 or 3). If UPPAAL would allow us to compare those priorities
we would not need to compute any global variable inside a specific user.
The user should care only by itself and to obey the scheduler orders. In
fact in our case this is doing so because even the user change the value
of x12,x13 or x23 it doesn't care about this effects and when make this
decision it not communicate with other users. It merely communicate only
with the controller. So our example from our model is very correctly and
it is no doubt about this ! The scheduler assign priorities and schedule
the independent requests send by different users.
So: x12>=1 means Pd1>Pd2 and x12<=0 means
Pd1<=Pd2,
x23>=1 means Pd2>Pd3 and x23<=0 means Pd2<=Pd3,
x13>=1 means Pd1>Pd3 and x13<=0 means Pd1<=Pd3
I hope that the logic of the scheduller is now very simple , it is a merely
a software multiplexer with 3 imputes Pd1,Pd2,Pd3 (substituted by x12,x13,x23
) and 8 outputs depending of the relationship among them. Of course
that Pd1,Pd2 and Pd3 are directly connected with request_1,request_2, and
request_3 and one should not be confused about that.
The previous model illustrate that real-time applications deal with
dynamically scheduled priority communication. However this model
deal only with a simple call control application. Note that the definition
of the call show features which relate to concurrent process.
(only some part of it is real time) We have therefore based our ideas on
this framework to be applied
to a more general case as wireless GSM telephony for example.
In the mobile telephone one has the call diverting option,and
off course that the phone exchange makes dynamic scheduling and priorities.
Our implementation is an example of a real-time distributed system.
It could be a collection of loosely coupled telephones
that operate asynchronously and autonomously and cooperate on the execution
of one (or more) problems. The
telephone communication system can be viewed as consisting of three major
layers:
Application processes,
distributed operating system and a communication subsystem
The application processes are the "user" in this three-part structure,
making use of the services provided by the distributed operating system
and the communication subsystem.
The distributed operating system unifies and and integrates the controller,
and provides a uniform high-level system interface to the application processes.
The communication subsystem hardware and software facilitate the exchange
of messages among the distributed components.Our experiment was concerned
with the performance of the lowest levels of the communication subsystem
--the physical communication medium(the physical layer) shared bus.
A more less the same same discussion could be done if one considers a LAN
of PC computers of an shared environment when multiple tasks want to use
the same resource in the same time.
6.
Test and verification.
We spend a lot of time with this design and we carefully implement each
state and transition searching to consider all the options in order to
avoid any deadlock or unpredictable transition. We checked the program
for errors until we removed all syntax errors. We simulated this system
several times and under different conditions and it never give us a wrong
behavior (2 users connected in the same time, priority low users connected
or priority users deadlocked !).We have seen during the simulation both
the tokens float and the space variables. We put in our code some variables
counter_x in order to count for how many times an user meet its deadline
during the simulation.We wrote an invariant (see testscheduller.q
for details) for testing that never is possible that the highest priority
process to not be connected (S_19 state and S_20 state ) when it require
to be connected. We started the verification of our software in E-Bar and
after 2 hours of verification the testing program tool from UPPAAL was
still working without any error message. The problem is that our system
has much states and transitions and the number of combinations that
the verification tool should test it is enormous. Our wish to have a system
with a behavior in that the deadlines and computational time could alternate
from a call to another for the same user makes the number of combinations
very huge ! This is the reason why it may be possible that the verification
tool to spend several days until will complete. But
we strongly thing that it will never give us wrong message. We provided
the source code for it here.
Note:
The verification will never end as in the dynamic priority allocation we
use the incrementation of Pd_x and x12,x13,x23. This will give an
infinite number of possible states of the automata. But as from simulation
viewing after about 20 minutes each user passes through all the states
and possible
ransitions. After that it is only a matter of the
scaling of the dynamic priorities. The fact that in one hour the verification
doesn't give any error message prove us that it will never give any error
message
The use of x12,x13,x23 as shared variables which represent the following
subtractions:
x12:= Pd1-Pd2,
x13:=Pd2-Pd3,
x23:=Pd2-Pd3
it is always true. This is another reason that proves
that our program is without any bug. One can see easily this during the
simulation by opening the "show variables" option
box from the run menu !
7. Discussion, Conclusions,Remarks
Real-Time vs. Concurrent Programming
Real-time programs are programs which must satisfy strict timing demands.
Such programs are required to respond to external stimuli and generate
results within a fixed time deadline. In designing a real-time program
there are two fundamental concerns:(1) to produce correct results, and
(2) to produce the results within the allotted time.
Although real-time and concurrent programming have a number of common goals
they also differ in fundamental ways. For example, inreal-time programming
the programmer must be able to control precisely the sequencing of operations
and, possibly, of processes. By contrast, in concurrent the goal is to
hide the precise sequencing of operations from the user. Similarly, in
real-time programming the programmer must be aware of the detailed timing
and control characteristics of the external devices, whereas in concurrent
programming these characteristics are generally hidden from him.
Our Scheduller Implementation
This is not the best solution of a dynamic priority scheduller, but it in our point of view is good compromise between the complexity of the solution and the available tool. Further solutions could be designed : queues of irrelevant and relevant processes, punctual points for executions and all the major hints of Chap.3. In this case additional vertices should be added to the scheduller and a ring of vertices should formed in order to simulate every queue. For each vertices in this queue several edges should be added in order to simulate the sampling rate at which the tokens are compared. The drawback of this solution will consist in an increased complexity and very few practical chances to test (verify) the invariants(far too many states). An more nice alternative solution for that would be to do it in JAVA or ADDA software.
Remarks
UPPAL is a very strong tool for testing real time systems as it analysing
of all the cases. Many other tools can only simulate a real time system
(ex Matlab which we tested and we saw that it could run concurrently :
two completely independent shells on the same computer or LAN ) ).
Its drawback is that so far it has no any tools for analysing
all the possible solutions (invariants) but it has a more attractive environment
if one is pleased only with simulations.
Overview of UPPAAL
UPPAAL is a tool box for modeling, simulation and verification of
real-time systems, based on constraint-solving and on-the-fly techniques,
developed jointly by Uppsala University and Aalborg university. It is appropriate
for systems that can be modeled as a collection of non deterministic processes
with finite control structure and real-valued clocks, communication through
channels and (or) shared variables. Typical application areas include real-time
controllers and communication protocols in particular, those where timing
aspects are critical.
UPPAAL consists of three main parts: a description language, a simulator
and a model-checker. The description language is a non-deterministic guarded
command language with data types.
To facilitate modeling,
uppaal provides both graphical and textual formats for the description
language.
Model-Checking. The
model-checker is designed to check for invariant and reachability properties,
in particular whether certain combinations of control-nodes and constraints
on clocks and integer variables are reachable from an
initial configuration.
More details could be found at http://www.docs.uu.se/docs/rtmv/uppaal/
We have met a lot of troubles in printing our ghostview files for the parts of our system as they are so large . This is the reason why we attached them in their *.ps and *.atg (original UPPAAL ) format here:
UPPAAL CODE SOURCE DEVELOPMENT
Whole Schematics in Ghostview format
User1,
User_2 ,User_3
, Config and Scheduller
picture in a ghostview format
This data file could be found at: http://www.ebar.dtu.dk/~c974446/telephone.html