Example #1
0
    private static ImmixChunkHeader *AllocateChunk()
    {
        var chunkMemPtr = (nint)mi_malloc_aligned_at(
            (nuint)ImmixConstants.TotalChunkSize,
            ImmixConstants.BlockSize,
            (nuint)ImmixConstants.ChunkMetadataSize);

        // Assign the chunk header.
        var chunkPtr = (ImmixChunkHeader *)chunkMemPtr;

        chunkPtr->Initialize(totalChunks);

        // Initialize the blocks.
        var lineMapsStart = (byte *)chunkMemPtr + sizeof(ImmixChunkHeader);

        for (var i = 0; i < ImmixConstants.BlocksPerChunk; i++)
        {
            *ImmixChunkHeader.GetBlock(chunkPtr, i).Header = new ImmixBlockHeader(i, lineMapsStart + (ImmixConstants.LinesCount * i));
        }

        // Add the chunk to the lists and increment the total chunks counter.
        // TODO: Add these by address order.
        chunks.Add(chunkPtr);
        freeChunks.Add(totalChunks);
        Interlocked.Increment(ref totalChunks);

        return(chunkPtr);
    }
Example #2
0
    internal static ImmixBlockAddress GetBlock()
    {
        ImmixBlockAddress block = null;

        lock (chunks) {
            if (freeChunks.Count > 0)
            {
                var chunkIdx = freeChunks [0];
                var chunk    = chunks [chunkIdx].Address;

                Debug.Assert(chunk->FreeBlocks > 0);

                for (var blockIdx = 0; blockIdx < ImmixConstants.BlocksPerChunk; blockIdx++)
                {
                    if (chunk->BlockUsed [blockIdx] != 0)
                    {
                        continue;
                    }

                    block = ImmixChunkHeader.GetBlock(chunk, blockIdx);
                    chunk->BlockUsed [blockIdx] = 0xFF;

                    break;
                }

                Debug.Assert(block.Header != null, "Free chunks list contains a full chunk.");

                if (--chunk->FreeBlocks < 1)
                {
                    freeChunks.RemoveAt(0);
                }
            }
            else
            {
                var newChunk = AllocateChunk();
                newChunk->BlockUsed [0] = 0xFF;
                newChunk->FreeBlocks--;

                block = ImmixChunkHeader.GetBlock(newChunk, 0);
            }
        }

        if (block.Header->UsageLevel != ImmixBlockUsage.Empty)
        {
            block.Header->UsageLevel = ImmixBlockUsage.Empty;
            block.Header->LineMapSpan.Clear();
        }

        return(block);
    }