singrdk/base/Applications/Tests/SharedHeapTest/SharedHeapTest.cs

350 lines
12 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note: User-mode test program for calling shared heap through the ABI.
//
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
using Microsoft.Singularity.V1.Services;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using Microsoft.Singularity.Channels;
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Configuration;
[assembly: Transform(typeof(ApplicationResourceTransform))]
2008-11-17 18:29:00 -05:00
namespace Microsoft.Singularity.Applications
{
2008-03-05 09:52:00 -05:00
[ConsoleCategory(DefaultAction=true)]
internal class Parameters {
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
reflective internal Parameters();
internal int AppMain() {
SharedHeapTest.AppMain(this);
return 0;
}
}
unsafe public class SharedHeapTest
{
//
// Note: The integrity check relies on there being one bit in each byte
// to represent the owning concurrent allocation slot, so the number of
// concurrent allocations can't exceed 8.
//
private const uint ConcurrentAllocations = 8;
private SharedHeapService.Allocation*[]! mem;
Random! random = new Random();
internal static void AppMain(Parameters! config)
{
SharedHeapTest test = new SharedHeapTest();
uint Iterations = 10;
Console.WriteLine("Starting Shared Heap Test\n");
test.StartUp();
for (uint loop = 0; loop < Iterations; loop++) {
test.Perturb();
if (test.Check() == false) {
break;
}
}
}
private SharedHeapTest() {
//
// Create an array to hold our concurrent allocations.
//
this.mem = new SharedHeapService.Allocation*[ConcurrentAllocations];
}
public static void Usage()
{
Console.WriteLine("Usage: sharedheap [Iterations]\n");
}
public void StartUp()
{
//
// Allocating a bunch of randomly sized things.
//
for (uint loop = 0; loop < ConcurrentAllocations; loop++) {
AllocRandomSizedThingy(loop);
if (CheckForValue(loop, 0) == true) {
Console.WriteLine("Passed zero-fill test.\n");
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
Console.WriteLine("Failed zero-fill test.\n");
}
FillWithValue(loop, (byte)(1 << (int)loop));
}
}
public bool Check()
{
//
// Check all allocations for expected bit settings.
//
Console.WriteLine("--------\n");
Console.WriteLine("Integrity Check\n");
for (uint loop = 0; loop < ConcurrentAllocations; loop++) {
if (CheckBits(loop, (byte)(1 << (int)loop)) == false) {
return false;
}
}
Console.WriteLine("--------\n");
return true;
}
public void Perturb()
{
//
// Pick an element slot to use and an action to take.
//
uint which = (uint)random.Next(ConcurrentAllocations);
uint action = (uint)random.Next(3);
//
// Free up the slot.
//
Console.WriteLine("--------\n");
Console.WriteLine(
"Freeing region: Data = {0}, Size = {1}.\n",
SharedHeapService.GetData(this.mem[which]),
SharedHeapService.GetSize(this.mem[which]));
ClearBits(which, (byte)(1 << (int)which));
SharedHeapService.Free(this.mem[which]);
Console.WriteLine("--------\n");
//
// Play around.
//
2008-11-17 18:29:00 -05:00
switch (action) {
2008-03-05 09:52:00 -05:00
case 0:
//
// Allocate something new.
//
Console.WriteLine("Allocation Test\n");
AllocRandomSizedThingy(which);
if (CheckForValue(which, 0) == true) {
Console.WriteLine("Passed zero-fill test.\n");
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
Console.WriteLine("Failed zero-fill test.\n");
}
//
// Store bit corresponding to slot number in each
// data byte. Used to check integrity later.
//
FillWithValue(which, (byte)(1 << (int)which));
break;
case 1:
//
// Split an element in two. Use the slot we freed
// up above to hold the split-off piece.
//
Console.WriteLine("Split Test\n");
//
// Pick a region to split.
//
uint split;
do {
split = (uint)random.Next(ConcurrentAllocations);
} while (split == which);
Console.Write(
"Splitting region: Data = {0}, Size = {1}",
SharedHeapService.GetData(this.mem[split]),
SharedHeapService.GetSize(this.mem[split]));
UIntPtr offset = (UIntPtr)random.Next(
1,
(int)SharedHeapService.GetSize(this.mem[split]));
Console.WriteLine(" in two at offset {0}.\n", offset);
this.mem[which] = SharedHeapService.Split(
this.mem[split],
offset);
Console.WriteLine(
"Revised region: Data = {0}, Size = {1}.\n",
SharedHeapService.GetData(this.mem[split]),
SharedHeapService.GetSize(this.mem[split]));
Console.WriteLine(
"New region: Data = {0}, Size = {1}.\n",
SharedHeapService.GetData(this.mem[which]),
SharedHeapService.GetSize(this.mem[which]));
//
// Remove bit corresponding to the slot of the original
// region from the split-off data. Likewise, add the
// bit corresponding to the slot number of the split-off
// region to the split-off data.
//
ClearBits(which, (byte)(1 << (int)split));
SetBits(which, (byte)(1 << (int)which));
break;
case 2:
//
// Share part of a region. Use the slot we freed
// up above to hold the shared piece.
//
Console.WriteLine("Share Test\n");
//
// Pick a region to share.
//
uint share;
do {
share = (uint)random.Next(ConcurrentAllocations);
} while (share == which);
Console.Write(
"Sharing region: Data = {0}, Size = {1}",
SharedHeapService.GetData(this.mem[share]),
SharedHeapService.GetSize(this.mem[share]));
UIntPtr start = (UIntPtr)random.Next(
1,
(int)SharedHeapService.GetSize(this.mem[share]));
Console.WriteLine(" starting at offset {0}.\n", start);
this.mem[which] = SharedHeapService.Share(
this.mem[share],
start, SharedHeapService.GetSize(this.mem[share]));
Console.WriteLine(
"Original region: Data = {0}, Size = {1}.\n",
SharedHeapService.GetData(this.mem[share]),
SharedHeapService.GetSize(this.mem[share]));
Console.WriteLine(
"New region: Data = {0}, Size = {1}.\n",
SharedHeapService.GetData(this.mem[which]),
SharedHeapService.GetSize(this.mem[which]));
//
// Modify each data byte in the shared region to include
// the bit corresponding to the slot number of the new
// shared allocation handle.
//
SetBits(which, (byte)(1 << (int)which));
break;
}
}
private void AllocRandomSizedThingy(uint index)
{
// REVIEW: We can't ask the system for the PageSize?
// Hardcoded to 2 * Pages.PageSize.
UIntPtr size = (UIntPtr)random.Next(1, 8192);
this.mem[index] = SharedHeapService.Allocate(size, typeof(byte).GetSystemType(), 0);
Console.WriteLine("Allocated region: Data = {0}, Size = {1}.\n",
SharedHeapService.GetData(this.mem[index]),
SharedHeapService.GetSize(this.mem[index]));
}
private void FillWithValue(uint index, byte value)
{
UIntPtr data = SharedHeapService.GetData(this.mem[index]);
UIntPtr size = SharedHeapService.GetSize(this.mem[index]);
for (UIntPtr address = data; address < data + size; address++) {
*(byte *)address = value;
}
return;
}
private bool CheckForValue(uint index, byte value)
{
UIntPtr data = SharedHeapService.GetData(this.mem[index]);
UIntPtr size = SharedHeapService.GetSize(this.mem[index]);
bool status = true;
for (UIntPtr address = data; address < data + size; address++) {
if (*(byte *)address != value) {
status = false;
Console.Write("Wrong value {0} at address {1}.\n",
*(byte *)address, address);
Console.Write("Should be {0}.\n", value);
}
}
return status;
}
private void SetBits(uint index, byte bit)
{
UIntPtr data = SharedHeapService.GetData(this.mem[index]);
UIntPtr size = SharedHeapService.GetSize(this.mem[index]);
for (UIntPtr address = data; address < data + size; address++) {
*(byte *)address |= bit;
}
return;
}
private void ClearBits(uint index, byte bit)
{
UIntPtr data = SharedHeapService.GetData(this.mem[index]);
UIntPtr size = SharedHeapService.GetSize(this.mem[index]);
for (UIntPtr address = data; address < data + size; address++) {
*(byte *)address &= (byte)~bit;
}
return;
}
private bool CheckBits(uint index, byte bit)
{
UIntPtr data = SharedHeapService.GetData(this.mem[index]);
UIntPtr size = SharedHeapService.GetSize(this.mem[index]);
bool status = true;
for (UIntPtr address = data; address < data + size; address++) {
if ((*(byte *)address & bit) != bit) {
status = false;
Console.WriteLine("Bad value {0} at address {1}.\n",
*(byte *)address, address);
//
// Stop at one to prevent huge output.
//
break;
}
}
return status;
}
}
}