R := P.R_Queue.Front_of; if R.R_time > Now then P.Replenishment.Event_Time := R.R_Time; Simulator.Schedule_Event (P.Replenishment); pragma Debug (Trace (5, Name (P.T.all) & "next replenishment due at" & Time'Image (R.R_Time))); Policy_Suspend (P.T); Schedule; else pragma Debug (Trace (7, Name (P.T.all) & "starting new replenishment chunk")); -- start using new chunk (**) P.T.Priority := R.R_Time + P.Parms.Budget_Interval; end if; if R := P.R_Queue.Front_Of; if P.Is_Suspended or P.Usage = R.R_Amount then -- Get the next chunk. -- Set server deadline to the chunk's deadline. P.T.Priority := R.R_Time + P.Parms.Budget_Interval; if R.R_Time > Now then -- Suspend the server until the replenishment. Policy_Suspend (P.T); -- Schedule a replenishment event. P.Replenishment.Event_Time := R.R_Time; Simulator.Schedule_Event (P.Replenishment); end if; elsif P.Is_Suspended then -- Compute the replenishment. R.R_Time := P.T.Priority; P.R_Queue.Pop; if P.Usage < R.R_Amount then -- Split the chunk. -- R2 is the unused part. R2.R_Amount := R.R_Amount - P.Usage; R2.R_Time := R.R_Time; Trace (0, "R.R_time = " & Time'Image (R.R_Time)); P.R_Queue.Add (R2); end if; -- R is the used part. R.R_Amount := P.Usage; R.R_Time := P.T.Priority; P.R_Queue.Add (R); P.Usage := 0; else -- end if; R.R_Time := E.T.Priority; P.R_Queue.Add (R); P.Usage := 0; end if; -- Check for errors pragma Debug (Check_R_Sum (P.R_Queue, P.Parms.Budget,"Exhaustion")); -- Fetch the next replenishment chunk. -- The new server priority is the chunk arrival time -- plus the server "period". R := P.R_Queue.Front_Of; P.T.Priority := R.R_Time + P.Parms.Budget_Interval; -- Schedule a replenishment event if we need to. if R.R_time > Now then P.Replenishment.Event_Time := R.R_Time; Simulator.Schedule_Event (P.Replenishment); pragma Debug (Trace (5, Name (P.T.all) & "next replenishment due at" & Time'Image (R.R_Time))); -- Suspend the thread until the replenishment comes. Policy_Suspend (P.T); -- Call the scheduler to choose another thread. Schedule; else -- We can continue, using the next chunk. pragma Debug (Trace (7, Name (P.T.all) & "starting new chunk")); end if; pragma Debug (Trace_Usage (9, P, "Exhaustion")); Used := Now - P.Last_Usage_Update_Time; pragma Assert (Used > 0); P.Usage := P.Usage + Used; -- Lie about the last Go time, since we are doing the -- time accounting here in this case, and will not Stop -- unless there are no more budget chunks left. If we -- do stop, Last_Usage_Update_Time will be reset when we Go again. P.Last_Usage_Update_Time := Now; -- Check for errors R := P.R_Queue.Front_Of; pragma Assert (P.Usage = R.R_Amount); pragma Debug (Check_Usage (3, P, R.R_Amount, "Budget_Exhaustion")); -- Set replenishment time to current deadline. -- The amount should be unchanged. -- Put the replenishment back in queue, in new position. P.R_Queue.Pop; R.R_Time := E.T.Priority; P.R_Queue.Add (R); P.Usage := 0; -- Check for errors pragma Debug (Check_R_Sum (P.R_Queue, P.Parms.Budget,"Exhaustion")); -- Fetch the next replenishment chunk. -- The new server priority is the chunk arrival time -- plus the server "period". R := P.R_Queue.Front_Of; P.T.Priority := R.R_Time + P.Parms.Budget_Interval; -- Schedule a replenishment event if we need to. if R.R_time > Now then P.Replenishment.Event_Time := R.R_Time; Simulator.Schedule_Event (P.Replenishment); pragma Debug (Trace (5, Name (P.T.all) & "next replenishment due at" & Time'Image (R.R_Time))); -- Suspend the thread until the replenishment comes. Policy_Suspend (P.T); -- Call the scheduler to choose another thread. Schedule; else -- We can continue, using the next chunk. pragma Debug (Trace (7, Name (P.T.all) & "starting new chunk")); end if; -- Debugging Support procedure Check_Usage (Threshold : Integer; P : Policy_Ref; Amount : Time; Msg : String) is begin if Debug_Level >= Threshold then if P.Usage > Amount then Put_Line (Log, "* usage > chunk size at " & Msg); Put (Log, " usage =" & Time'Image (P.Usage)); Put (Log, " chunk size =" & Time'Image (Amount)); pragma Assert (False); elsif P.Usage < 0 then Put (Log, "* usage < 0 at " & Msg); Put_Line (Log, " usage =" & Time'Image (P.Usage)); pragma Assert (False); end if; end if; end Check_Usage; procedure Trace_Usage (Threshold : Integer; P : Policy_Ref; Msg : String) is begin if Debug_Level >= Threshold then Put_Line (Log, Msg & ": Now =" & Time'Image (Simulator.Current_Time) & " Last_Usage_Update_Time =" & Time'Image (P.Last_Usage_Update_Time) & " P.Usage =" & Time'Image (P.Usage) & " P.R_Queue.Front_of.R_Amount =" & Time'Image (P.R_Queue.Front_Of.R_Amount)); end if; end Trace_Usage;