private void SvcWaitForAddress(CpuThreadState ThreadState) { long Address = (long)ThreadState.X0; ArbitrationType Type = (ArbitrationType)ThreadState.X1; int Value = (int)ThreadState.X2; long Timeout = (long)ThreadState.X3; Logger.PrintDebug(LogClass.KernelSvc, "Address = 0x" + Address.ToString("x16") + ", " + "Type = " + Type.ToString() + ", " + "Value = 0x" + Value.ToString("x8") + ", " + "Timeout = 0x" + Timeout.ToString("x16")); if (IsPointingInsideKernel(Address)) { Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); return; } if (IsAddressNotWordAligned(Address)) { Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); return; } long Result; switch (Type) { case ArbitrationType.WaitIfLessThan: Result = System.AddressArbiter.WaitForAddressIfLessThan(Memory, Address, Value, false, Timeout); break; case ArbitrationType.DecrementAndWaitIfLessThan: Result = System.AddressArbiter.WaitForAddressIfLessThan(Memory, Address, Value, true, Timeout); break; case ArbitrationType.WaitIfEqual: Result = System.AddressArbiter.WaitForAddressIfEqual(Memory, Address, Value, Timeout); break; default: Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); break; } if (Result != 0) { Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); } ThreadState.X0 = (ulong)Result; }
private void SvcWaitForAddress(AThreadState ThreadState) { long Address = (long)ThreadState.X0; ArbitrationType Type = (ArbitrationType)ThreadState.X1; int Value = (int)ThreadState.X2; ulong Timeout = ThreadState.X3; Ns.Log.PrintDebug(LogClass.KernelSvc, "Address = " + Address.ToString("x16") + ", " + "ArbitrationType = " + Type.ToString() + ", " + "Value = " + Value.ToString("x8") + ", " + "Timeout = " + Timeout.ToString("x16")); if (IsPointingInsideKernel(Address)) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); return; } if (IsWordAddressUnaligned(Address)) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); return; } switch (Type) { case ArbitrationType.WaitIfLessThan: ThreadState.X0 = AddressArbiter.WaitForAddressIfLessThan(Process, ThreadState, Memory, Address, Value, Timeout, false); break; case ArbitrationType.DecrementAndWaitIfLessThan: ThreadState.X0 = AddressArbiter.WaitForAddressIfLessThan(Process, ThreadState, Memory, Address, Value, Timeout, true); break; case ArbitrationType.WaitIfEqual: ThreadState.X0 = AddressArbiter.WaitForAddressIfEqual(Process, ThreadState, Memory, Address, Value, Timeout); break; default: ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); break; } }
private KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout) { if (IsPointingInsideKernel(address)) { return(KernelResult.InvalidMemState); } if (IsAddressNotWordAligned(address)) { return(KernelResult.InvalidAddress); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KernelResult result; switch (type) { case ArbitrationType.WaitIfLessThan: result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout); break; case ArbitrationType.DecrementAndWaitIfLessThan: result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout); break; case ArbitrationType.WaitIfEqual: result = currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout); break; default: result = KernelResult.InvalidEnumValue; break; } return(result); }
public KernelResult WaitForAddress64([R(0)] ulong address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] long timeout) { return(_syscall.WaitForAddress(address, type, value, timeout)); }
public KernelResult WaitForAddress64(ulong address, ArbitrationType type, int value, long timeout) { return(WaitForAddress(address, type, value, timeout)); }
public KernelResult WaitForAddress32([R(0)] uint address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] uint timeoutLow, [R(4)] uint timeoutHigh) { long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32)); return(_syscall.WaitForAddress(address, type, value, timeout)); }
/// <summary>Does the uptake.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="Option">The option.</param> public virtual void DoUptake(IArbitration[] Organs, BiomassArbitrationType BAT, ArbitrationType Option) { double BiomassTakenUp = 0; if (BAT.TotalUptakeSupply > 0.00000000001) { // Calculate how much uptake N each demanding organ is allocated based on relative demands if (Option == ArbitrationType.RelativeAllocation) RelativeAllocation(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT); if (Option == ArbitrationType.PriorityAllocation) PriorityAllocation(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT); if (Option == ArbitrationType.PriorityThenRelativeAllocation) PrioritythenRelativeAllocation(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT); if (Option == ArbitrationType.RelativeAllocationSinglePass) RelativeAllocationSinglePass(Organs, BAT.TotalUptakeSupply, ref BiomassTakenUp, BAT); // Then calculate how much N is taken up by each supplying organ based on relative uptake supply for (int i = 0; i < Organs.Length; i++) { if (BAT.UptakeSupply[i] > 0.00000000001) { double RelativeSupply = BAT.UptakeSupply[i] / BAT.TotalUptakeSupply; BAT.Uptake[i] += BiomassTakenUp * RelativeSupply; } } } }
/// <summary>Does the retranslocation.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="Option">The option.</param> public virtual void DoRetranslocation(IArbitration[] Organs, BiomassArbitrationType BAT, ArbitrationType Option) { double BiomassRetranslocated = 0; if (BAT.TotalRetranslocationSupply > 0.00000000001) { // Calculate how much retranslocation N (and associated biomass) each demanding organ is allocated based on relative demands if (Option == ArbitrationType.RelativeAllocation) RelativeAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); if (Option == ArbitrationType.PriorityAllocation) PriorityAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); if (Option == ArbitrationType.PriorityThenRelativeAllocation) PrioritythenRelativeAllocation(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); if (Option == ArbitrationType.RelativeAllocationSinglePass) RelativeAllocationSinglePass(Organs, BAT.TotalRetranslocationSupply, ref BiomassRetranslocated, BAT); // Then calculate how much N (and associated biomass) is retranslocated from each supplying organ based on relative retranslocation supply for (int i = 0; i < Organs.Length; i++) { if (BAT.RetranslocationSupply[i] > 0.00000000001) { double RelativeSupply = BAT.RetranslocationSupply[i] / BAT.TotalRetranslocationSupply; BAT.Retranslocation[i] += BiomassRetranslocated * RelativeSupply; } } } }
/// <summary>Does the fixation.</summary> /// <param name="Organs">The organs.</param> /// <param name="BAT">The bat.</param> /// <param name="Option">The option.</param> /// <exception cref="System.Exception">Crop is trying to Fix excessive amounts of BAT. Check partitioning coefficients are giving realistic nodule size and that FixationRatePotential is realistic</exception> public virtual void DoFixation(IArbitration[] Organs, BiomassArbitrationType BAT, ArbitrationType Option) { double BiomassFixed = 0; if (BAT.TotalFixationSupply > 0.00000000001) { // Calculate how much fixed resource each demanding organ is allocated based on relative demands if (Option == ArbitrationType.RelativeAllocation) RelativeAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT); if (Option == ArbitrationType.PriorityAllocation) PriorityAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT); if (Option == ArbitrationType.PriorityThenRelativeAllocation) PrioritythenRelativeAllocation(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT); if (Option == ArbitrationType.RelativeAllocationSinglePass) RelativeAllocationSinglePass(Organs, BAT.TotalFixationSupply, ref BiomassFixed, BAT); //Set the sink limitation variable. BAT.NotAllocated changes after each allocation step so it must be caught here and assigned as sink limitation BAT.SinkLimitation = BAT.NotAllocated; // Then calculate how much resource is fixed from each supplying organ based on relative fixation supply if (BiomassFixed > 0) { for (int i = 0; i < Organs.Length; i++) { if (BAT.FixationSupply[i] > 0.00000000001) { double RelativeSupply = BAT.FixationSupply[i] / BAT.TotalFixationSupply; BAT.Fixation[i] = BiomassFixed * RelativeSupply; double Respiration = BiomassFixed * RelativeSupply * Organs[i].NFixationCost; //Calculalte how much respirtion is associated with fixation DM.Respiration[i] = Respiration; // allocate it to the organ } DM.TotalRespiration = MathUtilities.Sum(DM.Respiration); } } // Work out the amount of biomass (if any) lost due to the cost of N fixation if (DM.TotalRespiration <= DM.SinkLimitation) { } //Cost of N fixation can be met by DM supply that was not allocated else {//claw back todays NonStructuralDM allocation to cover the cost double UnallocatedRespirationCost = DM.TotalRespiration - DM.SinkLimitation; if (DM.TotalNonStructuralAllocation > 0) { for (int i = 0; i < Organs.Length; i++) { double proportion = DM.NonStructuralAllocation[i] / DM.TotalNonStructuralAllocation; double Clawback = Math.Min(UnallocatedRespirationCost * proportion, DM.NonStructuralAllocation[i]); DM.NonStructuralAllocation[i] -= Clawback; UnallocatedRespirationCost -= Clawback; } } if (UnallocatedRespirationCost == 0) { }//All cost accounted for else {//Remobilise more Non-structural DM to cover the cost if (DM.TotalRetranslocationSupply > 0) { for (int i = 0; i < Organs.Length; i++) { double proportion = DM.RetranslocationSupply[i] / DM.TotalRetranslocationSupply; double DMRetranslocated = Math.Min(UnallocatedRespirationCost * proportion, DM.RetranslocationSupply[i]); DM.Retranslocation[i] += DMRetranslocated; UnallocatedRespirationCost -= DMRetranslocated; } } if (UnallocatedRespirationCost == 0) { }//All cost accounted for else {//Start cutting into Structural and Metabolic Allocations if ((DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation) > 0) { double Costmet = 0; for (int i = 0; i < Organs.Length; i++) { if ((DM.StructuralAllocation[i] + DM.MetabolicAllocation[i]) > 0) { double proportion = (DM.StructuralAllocation[i] + DM.MetabolicAllocation[i]) / (DM.TotalStructuralAllocation + DM.TotalMetabolicAllocation); double StructualFraction = DM.StructuralAllocation[i] / (DM.StructuralAllocation[i] + DM.MetabolicAllocation[i]); double StructuralClawback = Math.Min(UnallocatedRespirationCost * proportion * StructualFraction, DM.StructuralAllocation[i]); double MetabolicClawback = Math.Min(UnallocatedRespirationCost * proportion * (1 - StructualFraction), DM.MetabolicAllocation[i]); DM.StructuralAllocation[i] -= StructuralClawback; DM.MetabolicAllocation[i] -= MetabolicClawback; Costmet += (StructuralClawback + MetabolicClawback); } } UnallocatedRespirationCost -= Costmet; } } if (UnallocatedRespirationCost > 0.0000000001) throw new Exception("Crop is trying to Fix excessive amounts of " + BAT.BiomassType +" Check partitioning coefficients are giving realistic nodule size and that FixationRatePotential is realistic"); } } } }
private void SvcWaitForAddress(CpuThreadState threadState) { long address = (long)threadState.X0; ArbitrationType type = (ArbitrationType)threadState.X1; int value = (int)threadState.X2; long timeout = (long)threadState.X3; Logger.PrintDebug(LogClass.KernelSvc, "Address = 0x" + address.ToString("x16") + ", " + "Type = " + type.ToString() + ", " + "Value = 0x" + value.ToString("x8") + ", " + "Timeout = 0x" + timeout.ToString("x16")); if (IsPointingInsideKernel(address)) { Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{address:x16}!"); threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm); return; } if (IsAddressNotWordAligned(address)) { Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{address:x16}!"); threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress); return; } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); long result; switch (type) { case ArbitrationType.WaitIfLessThan: result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, false, timeout); break; case ArbitrationType.DecrementAndWaitIfLessThan: result = currentProcess.AddressArbiter.WaitForAddressIfLessThan(address, value, true, timeout); break; case ArbitrationType.WaitIfEqual: result = currentProcess.AddressArbiter.WaitForAddressIfEqual(address, value, timeout); break; default: result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue); break; } if (result != 0) { Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); } threadState.X0 = (ulong)result; }