关于 ucontext 的源码阅读

之前有写过一个协程库,用的是libco的context_swap.s作为协程切换,为了了解与ucontext的区别,去读了源码进行了解。

#include 

#include "ucontext_i.h"

/* 这个函数的功能是获得当前协程(或者此时还不能称为协程)的上下文将他存入参数中 */
ENTRY(__getcontext)
	/* 4(%esp)就是函数所提供参数的地址,将他赋值给eax */
	movl	4(%esp), %eax

	/* 将eax的值作为0传入 */
	movl	$0, oEAX(%eax)

	/* 下面是一系列将寄存器内容保存的操作,这些寄存器参数与libco相同  */
	movl	%ecx, oECX(%eax)
	movl	%edx, oEDX(%eax)
	movl	%edi, oEDI(%eax)
	movl	%esi, oESI(%eax)
	movl	%ebp, oEBP(%eax)
	movl	(%esp), %ecx
	/* eip存入的是esp的内容,因为esp未动过所以一直指向的是返回地址 */
	movl	%ecx, oEIP(%eax)
	leal	4(%esp), %ecx		/* Exclude the return address.  */
	/* esp并非真正的栈顶位置,取出时需要进行修改,这个在libco中也是同样的实现 */
	movl	%ecx, oESP(%eax)
	movl	%ebx, oEBX(%eax)

	/* FS寄存器指向当前活动线程的TEB结构(线程结构)libco中并未保存此寄存器  */
	xorl	%edx, %edx
	movw	%fs, %dx
	movl	%edx, oFS(%eax)

	/* 这是设置浮点计数器,libco中舍弃了浮点计数器,因为浮点数在服务器中使用不多 */
	leal	oFPREGSMEM(%eax), %ecx
	movl	%ecx, oFPREGS(%eax)
	/* Save the floating-point context.  */
	fnstenv	(%ecx)
	/* And load it right back since the processor changes the mask.
	   Intel thought this opcode to be used in interrupt handlers which
	   would block all exceptions.  */
	fldenv	(%ecx)

	/* 这是保存当前线程信号屏蔽掩码,这里会有系统调用在性能上有所损耗,这也是libco优化的一个点  */
	pushl	%ebx
	cfi_adjust_cfa_offset (4)
	cfi_rel_offset (ebx, 0)
	leal	oSIGMASK(%eax), %edx
	xorl	%ecx, %ecx
	movl	$SIG_BLOCK, %ebx
	movl	$__NR_sigprocmask, %eax
	ENTER_KERNEL
	popl	%ebx
	cfi_adjust_cfa_offset (-4)
	cfi_restore (ebx)
	cmpl	$-4095, %eax		/* Check %eax for error.  */
	jae	SYSCALL_ERROR_LABEL	/* Jump to error handler if error.  */

	/* All done, return 0 for success.  */
	xorl	%eax, %eax
	ret
PSEUDO_END(__getcontext)

weak_alias (__getcontext, getcontext)

你可能感兴趣的:(C++)