.Net Core在X86上实现Interlocked.Increment(ref long)的方式
因为在X86上long会被分割为两个int进行操作, 那么Interlocked.Increment的实现成为了一个问题。
在一番搜索后未发现有现成的文章解释这个问题,于是我就动手分析了。
这篇是笔记,不会做过多的解释。
首先重现环境是 .Net Core 2.0 Windows (x86) Binaries, 下载可以到 https://www.microsoft.com/net/download/core#/sdk
重现的代码如下
using System;
using System.Threading;
namespace x86program
{
class Program
{
static void Main(string[] args)
{
Console.ReadLine();
Console.WriteLine("Hello World!");
Console.ReadLine();
long a = 0x1234567887564321;
Console.WriteLine(Interlocked.Increment(ref a));
}
}
}
需要的工具:
Visual Studio 2017 15.3 RTM
OllyDbg 1.1 (or 2.0)
首先下载了x86版的dotnet后,解压然后在命令行运行
F:\dotnet-sdk-2.0.0-win-x86\x86program>..\dotnet.exe run
运行后使用Visual Studio打开项目然后"附加到进程", 成功后在下图中的地方下断点
然后命令行回车, 可以触发此断点, 我们可以看到 Interlocked.Increment 调用了 0x76A7CA0 处的函数, 传入参数只有一个, 就是指向long变量的指针
之后在Visual Studio中取消附加, 然后使用ollydbg的Attach, 成功后在 0x76A7CA0 下断点
这个函数调用了函数 0x7428BE0, 传入了分割为两个int的long (1), ecx仍然指向原来的long变量
函数 0x7428BE0 是一个JIT桩(Stub), 第一次调用会触发JIT编译, 第二次调用会跳到JIT编译结果
JIT编译后的实现就在 0x3410F40 处,这里的就是 Interlocked.Increment(ref long) 的实现
我们可以看到这个实现使用了x86的CMPXCHG8B指令,如果出现long变量的值被其他线程修改,会检测出来并重试添加
当然,不是所有x86的CPU都支持CMPXCHG8B指令, 但至少可以运行.Net Core的CPU都会支持此指令, 也就是说实现 atomic long 不需要semaphore
http://www.geoffchappell.com/studies/windows/km/cpu/cx8.htm
上面的代码是Debug下编译得到的, Release下同样需要调用一个helper函数, 内部的逻辑是一样的
x64位上的 Interlocked.Increment(ref long) 就很简单了, 可以使用现成的指令 lock xadd
分析到此为止
=================================================================================
微软最近发布了新的JIT文档,比原来的文档要容易理解很多,有兴趣的可以去围观:
https://github.com/dotnet/coreclr/blob/master/Documentation/botr/ryujit-tutorial.md
下一篇CoreCLR源码探索会讲解JIT是如何实现的,但是还需要最少一个月的时间,有兴趣的请耐心等待。
.Net Core在X86上实现Interlocked.Increment(ref long)的方式的更多相关文章
- 多线程相关Interlocked.Increment问题
今天群里有人问到如下代码打印出来的东西为什么不是连续得,所以有大神解释了原因.在这过程中遇到了些奇怪的情况 static void Main(string[] args) { for (int i = ...
- Interlocked.Increment 方法 和Interlocked.Decrement 方法作用
Interlocked.Increment 方法:让++成为原子操作:Interlocked.Decrement 方法让--成为原子操作.什么叫原子操作呢.就是不会被别人打断,因为C#中的一个语句,编 ...
- Interlocked.Increment()函数详解 (转载)
原文地址 class Program { static object lockObj = new object(); ; ; //假设要处理的数据源 , ).ToList(); static void ...
- 在ASP.NET Core Web API上使用Swagger提供API文档
我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...
- win2008server R2 x64 部署.net core到IIS上出现【Failed to load the dll from [C:\Program Files\dotnet\host\fxr\1.0.1\hostfxr.dll], HRESULT: 0x80070057】错误
win2008server R2 x64 部署.net core到IIS上出现[Failed to load the dll from [C:\Program Files\dotnet\host\fx ...
- Core Web API上使用Swagger提供API文档
在ASP.NET Core Web API上使用Swagger提供API文档 我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的AP ...
- .net core版 文件上传/ 支持批量上传,拖拽以及预览,bootstrap fileinput上传文件
asp.net mvc请移步 mvc文件上传支持批量上传,拖拽以及预览,文件内容校验 本篇内容主要解决.net core中文件上传的问题 开发环境:ubuntu+vscode 1.导入所需要的包:n ...
- .Net Core 图片文件上传下载
当下.Net Core项目可是如雨后春笋一般发展起来,作为.Net大军中的一员,我热忱地拥抱了.Net Core并且积极使用其进行业务的开发,我们先介绍下.Net Core项目下实现文件上传下载接口. ...
- ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)
早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...
随机推荐
- mysql数据库事务详细剖析
在写之前交代一下背景吧! 做开发也好久了,没怎么整理过知识,现在剖析一下自己对数据库事务的认识,以前用sqlserver,现在转java后又用mysql.oracle.我这块就主要解释一下mysql数 ...
- [转载] Redis资料汇总专题
转载自http://www.cnblogs.com/tommyli/archive/2011/12/14/2287614.html 1.Redis是什么? 十五分钟介绍 Redis数据结构 Redis ...
- Vocabulary & Phrase
Vocabulary A ANSI 美国国家标准学会,American National Standards Institute的缩写 a couple of [口语]少数的,几个 a s ...
- Scratch——教小孩子学编码
教小孩子学编码 http://scratch.mit.edu/ http://v.163.com/movie/2013/3/H/I/M92389L06_M9238GTHI.html
- window环境下npm install node-sass报错
最近准备想用vue-cli初始化一个项目,需要sass-loader编译: 发现window下npm install node-sass和sass-loader一直报错, window 命令行中提示我 ...
- lua元表
__index元方法:按照之前的说法,如果A的元表是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员.这个过程大体是这样,但却不完全是这样,实际上,即使将A的元表设置为B,而且B ...
- 【机器学习】彻底搞懂CNN
之前通过各种博客视频学习CNN,总是对参数啊原理啊什么的懵懵懂懂..这次上课终于弄明白了,O(∩_∩)O~ 上世纪科学家们发现了几个视觉神经特点,视神经具有局部感受眼,一整张图的识别由多个局部识别点构 ...
- 用lua+redis实现一个简单的计数器功能 (二)
环境已经搭建完毕 传送门 计数方案 就目前来看nginx是最快的服务 我在设计方案时选择信任redis作为存储库,不做穿透处理,由于目前redis集群方案还不成熟,只在这里做了主备方案.想做集群方案的 ...
- PHP随手记1--内置函数date
1. date_default_timezone_set date_default_timezone_set — 设定用于一个脚本中所有日期时间函数的默认时区 在php中只用 mktime() 函数时 ...
- mysql如何查看索引使用情况以及优化 - guols0612
mysql中支持hash和btree索引.innodb和myisam只支持btree索引,而memory和heap存储引擎可以支持hash和btree索引 我们可以通过下面语句查询当前索引使用情况: ...