CAS与内存屏障: 内联汇编的实际应用场景_(S1封装系统调用)

c++的CAS与内存屏障: 内联汇编的实际应用场景(S1封装系统调用)

上一篇主要讨论了内联汇编语法层面的东西,现在接着深入研究下实际应用的场景.

封装系统调用

一些非posix标准的系统调用,可能需要通过glibc提供的syscall函数来调用.(unistd.h下的syscall(2))
在x86架构下,x86_64linux上较新glibc的syscall函数最终调用的指令为syscall汇编指令,而较旧的x86_64架构下的glibc或x86架构可能调用int 0x80 指令.
Linux Assembly X86

  • syscall指令 vs int 0x08
    看wiki上的解释
syscall
The x86_64 architecture introduced a dedicated instruction to make a syscall. It does not access the interrupt descriptor table and is faster.
  • 实验1,x86_64下的write系统调用封装.
    这里用c++模板封装了个简单的类型转换层.
    大概的层次关系如下:
层次 代码片段 备注
api层 write(int, const char*, int) 参数有类型,不同系统调用参数个数不同
胶水层 DoSysCall... 类型转换和参数个数匹配,如int类型参数需要转成64位寄存器的合法操作数
系统调用 asm(...) 参数无类型(只有长度),参数个数明确.(1-6)
  • 这个例子简单粗暴地进行了复制和十分冗长的类型转换.
    这个例子接受参数个数为3的系统调用(不算系统调用号)
1
2   /*
3    *
4    *
5    * from the glibc wiki page https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux
6   - int 0x80
7   On both Linux x86 and Linux x86_64 systems you can make a syscall by calling interrupt 0x80 using the int $0x80 command. Parameters are passed by setting the general purpose registers as following:
8
9   Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
10  eax ebx ecx edx esi edi ebp
11  Return value
12  eax
13  The syscall numbers are described in the Linux generated file $build/arch/x86/include/generated/uapi/asm/unistd_32.h or $build/usr/include/asm/unistd_32.h. The latter could also be present on your Linux system, just omit the $build.
14  All registers are preserved during the syscall.
15
16  - syscall
17  The x86_64 architecture introduced a dedicated instruction to make a syscall. It does not access the interrupt descriptor table and is faster. Parameters are passed by setting the general purpose registers as following:
18
19  Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
20  rax rdi rsi rdx r10 r8  r9
21  Return value
22  rax
23  The syscall numbers are described in the Linux generated file $build/usr/include/asm/unistd_64.h. This file could also be present on your Linux system, just omit the $build.
24  All registers, except rcx and r11 (and the return value, rax), are preserved during the syscall.
25   * */
26
27  /// for x86 & x86_64
28  #include <iostream>
29  #include <cstring>
30  #include <sys/syscall.h>
31  #include <cstdio>
32
33  template <int len>
34  struct byte {           /// this type is a pod type.
35      char ctn[len];
36  };
37
38
39  template <typename T>
40  struct byte_t {
41      byte<sizeof(T)> itn;
42  };
43
44  template<typename T>
45  uint64_t* FetchCtnPtr(T* x) {
46      return reinterpret_cast<uint64_t*>(x->itn.ctn);
47  }
48
49  template<typename T1, typename T2, typename T3>
50  int DoSysCall0(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3)
51  {
52      uint64_t ret;
53      byte_t<uint64_t> x1;
54      byte_t<uint64_t> x2;
55      byte_t<uint64_t> x3;
56      const char * ptr;
57      memcpy(static_cast<void*>(x1.itn.ctn), static_cast<void*>(&a1), sizeof(a1));
58      memcpy(static_cast<void*>(x2.itn.ctn), static_cast<void*>(&a2), sizeof(a2));
59      memcpy(static_cast<void*>(x3.itn.ctn), static_cast<void*>(&a3), sizeof(a3));
60      
61      printf("%d %s %d\n", *(reinterpret_cast<int*>(x1.itn.ctn)),
62              (ptr = reinterpret_cast<const char*>(*(FetchCtnPtr(&x2)))) == NULL ? "NULL" : ptr,
63              *(reinterpret_cast<int*>(x3.itn.ctn)));
64
65      asm(
66      "movq %1, %%rax\n\t" /// SysCall Number
67      "movq %2, %%rdi\n\t" /// Para 1
68      "movq %3, %%rsi\n\t" /// Para 2
69      "movq %4, %%rdx\n\t" /// Para 3
70      "syscall\n\t"     /// Call it
71      "movq %%rax, %0\n\t" /// Fetch Return Value
72      :"=r"(ret)
73      :"r"(SysCallNR),"r"(*(FetchCtnPtr(&x1))), "r"(*(FetchCtnPtr(&x2))), "r"(*(FetchCtnPtr(&x3)))
74      :"%rax","%rdi", "%rsi", "%rdx"
75      );
76      return (int)ret;
77  }
78
79
80  int Write(int fd, const char* str, int num) {
81      return DoSysCall0(SYS_write, fd, str, num);
82  }
83
84  int main() {
85      int ret;
86      const char * str1 = "Hello Syscall\n";
87      ret = Write(1, str1, strlen(str1));
88      std::cout << "Ret: " << ret << std::endl;
89      return 0;
90  }

运行结果如下:


result

从这个例子可看出,glibc在包裹函数做的的事情应该是包括:

  1. 入参/出参类型转换.(系统调用在上层的参数类型可能不同)
  2. 填充寄存器.(架构相关,填充哪些寄存器)
  3. 调用中断指令
  • 最后,总结一下这个部分
    glibc的syscall函数是根据不同架构、不同版本内核由脚本生成来的,扩展性比自己写syscall_wrapper好得多.
    建议还是使用syscall函数而非自己封装一个,毕竟这些脏活累活吃力不讨好.
    需要自己封装时,一定是非常少见的情况了(估计这辈子都碰不到),这有对添加system call的glibc现状做一些讨论.lwn
  • 这里对类型封装部分进行一些重构, 采用type_traits和enable_if等trick对类型转换部分优化了一下.
Here is an improve version of syscall wrapper
Compile: g++ tst-syscall.cc -o test -std=c++11 or g++ tst-syscall.cc -o test

1
2   /*
3    *
4    *
5    * from the glibc wiki page https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux
6   - int 0x80
7   On both Linux x86 and Linux x86_64 systems you can make a syscall by calling interrupt 0x80 using the int $0x80 command. Parameters are passed by setting the general purpose registers as following:
8
9   Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
10  eax ebx ecx edx esi edi ebp
11  Return value
12  eax
13  The syscall numbers are described in the Linux generated file $build/arch/x86/include/generated/uapi/asm/unistd_32.h or $build/usr/include/asm/unistd_32.h. The latter could also be present on your Linux system, just omit the $build.
14  All registers are preserved during the syscall.
15
16  - syscall
17  The x86_64 architecture introduced a dedicated instruction to make a syscall. It does not access the interrupt descriptor table and is faster. Parameters are passed by setting the general purpose registers as following:
18
19  Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
20  rax rdi rsi rdx r10 r8  r9
21  Return value
22  rax
23  The syscall numbers are described in the Linux generated file $build/usr/include/asm/unistd_64.h. This file could also be present on your Linux system, just omit the $build.
24  All registers, except rcx and r11 (and the return value, rax), are preserved during the syscall.
25   * */
26
27  /// for x86 & x86_64
28  #include <iostream>
29  #include <cstring>
30  #include <cstdio>
31  #include <sys/syscall.h>
32
33
34
35  struct b4 {
36      char buf[4];
37  };
38  struct b8 {
39      char buf[8];
40  };
41
42  #if __cplusplus >= 201103L
43
44  #include <type_traits>
45  typedef std::true_type true_type;
46  typedef std::false_type false_type;
47
48  #else
49  template <typename T, T Val>                      
50  struct integer_constant {                         
51      typedef T value_type;                         
52      enum { value = Val };                         
53  };                                                
54  typedef integer_constant<bool, true> true_type;   
55  typedef integer_constant<bool, false> false_type;
56  #endif
57
58  template <typename T>
59  struct is_b4 {
60      typedef false_type value_type;
61      const bool value = false;
62  };
63
64  template <>
65  struct is_b4<b4> {
66      typedef true_type value_type;
67      const bool value = true;
68  };
69
70  template <typename T>
71  struct is_b8 {
72      typedef false_type value_type;
73      static const bool value = false;
74  };
75
76  template <>
77  struct is_b8<b8> {
78      typedef true_type value_type;
79      static const bool value = true;
80  };
81
82  template <bool, typename T = void>
83  struct enable_if_my {
84  };
85  template <typename T>
86  struct enable_if_my<true, T> {
87      typedef T type;
88  };
89
90
91  template<typename T>
92  void makeb48(b4* b, T* x) {
93      memcpy(static_cast<void*>(b->buf), static_cast<void*>(x), sizeof(T));
94  }
95  template<typename T>
96  void makeb48(b8* b, T* x) {
97      memcpy(static_cast<void*>(b->buf), static_cast<void*>(x), sizeof(T));
98  }
99  template<typename T, typename enable_if_my<is_b4<T>::value, T>::type* = nullptr>
100 uint32_t* CtnPtr(T *b){
101     return reinterpret_cast<uint32_t*>(b->buf);
102 }
103 template<typename T, typename enable_if_my<is_b8<T>::value, T>::type* = nullptr>  /// should be ::type* , or compiler cannot infer the tempalte argument.
104 uint64_t* CtnPtr(T *b){
105     return reinterpret_cast<uint64_t*>(b->buf);
106 }
107
108 template<typename T1, typename T2, typename T3>
109 int DoSysCall0(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3)
110 {
111     uint64_t ret;
112     b8 x1;
113     b8 x2;
114     b8 x3;
115     const char * ptr;
116     makeb48(&x1, &a1);
117     makeb48(&x2, &a2);
118     makeb48(&x3, &a3);
119
120     printf("%d %s %d\n", *(reinterpret_cast<int*>(CtnPtr(&x1))),
121             (ptr = reinterpret_cast<const char*>(*(CtnPtr(&x2)))) == NULL ? "NULL" : ptr,
122             *(reinterpret_cast<int*>(CtnPtr(&x3))));
123
124     asm(
125     "movq %1, %%rax\n\t" /// SysCall Number
126     "movq %2, %%rdi\n\t" /// Para 1
127     "movq %3, %%rsi\n\t" /// Para 2
128     "movq %4, %%rdx\n\t" /// Para 3
129     "syscall\n\t"     /// Call it
130     "movq %%rax, %0\n\t" /// Fetch Return Value
131     :"=r"(ret)
132     :"r"(SysCallNR),"r"(*(CtnPtr(&x1))), "r"(*(CtnPtr(&x2))), "r"(*(CtnPtr(&x3)))
133     :"%rax","%rdi", "%rsi", "%rdx"
134     );
135     return (int)ret;
136 }
137
138
139 int Write(int fd, const char* str, int num) {
140     return DoSysCall0(SYS_write, fd, str, num);
141 }
142
143 int main() {
144     int ret;
145     const char * str1 = "Hello Syscall\n";
146     ret = Write(1, str1, strlen(str1));
147     std::cout << "Ret: " << ret << std::endl;
148     return 0;
149 }
improve version of syscall wrapper
  • 重构第二个版本,添加系统调用的通用化支持
 1
 2 /*
 3  *
 4  *
 5  * from the glibc wiki page https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux
 6 - int 0x80
 7 On both Linux x86 and Linux x86_64 systems you can make a syscall by calling interrupt 0x80 using the int $0x80 command. Parameters are passed by setting the general purpose registers as following:
 8
 9 Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
 10    eax ebx ecx edx esi edi ebp
 11    Return value
 12    eax
 13    The syscall numbers are described in the Linux generated file $build/arch/x86/include/generated/uapi/asm/unistd_32.h or $build/usr/include/asm/unistd_32.h. The latter could also be present on your Linux system, just omit the $build.
 14    All registers are preserved during the syscall.
 15
 16    - syscall
 17    The x86_64 architecture introduced a dedicated instruction to make a syscall. It does not access the interrupt descriptor table and is faster. Parameters are passed by setting the general purpose registers as following:
 18
 19    Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
 20    rax rdi rsi rdx r10 r8  r9
 21    Return value
 22    rax
 23    The syscall numbers are described in the Linux generated file $build/usr/include/asm/unistd_64.h. This file could also be present on your Linux system, just omit the $build.
 24    All registers, except rcx and r11 (and the return value, rax), are preserved during the syscall.
 25     * */
 26
 27    /// for x86 & x86_64
 28    #include <iostream>
 29    #include <cstring>
 30    #include <cstdio>
 31    #include <sys/syscall.h>
 32
 33
 34
 35    struct b4 {
 36        char buf[4];
 37    };
 38    struct b8 {
 39        char buf[8];
 40    };
 41
 42    #if __cplusplus >= 201103L
 43
 44    #include <type_traits>
 45    typedef std::true_type true_type;
 46    typedef std::false_type false_type;
 47
 48    #else
 49    template <typename T, T Val>                      
 50    struct integer_constant {                         
 51        typedef T value_type;                         
 52        enum { value = Val };                         
 53    };                                                
 54    typedef integer_constant<bool, true> true_type;   
 55    typedef integer_constant<bool, false> false_type;
 56    #endif
 57
 58    template <typename T>
 59    struct is_b4 {
 60        typedef false_type value_type;
 61        const bool value = false;
 62    };
 63
 64    template <>
 65    struct is_b4<b4> {
 66        typedef true_type value_type;
 67        const bool value = true;
 68    };
 69
 70    template <typename T>
 71    struct is_b8 {
 72        typedef false_type value_type;
 73        static const bool value = false;
 74    };
 75
 76    template <>
 77    struct is_b8<b8> {
 78        typedef true_type value_type;
 79        static const bool value = true;
 80    };
 81
 82    template <bool, typename T = void>
 83    struct enable_if_my {
 84    };
 85    template <typename T>
 86    struct enable_if_my<true, T> {
 87        typedef T type;
 88    };
 89
 90
 91    template<typename T>
 92    void makeb48(b4* b, T* x) {
 93        memcpy(static_cast<void*>(b->buf), static_cast<void*>(x), sizeof(T));
 94    }
 95    template<typename T>
 96    void makeb48(b8* b, T* x) {
 97        memcpy(static_cast<void*>(b->buf), static_cast<void*>(x), sizeof(T));
 98    }
 99    template<typename T, typename enable_if_my<is_b4<T>::value, T>::type* = nullptr>
 100   uint32_t* CtnPtr(T *b){
 101       return reinterpret_cast<uint32_t*>(b->buf);
 102   }
 103   template<typename T, typename enable_if_my<is_b8<T>::value, T>::type* = nullptr>  /// should be ::type* , or compiler cannot infer the tempalte argument.
 104   uint64_t* CtnPtr(T *b){
 105       return reinterpret_cast<uint64_t*>(b->buf);
 106   }
 107
 108
 109   #define SysCallCmd0 "movq %1, %%rax\n\t"
 110   #define SysCallCmd1 SysCallCmd0 "movq %2, %%rdi\n\t"
 111   #define SysCallCmd2 SysCallCmd1 "movq %3, %%rsi\n\t"
 112   #define SysCallCmd3 SysCallCmd2 "movq %4, %%rdx\n\t"
 113   #define SysCallCmd4 SysCallCmd3 "movq %5, %%r10\n\t"
 114   #define SysCallCmd5 SysCallCmd4 "movq %6, %%r8\n\t"
 115   #define SysCallCmd6 SysCallCmd5 "movq %7, %%r9\n\t"
 116
 117   #define SysCallRet "movq %%rax,%0\n\t"
 118
 119   #define OutputReg(x) "=r"(x)
 120   #define InputReg(x) "r"(x)
 121   #define SysCallInRegList0(nr,ofs) InputReg(nr)
 122   #define SysCallInRegList1(nr,a1) InputReg(nr),InputReg(a1)
 123   #define SysCallInRegList2(nr,a1,a2) SysCallInRegList1(nr,a1),InputReg(a2)
 124   #define SysCallInRegList3(nr,a1,a2,a3) SysCallInRegList2(nr,a1,a2),InputReg(a3)
 125   #define SysCallInRegList4(nr,a1,a2,a3,a4) SysCallInRegList3(nr,a1,a2,a3),InputReg(a4)
 126   #define SysCallInRegList5(nr,a1,a2,a3,a4,a5) SysCallInRegList4(nr,a1,a2,a3,a4),InputReg(a5)
 127   #define SysCallInRegList6(nr,a1,a2,a3,a4,a5,a6) SysCallInRegList5(nr,a1,a2,a3,a4,a5),InputReg(a6)
 128
 129   #define SysCallCrobList0 "%rax"
 130   #define SysCallCrobList1 SysCallCrobList0,"%rdi"
 131   #define SysCallCrobList2 SysCallCrobList1,"%rsi"
 132   #define SysCallCrobList3 SysCallCrobList2,"%rdx"
 133   #define SysCallCrobList4 SysCallCrobList3,"%r10"
 134   #define SysCallCrobList5 SysCallCrobList4,"%r8"
 135   #define SysCallCrobList6 SysCallCrobList5,"%r9"
 136
 137
 138   #define SysCallTemplateX8664(ret, NR, i, ...) do { asm( \
 139           SysCallCmd##i    \
 140           "syscall\n\t"   \
 141           SysCallRet      \
 142           :OutputReg(ret) \
 143           :SysCallInRegList##i(NR, __VA_ARGS__) \
 144           :SysCallCrobList##i \
 145           ); } while(0)
 146
 147   #define X86_64DefSysCall0(ret, NR)          SysCallTemplateX8664(ret, NR, 0)
 148   #define X86_64DefSysCall1(ret, NR, a1)      SysCallTemplateX8664(ret, NR, 1, a1)
 149   #define X86_64DefSysCall2(ret, NR, a1, a2)  SysCallTemplateX8664(ret, NR, 2, a1, a2)
 150
 151   #define X86_64DefSysCall3(ret, NR, a1, a2, a3) \
 152       SysCallTemplateX8664(ret, NR, 3, a1, a2, a3)
 153   #define X86_64DefSysCall4(ret, NR, a1, a2, a3, a4) \
 154       SysCallTemplateX8664(ret, NR, 4, a1, a2, a3, a4)
 155   #define X86_64DefSysCall5(ret, NR, a1, a2, a3, a4, a5) \
 156       SysCallTemplateX8664(ret, NR, 5, a1, a2, a3, a4, a5)
 157   #define X86_64DefSysCall6(ret, NR, a1, a2, a3, a4, a5, a6) \
 158       SysCallTemplateX8664(ret, NR, 6, a1, a2, a3, a4, a5, a6)
 159
 160
 161   int DoSysCall(uint64_t SysCallNR)
 162   {
 163       uint64_t ret;
 164       X86_64DefSysCall0(ret, SysCallNR);
 165       return (int)ret;
 166   }
 167
 168   template<typename T1>
 169   int DoSysCall(uint64_t SysCallNR, T1 a1)
 170   {
 171       uint64_t ret;
 172       b8 x1;
 173       makeb48(&x1, &a1);
 174       X86_64DefSysCall1(ret, SysCallNR, (*CtnPtr(&x1)));
 175       return (int)ret;
 176   }
 177
 178   template<typename T1, typename T2>
 179   int DoSysCall(uint64_t SysCallNR, T1 a1, T2 a2)
 180   {
 181       uint64_t ret;
 182       b8 x1, x2;
 183       makeb48(&x1, &a1);
 184       makeb48(&x2, &a2);
 185       X86_64DefSysCall2(ret, SysCallNR, (*CtnPtr(&x1)), (*CtnPtr(&x2)));
 186       return (int)ret;
 187   }
 188
 189   template<typename T1, typename T2, typename T3>
 190   int DoSysCall(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3)
 191   {
 192       uint64_t ret;
 193       b8 x1, x2, x3;
 194       makeb48(&x1, &a1);
 195       makeb48(&x2, &a2);
 196       makeb48(&x3, &a3);
 197       X86_64DefSysCall3(ret, SysCallNR, (*CtnPtr(&x1)), (*CtnPtr(&x2)), (*CtnPtr(&x3)));
 198       return (int)ret;
 199   }
 200
 201   template<typename T1, typename T2, typename T3, typename T4>
 202   int DoSysCall(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3, T4 a4)
 203   {
 204       uint64_t ret;
 205       b8 x1, x2, x3, x4;
 206       makeb48(&x1, &a1);
 207       makeb48(&x2, &a2);
 208       makeb48(&x3, &a3);
 209       makeb48(&x4, &a4);
 210       X86_64DefSysCall4(ret, SysCallNR, (*CtnPtr(&x1)), (*CtnPtr(&x2)), (*CtnPtr(&x3)), (*CtnPtr(&x4)));
 211       return (int)ret;
 212   }
 213
 214   template<typename T1, typename T2, typename T3, typename T4, typename T5>
 215   int DoSysCall(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
 216   {
 217       uint64_t ret;
 218       b8 x1, x2, x3, x4, x5;
 219       makeb48(&x1, &a1);
 220       makeb48(&x2, &a2);
 221       makeb48(&x3, &a3);
 222       makeb48(&x4, &a4);
 223       makeb48(&x5, &a5);
 224       X86_64DefSysCall5(ret, SysCallNR, (*CtnPtr(&x1)), (*CtnPtr(&x2)), (*CtnPtr(&x3)), (*CtnPtr(&x4)), (*CtnPtr(&x5)));
 225       return (int)ret;
 226   }
 227
 228   template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
 229   int DoSysCall(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
 230   {
 231       uint64_t ret;
 232       b8 x1, x2, x3, x4, x5, x6;
 233       makeb48(&x1, &a1);
 234       makeb48(&x2, &a2);
 235       makeb48(&x3, &a3);
 236       makeb48(&x4, &a4);
 237       makeb48(&x5, &a5);
 238       makeb48(&x6, &a6);
 239       X86_64DefSysCall6(ret, SysCallNR, (*CtnPtr(&x1)), (*CtnPtr(&x2)), (*CtnPtr(&x3)), (*CtnPtr(&x4)), (*CtnPtr(&x5)), (*CtnPtr(&x6)));
 240       return (int)ret;
 241   }
 242
 243   template<typename T1, typename T2, typename T3>
 244   int DoSysCall0(uint64_t SysCallNR, T1 a1, T2 a2, T3 a3)
 245   {
 246       uint64_t ret;
 247       b8 x1;
 248       b8 x2;
 249       b8 x3;
 250       const char * ptr;
 251       makeb48(&x1, &a1);
 252       makeb48(&x2, &a2);
 253       makeb48(&x3, &a3);
 254
 255       printf("%d %s %d\n", *(reinterpret_cast<int*>(CtnPtr(&x1))),
 256               (ptr = reinterpret_cast<const char*>(*(CtnPtr(&x2)))) == NULL ? "NULL" : ptr,
 257               *(reinterpret_cast<int*>(CtnPtr(&x3))));
 258
 259       asm(
 260       "movq %1, %%rax\n\t" /// SysCall Number
 261       "movq %2, %%rdi\n\t" /// Para 1
 262       "movq %3, %%rsi\n\t" /// Para 2
 263       "movq %4, %%rdx\n\t" /// Para 3
 264       "syscall\n\t"     /// Call it
 265       "movq %%rax, %0\n\t" /// Fetch Return Value
 266       :"=r"(ret)
 267       :"r"(SysCallNR),"r"(*(CtnPtr(&x1))), "r"(*(CtnPtr(&x2))), "r"(*(CtnPtr(&x3)))
 268       :"%rax","%rdi", "%rsi", "%rdx"
 269       );
 270       return (int)ret;
 271   }
 272
 273
 274   int Write(int fd, const char* str, int num) {
 275       return DoSysCall(SYS_write, fd, str, num);
 276   }
 277
 278   int Exit(int code) {
 279       return DoSysCall(SYS_exit, code);
 280   }
 281
 282   int Gettid() {
 283       return DoSysCall(SYS_gettid);
 284   }
 285
 286   int main() {
 287       int ret;
 288       const char * str1 = "Hello Syscall\n";
 289       ret = Write(1, str1, strlen(str1));
 290       std::cout << "Ret: " << ret << std::endl;
 291
 292       std::cout << "Tid: " << Gettid() << std::endl;
 293       return 0;
 294   }
添加tid

内存屏障和CAS放入下一篇.

内存屏障

tbd...

CAS

tbd...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 一次LINUX网络协议栈的探根之旅 公司的公共库中发现一段代码,简单化之,如下 我们知道sockaddr和sock...
    yiltoncent阅读 2,250评论 0 3
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,509评论 25 707
  • 日本是一个非常适合用走路来旅行的国家,首先是车辆驾驶大多很遵守交通规则,所以只要乖乖走在行人专用的道路上,安全性大...
    季子弘阅读 394评论 4 6
  • “写点评像是站在更高点上看文章,看逻辑,看表达。”(出自:97班战友美少女:张少侠) 看到这句话,有什么反应? 我...
    多收三五斗阅读 272评论 0 0
  • (未经本人允许,谢绝转载) 第三章 我的兄弟姐妹 5、我家小九妹(下) 打小,小九妹就爱美。十五六岁时,她经常掐一...
    子期听琴阅读 2,155评论 52 60