예제 #1
0
        public unsafe static IntPtr AllocateThunk(IntPtr commonStubAddress)
        {
            lock (s_Lock)
            {
                LowLevelList <ThunksTemplateMap> mappings;
                if (!s_ThunkMaps.TryGetValue(commonStubAddress, out mappings))
                {
                    s_ThunkMaps[commonStubAddress] = mappings = new LowLevelList <ThunksTemplateMap>();
                }

                IntPtr thunkStub = GetThunkFromAllocatedPool(mappings, commonStubAddress);

                if (thunkStub == IntPtr.Zero)
                {
                    // No available thunks, so we need a new mapping of the thunks template page

                    IntPtr thunkBase = AsmCode.GetThunksBase();
                    Debug.Assert(thunkBase != IntPtr.Zero);

                    IntPtr moduleHandle = RuntimeAugments.GetModuleFromTypeHandle(typeof(ThunkPool).TypeHandle);
                    Debug.Assert(moduleHandle != IntPtr.Zero);

                    int templateRva = (int)((long)thunkBase - (long)moduleHandle);
                    Debug.Assert(templateRva % ALLOCATION_GRANULARITY == 0);

                    IntPtr thunkMap = IntPtr.Zero;
                    if (s_ThunksTemplate == IntPtr.Zero)
                    {
                        // First, we use the thunks directly from the thunks template sections in the module until all
                        // thunks in that template are used up.
                        thunkMap         = moduleHandle + templateRva;
                        s_ThunksTemplate = thunkMap;
                    }
                    else
                    {
                        // We've already used the thunks tempate in the module for some previous thunks, and we
                        // cannot reuse it here. Now we need to create a new mapping of the thunks section in order to have
                        // more thunks
                        thunkMap = RuntimeImports.RhAllocateThunksFromTemplate(moduleHandle, templateRva, NUM_THUNK_BLOCKS * PAGE_SIZE * 2);

                        if (thunkMap == IntPtr.Zero)
                        {
                            // We either ran out of memory and can't do anymore mappings of the thunks templates sections,
                            // or we are using the managed runtime services fallback, which doesn't provide the
                            // file mapping feature (ex: older version of mrt100.dll, or no mrt100.dll at all).

                            // The only option is for the caller to attempt and recycle unused thunks to be able to
                            // find some free entries.
                            return(IntPtr.Zero);
                        }
                    }
                    Debug.Assert(thunkMap != IntPtr.Zero && (long)thunkMap % ALLOCATION_GRANULARITY == 0);

                    // Each mapping consists of multiple blocks of thunk stubs/data pairs. Keep track of those
                    // so that we do not create a new mapping until all blocks in the sections we just mapped are consumed
                    for (int i = 0; i < NUM_THUNK_BLOCKS; i++)
                    {
                        s_RecentlyMappedThunksBlock[i] = thunkMap + (PAGE_SIZE * i * 2);
                    }
                    s_RecentlyMappedThunksBlockIndex = 1;

                    thunkStub = AllocateThunksTemplateMapFromMapping(thunkMap, commonStubAddress, mappings);
                }

                return(SetThumbBit(thunkStub));
            }
        }