⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 semalib.s

📁 VXWORKS源代码
💻 S
📖 第 1 页 / 共 2 页
字号:
/* semALib.s - i80x86 internal VxWorks binary semaphore assembly library *//* Copyright 1984-2002 Wind River Systems, Inc. *//*modification history--------------------01l,20mar02,hdn  preserved previous state of the int enable bit (spr 74016)01k,09nov01,pcm  added VxWorks semaphore events01j,23aug01,hdn  added FUNC/FUNC_LABEL, replaced .align with .balign01i,30apr98,cjtc bug fixes in semaphore instrumentation01h,28apr98,pr   fixed problem with registers in WV code.01g,16apr98,pr   cleanup.01f,17feb98,pr   added WindView 2.0 code.01f,24jun97,sub  fixed semTakeGlobal and semGiveGlobal for VxMP - SPR # 883301e,29jul96,sbs  Made windview conditionally compile.01d,08aug94,hdn  added support for WindView.01c,02jun93,hdn  split into sem[CM]ALib.s to increase modularity.		 added shared memory semaphores support.		 added signal restart.		 updated to 5.1		  - fixed #else and #endif		  - changed ASMLANGUAGE to _ASMLANGUAGE		  - changed copyright notice01b,13oct92,hdn  debugged.01a,07apr92,hdn  written based on TRON version.*//*DESCRIPTIONThis module contains internals to the VxWorks kernel.These routines have been coded in assembler because they are optimized forperformance.*/#define _ASMLANGUAGE#include "vxWorks.h"#include "vwModNum.h"#include "asm.h"#include "eventLib.h"#include "semLib.h"#include "private/semLibP.h"#include "private/classLibP.h"#include "private/taskLibP.h"#include "private/eventP.h"		.data	.globl	FUNC(copyright_wind_river)	.long	FUNC(copyright_wind_river)#ifndef PORTABLE	/* externals */	.globl	FUNC(semIntRestrict)	.globl	FUNC(semInvalid)	.globl	FUNC(semGiveDefer)	.globl	FUNC(windExit)	.globl	FUNC(windPendQPut)	.globl	FUNC(windPendQGet)	.globl	VAR(smObjPoolMinusOne)	/* internals */	.globl	GTEXT(semGive)		/* optimized semGive demultiplexer */	.globl	GTEXT(semTake)		/* optimized semTake demultiplexer */	.globl	GTEXT(semBGive)		/* optimized binary semaphore give */	.globl	GTEXT(semBTake)		/* optimized binary semaphore take */	.globl	GTEXT(semQGet)		/* semaphore queue get routine */	.globl	GTEXT(semQPut)		/* semaphore queue put routine */	.globl	GTEXT(semOTake)		/* optimized old semaphore take */	.globl	GTEXT(semClear)		/* optimized old semaphore semClear */	.globl	GTEXT(semEvRsrcSend)	.text	.balign 16/********************************************************************************* semGiveKern - add give routine to work queue**/semGiveKern:	jmp	FUNC(semGiveDefer)	/* let C rtn defer work and ret *//********************************************************************************* semGive - give a semaphore***STATUS semGive (semId)*    SEM_ID semId;		/* semaphore id to give **/	.balign 16, 0x90semGiveReturn:			/* This small block is before the semGive */	popfl			/* as the default branch for a conditional */ 	ret			/* jump is jump back. */	.balign 16,0x90FUNC_LABEL(semGive)	movl	SP_ARG1(%esp),%ecx	/* semId goes into %ecx */	testl	$1,%ecx			/* is it a global semId */	jne	semGiveGlobal		/* if LSB is 1, its a global sem */	xorl	%edx, %edx		/* Clear edx */#ifdef	WV_INSTRUMENTATION	/* 	 * windview instrumentation - BEGIN	 * semGive: object status class	 */	cmpl	FUNC(evtAction), %edx	/*  is WindView on? */	je	noSemGiveEvt        cmpl    $FUNC(semClass),(%ecx)	/* check validity */        je	objOkGive        cmpl	$FUNC(semInstClass),(%ecx) /* check validity */        jne     noSemGiveEvt		/* invalid semaphore */objOkGive:	movl	$ WV_CLASS_3_ON,%eax        andl    FUNC(wvEvtClass),%eax	/* is event collection on? */        cmpl    $ WV_CLASS_3_ON,%eax	/* is event collection on? */	jne	trgCheckSemGive	pushl	%eax	pushl	%ecx			/* semId */	pushl	%edx	/* is this semaphore object instrumented? */	movl	(%ecx),%eax		/* %ecx - semId */	cmpl	$0,SEM_INST_RTN(%eax)	/* event routine attached? */	je	trgNoSemGive	/* log event for this object */	pushl	%edx			/* $0 */	pushl	%edx			/* $0 */	movw	SEM_RECURSE(%ecx),%dx	/* recursively called */	pushl	%edx		movl	SEM_STATE(%ecx),%edx	/* state/count/owner */	pushl	%edx	pushl	%ecx			/* semId */	pushl	$ 3			/* number of paramters */	pushl	$ EVENT_SEMGIVE		/* EVENT_SEMGIVE, event id */	movl	SEM_INST_RTN(%eax),%edx	/* get logging routine */	call	*%edx			/* call routine */	addl	$28,%esptrgNoSemGive:	popl	%edx	popl	%ecx			/* semId */	popl	%eaxtrgCheckSemGive:	movl	$ TRG_CLASS_3,%eax     	orl 	$ TRG_ON,%eax        cmpl    FUNC(trgEvtClass),%eax	/* any trigger? */	jne	noSemGiveEvt        movl    FUNC(_func_trgCheck),%eax    /* triggering routine */        cmpl    %edx, %eax		/* Note: %edx = 0 */        je      noSemGiveEvt	pushl	%ecx			/* semId */	pushl	%edx        pushl   %edx			/* $0 */        pushl   %edx			/* $0 */	movw	SEM_RECURSE(%ecx),%dx	/* recursively called */	pushl	%edx		movl	SEM_STATE(%ecx),%edx	/* state/count/owner */	pushl	%edx	pushl	%ecx			/* semId */	pushl	%ecx			/* objId */        pushl   $ TRG_CLASS3_INDEX      /* TRG_CLASS3_INDEX */	pushl	$ EVENT_SEMGIVE		/* EVENT_SEMGIVE, event id */        call    *%eax                   /* call triggering routine */        addl    $32,%esp	popl	%edx	popl	%ecx			/* semId */noSemGiveEvt:	/* windview instrumentation - END */#endif  /* WV_INSTRUMENTATION */	movl	FUNC(kernelState),%eax	/* are we in kernel state? */	cmpl	%edx, %eax		/* %edx already 0 */	jne	semGiveKern		/* %eax = 0 if we are not */	movb	SEM_TYPE(%ecx),%dl	/* put the sem class into %edx */	andb	$ SEM_TYPE_MASK,%dl	/* mask %edx to MAX_SEM_TYPE value */	jne	semGiveNotBinary	/* optimize for BINARY if %edx == 0 */		/* 		 * BINARY SEMAPHORE OPTIMIZATION		 * assumptions are:		 *  - %ecx = semId (%ecx is a volatile register)		 */FUNC_LABEL(semBGive)		pushfl				/* save IF in EFLAGS */		cli				/* LOCK INTERRUPTS */		cmpl    $FUNC(semClass),(%ecx)	/* check validity */		/*		 * FIXME-PR: if this is going to be part of the kernel 		 *           permanently, it should be rearranged. It  		 *           does an extra instruction that is not needed.		 */#ifdef	WV_INSTRUMENTATION		je	objOkBGive		/* object is okay */		/* windview - check the validity of instrumented class */		cmpl    $FUNC(semInstClass),(%ecx) /* check validity */		jne	    semIsInvalidUnlock	/* semaphore id error */objOkBGive:#else		jne     semIsInvalidUnlock	/* invalid semaphore */#endif  /* WV_INSTRUMENTATION */		movl    SEM_Q_HEAD(%ecx),%eax		movl    SEM_STATE(%ecx), %edx	/* %edx = previous semOwner */		movl    %eax,SEM_STATE(%ecx)		testl   %eax, %eax		/* is new semOwner NULL? */		jne	    FUNC(semQGet)	/* if not empty, get from q */		cmpl    SEM_EVENTS_TASKID (%ecx), %eax		jz	    semGiveReturn	/* skip if taskId == NULL */		testl   %edx, %edx		/* is prev semOwner NULL? */		jnz     FUNC(semEvRsrcSend)	/* if not, jump */		popfl				/* UNLOCK INTERRUPTS */		ret				/* return OK */	.balign 16,0x90semGiveNotBinary:        /*	 * Call semGive indirectly via semGiveTbl.  Note that the index could	 * equal zero after it is masked.  semBGive is the zeroeth element	 * of the table, but for it to function correctly in the optimized	 * version above, we must be certain not to clobber %ecx.  Note, also	 * that old semaphores will also call semBGive above.	 */	movl	FUNC(semGiveTbl)(,%edx,4),%edx	jmp	*%edx			    /* invoke give rtn, it will ret */	.balign 16,0x90semGiveGlobal:	addl	FUNC(smObjPoolMinusOne),%ecx /* convert id to local addr */	movb	7(%ecx),%dl		    /* get semaphore type in %dl */				            /* offset 7 is used as the type					     * is stored in  network order					     */			andl	$ SEM_TYPE_MASK,%edx	    /* mask %edx to MAX_SEM_TYPE */	movl	FUNC(semGiveTbl)(,%edx,4),%edx /* %edx is the give rtn. */	pushl	%ecx			    /* push converted semId */	call	*%edx			    /* call appropriate give rtn. */	addl	$4,%esp			    /* clean up */	ret/********************************************************************************* semEvRsrcSend - send a semaphore event on semGive** This sub-routine is only executed if a semaphore state change has occurred,* and semId->events.taskId is not NULL.** INTERNAL* assumptions are:*  - %ecx = semId (%ecx is a volatile register)*  - %eax = 0*/	.balign	16, 0x90FUNC_LABEL(semEvRsrcSend)	movl	$1, FUNC(kernelState)	/* ENTER KERNEL */	popfl				/* UNLOCK INTERRUPTS */	movl	FUNC(errno), %eax	pushl	%esi			/* Save %esi */	pushl	%edi			/* Save %edi */	pushl	%ebx			/* Save %ebx */	pushl	%eax			/* Save errno */	movl	%ecx, %esi		/* %esi = semId */	/*	 * Both semId->events.options and semId->options are being pushed	 * onto the stack.  But where is semId->options?  SEM_TYPE is located	 * at offset 0x04, and SEM_OPTIONS is located at offset 0x05.  As the 	 * x86 series is little-endian, semId->options will be loaded into the	 * %bh portion of the %ebx register.  It should also be noted that both	 * semId->options and semId->events.options are a single byte.	 */	movl	SEM_EVENTS_OPTIONS (%ecx), %edi	/* Get semId->events.options */	movl	SEM_TYPE (%ecx), %ebx		/* Get semId->options */	movl	SEM_EVENTS_REGISTERED (%ecx), %edx	movl	SEM_EVENTS_TASKID (%ecx), %eax	pushl	%edx			/* semId->events.registered param */	pushl	%eax			/* semId->events.taskId param */	call	FUNC(eventRsrcSend)	/* eventRsrcSend (%eax, %edx) */	addl	$8, %esp		/* Remove params from stack */	/*	 * This next block does the C code	 * if ((evSendStatus != OK) && !(semOptions & EVENT_SEND_NOTIFY_ERROR))	 * Two tests can be condensed into one since ...	 * OK & x = 0, and ERROR & x = x	 * Thus (evSendStatus & semOptions & EVENT_SEND_NOTIFY_ERROR) works.	 * To avoid extra jumps (and flushing of the pipeline), the setXX	 * commands are used.	 */	movl	%eax, %edx		/* edx = %eax (backup) */	xorl	%ecx, %ecx		/* Clear <retStatus> */	andl	%ebx, %eax		/* %eax = {0, semOptions << 8} */	testl	$(SEM_EVENTSEND_ERR_NOTIFY << 8), %eax	setz	%cl			/* 1 if will return OK, 0 if ERROR */	/*	 * "if ((evtOptions & EVENTS_SEND_ONCE) || (evSendStatus != OK))"	 * combined into one test.  semId->events.taskId is cleared if the 	 * if-statement was TRUE.  No branching--cool.	 */	xorl	%eax, %eax		/* Clear %eax */	decl	%ecx			/* retStatus = {OK, ERROR} */	orl	%edi, %edx		/* Combine two tests into one */	incl	%eax			/* %eax  = $EVENTS_SEND_ONCE */	movl	$S_eventLib_EVENTSEND_FAILED, %edi	/* new errno */	andl	%edx, %eax		/* %eax = {1,0} */	popl	%ebx			/* old <errno> */	decl	%eax			/* %eax = {0x0, 0xffffffff} */	subl	%ebx, %edi		/* new <errno> - old <errno> */	andl	%eax, SEM_EVENTS_TASKID (%esi)	/* {0, unchanged} */	andl	%ecx, %edi		/* %edi = {0, new errno - old errno} */	movl	%ecx, %esi		/* Save <retStatus> */	addl	%ebx, %edi		/* %edi = {old errno, new errno} */	call	FUNC(windExit)		/* EXIT KERNEL */	movl	%edi, FUNC(errno)	/* Restore errno */	movl	%esi, %eax		/* Restore <retStatus> */	popl	%ebx			/* Restore %ebx */	popl	%edi			/* Restore %edi */	popl	%esi			/* Restore %esi */	ret/********************************************************************************* semIsInvalid - unlock interupts and call semInvalid ().*/	.balign 16,0x90semIsInvalidUnlock:	popfl				/* UNLOCK INTERRUPTS */semIsInvalid:	jmp	FUNC(semInvalid)	/* let C rtn do work and ret *//********************************************************************************* semTake - take a semaphore*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -