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)); } }