1 | package de.uka.ipd.sdq.scheduler.loaddistribution.balancers; |
2 | |
3 | import java.util.List; |
4 | |
5 | import de.uka.ipd.sdq.scheduler.processes.IActiveProcess; |
6 | import de.uka.ipd.sdq.scheduler.processes.impl.PreemptiveProcess; |
7 | import de.uka.ipd.sdq.scheduler.resources.IResourceInstance; |
8 | |
9 | /** |
10 | * Moves one process to each idle resource, if possible. |
11 | * |
12 | * @author jens.happe |
13 | * |
14 | */ |
15 | public class OneToIdleBalancer extends AbstractLoadBalancer { |
16 | |
17 | private int upperBound = 1; |
18 | |
19 | private int lowerBound = 1; |
20 | |
21 | public OneToIdleBalancer(double balance_interval, boolean prio_increasing, |
22 | boolean queue_ascending) { |
23 | super(balance_interval, prio_increasing, queue_ascending); |
24 | } |
25 | |
26 | public void activelyBalance(IResourceInstance instance) { |
27 | // double now = simulator.time(); |
28 | // if ((now - last_balanced.get(instance)) > balancing_interval) { |
29 | // balanceAsReceiver(instance); |
30 | // last_balanced.put(instance, now); |
31 | // } |
32 | } |
33 | |
34 | public void onFork(IResourceInstance instance) { |
35 | balanceAsSender(instance); |
36 | } |
37 | |
38 | public void onSleep(IResourceInstance instance) { |
39 | balanceAsReceiver(instance); |
40 | } |
41 | |
42 | public void onTerminate(IResourceInstance instance) { |
43 | balanceAsReceiver(instance); |
44 | } |
45 | |
46 | public void onWake(IResourceInstance instance) { |
47 | balanceAsSender(instance); |
48 | } |
49 | |
50 | private void balanceAsSender(IResourceInstance instance) { |
51 | if (load(instance) > upperBound) { |
52 | balance(instance, getReceiver()); |
53 | } |
54 | } |
55 | |
56 | private void balanceAsReceiver(IResourceInstance instance) { |
57 | if (load(instance) < lowerBound) { |
58 | balance(getSender(), instance); |
59 | } |
60 | } |
61 | |
62 | private IResourceInstance getSender() { |
63 | IResourceInstance result = null; |
64 | for (IResourceInstance ri : queue_holder.getResourceInstances()) { |
65 | if (result == null || load(ri) > load(result)) { |
66 | result = ri; |
67 | } |
68 | } |
69 | if (load(result) > upperBound) { |
70 | return result; |
71 | } else { |
72 | return null; |
73 | } |
74 | } |
75 | |
76 | private IResourceInstance getReceiver() { |
77 | IResourceInstance result = null; |
78 | for (IResourceInstance ri : queue_holder.getResourceInstances()) { |
79 | if (result == null || load(ri) < load(result)) { |
80 | result = ri; |
81 | } |
82 | } |
83 | if (load(result) < lowerBound) { |
84 | return result; |
85 | } else { |
86 | return null; |
87 | } |
88 | } |
89 | |
90 | private void balance(IResourceInstance sender, IResourceInstance receiver) { |
91 | if (sender != null && receiver != null) { |
92 | if (!sender.equals(receiver)) { |
93 | List<IActiveProcess> processList = queue_holder.getRunQueueFor( |
94 | sender).identifyMovableProcesses(receiver, |
95 | prio_increasing, queue_ascending, 1); |
96 | |
97 | if (processList.size() > 0) { |
98 | fakeThreadLoadBalancing(processList.get(0), sender, |
99 | receiver); |
100 | } |
101 | } |
102 | } |
103 | } |
104 | |
105 | /** |
106 | * From the beautiful method name, the careful reader might have guessed |
107 | * that things get a bit, well, messy at this point. Fact is, that Windows |
108 | * (or Java ?) balances threads differently from processes by simply |
109 | * changing the association between light weight processes and (user level) |
110 | * threads. That makes things a bit difficult as heavy weight and light |
111 | * weight processes as well as threads would have to be reflected in the |
112 | * model. |
113 | * |
114 | * Sorry for anyone responsible fixing this, but I hope this comment helps. |
115 | * Further discussion can be found in class 'SimResourceInstance' at |
116 | * variable 'last_running_process'. |
117 | * |
118 | * @param process |
119 | * moved process |
120 | * @param sender |
121 | * sending resource instance |
122 | * @param receiver |
123 | * receiving resource instance |
124 | */ |
125 | private void fakeThreadLoadBalancing(IActiveProcess process, |
126 | IResourceInstance sender, IResourceInstance receiver) { |
127 | if (receiver.getLastRunningProcess() != null) { |
128 | PreemptiveProcess p = (PreemptiveProcess) receiver.getLastRunningProcess(); |
129 | |
130 | // here we assume that the waiting process is in fact a thread that |
131 | // belongs to the same process as the thread (process) to move. |
132 | // the following assigns the waiting thread to the resource of |
133 | // the sender. This fakes the switch of LWPs. |
134 | if (p.isWaiting()) { |
135 | p.setLastInstance(process.getLastInstance()); |
136 | p.setIdealInstance(process.getIdealInstance()); |
137 | } |
138 | } |
139 | queue_holder.move(process, sender, receiver); |
140 | } |
141 | } |