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

📄 semaphor.c

📁 深圳市微逻辑电子有限公司 巨果&#8226 Kingmos&reg 系统核心
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************
Copyright(c) 版权所有,1998-2005微逻辑。保留所有权利。
******************************************************/

/*****************************************************
文件说明:信号量管理
版本号:2.0.0
开发时期:2000
作者:李林
修改记录:
	2004-12-09, 增加对线程退出的 CS 的复位处理 _Semaphore_HandleThreadExit
	2004-08-31, 去掉 SEMAPHORE的 objType用 hThis 代替
    2004-08-11, 不是用动态分配( WaitForSingleObject。WaitMultiSingleObject  ) 信号量,涉及到 semaphpor.c thread.c sche.c
	2004-05-18: 完成 PulseEvent
    2003-05-22: 增加对 CURRENT_PROCESS_HANDLE 和 CURRENT_THREAD_HANDLE 的处理
    2003-04-24:
	    1.增加信号量的 互斥 功能
		2.WaitForSingleObject增加对线程句柄的处理

******************************************************/

#include <eframe.h>
#include <eobjlist.h>
#include <epcore.h>
#include <epalloc.h>
#include <coresrv.h>

extern void UpCrit( LPSEMAPHORE lpsem, LPCRITICAL_SECTION lpcs );
extern BOOL DownCrit( LPSEMAPHORE lpsem, LPCRITICAL_SECTION lpcs, BOOL bEntryBlock );
extern VOID DumpCallStack( LPTHREAD );

static LPSEMAPHORE lpSemList = NULL;
static CRITICAL_SECTION csSemList;

// ********************************************************************
// 声明:BOOL _InitSemMgr( void )
// 参数:
//		无
// 返回值:
//		假如成功,返回TRUE;否则,返回FALSE
// 功能描述:
//		初始化信号量管理器
// 引用:
//	
// ********************************************************************
BOOL _InitSemMgr( void )
{
	

	KC_InitializeCriticalSection( &csSemList );
#ifdef __DEBUG
	csSemList.lpcsName = "CS-SEM"; // 用于调试
#endif
	return TRUE;
}

// ********************************************************************
// 声明:LPSEMAPHORE _SemaphoreCreate(
//							 LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  // must is 0
//							 int nInitialCount,                         // initial count
//							 int nMaximumCount,                     // maximum count
//							 LPCTSTR lpName,     // must is 0
//							 UINT uiFlag
//							 )
// 参数:
//	IN lpSemaphoreAttributes - 安全属性(不支持,必须为NULL)
//	IN nInitialCount - 初始化时拥有的信号量数
//	IN nMaximumCount - 最大的信号量
//	IN lpName - 信号量名(可以为NULL)
//	IN uiFlag - 标志,为:
//			SF_SEMAPHORE - 为信号量对象
//			SF_MUTEX - 互斥量对象
//			SF_EVENT - 事件对象
//			SF_OWNER - 设定拥有者线程(针对MUTEX对象)
//			SF_MANUALRESET - 手工重设(针对EVENT对象)
// 返回值:
//	假如成功,返回有效的SEMAPHORE结构指针;否则,返回NULL
// 功能描述:
//	创造信号量对象
// 引用:
//	
// ********************************************************************

LPSEMAPHORE _SemaphoreCreate(
							 LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  // must is 0
							 int nInitialCount,                         // initial count
							 int nMaximumCount,                     // maximum count
							 LPCTSTR lpName,     // must is 0
							 UINT uiFlag
							 )
{
    LPSEMAPHORE lpsem;
    int iStrLen;

    if( lpName && lpSemList )
    {    //命名对象,先查找当前是否存在该名
        for( lpsem = lpSemList; lpsem; lpsem = lpsem->lpNext )
        {
            if( lpsem->lpszName && stricmp( lpName, lpsem->lpszName ) == 0 )
            {   // 找到相同的 ,find same name
				KL_SetLastError( ERROR_ALREADY_EXISTS );
				if( (WORD)(uiFlag & 0xf) == (lpsem->semFlag & 0xf) )
				{   // 同样的对象
					lpsem->nRefCount++;	//增加引用
					goto _ret;
				}
				else
				{   // 同名但不同的对象,diff object but same name
					lpsem = NULL; // error
					goto _ret;
				}
            }
        }
    }
	// 没有找到
    iStrLen = 0;
    if( lpName )
    {
        iStrLen = strlen( lpName );
    }
	// 分配结构
    lpsem = (LPSEMAPHORE)KHeap_Alloc( sizeof(SEMAPHORE) );
	if( lpsem )
    {	// 初始化
		memset( lpsem, 0, sizeof( SEMAPHORE ) );
		if( lpName )
		{
		    lpsem->lpszName = KHeap_AllocString( iStrLen + 1 );
			if( lpsem->lpszName == NULL )
			{
				KHeap_Free( lpsem, sizeof(SEMAPHORE) );
				lpsem = NULL;
				goto _ret;
            }
			strcpy( lpsem->lpszName, lpName );
		}
		else
			lpsem->lpszName = NULL;
        //lpsem->objType = OBJ_SEMAPHORE; // 2004-08-31
        lpsem->nCount = nInitialCount;
        lpsem->nWaiting = 0;
        lpsem->nMaxCount = nMaximumCount;
        lpsem->lpWaitQueue = 0;
        lpsem->nRefCount = 1;
        lpsem->semFlag = uiFlag;
		lpsem->nHighPriority = IDLE_PRIORITY;
		
		if( (uiFlag & SF_OWNER) && nInitialCount )
		{
			lpsem->lpOwner = lpCurThread;
			lpsem->nLockCount = 1;
		}
		//	加入链表头
        lpsem->lpNext = lpSemList;
        lpSemList = lpsem;
    }
_ret:
    return lpsem;
}

// ********************************************************************
// 声明:BOOL _SemaphoreRemove( LPSEMAPHORE lpsem )
// 参数:
//		IN lpsem -  SEMAPHORE结构指针
// 返回值:
//		假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
//		该功能将信号量移出链表
// 引用:
//	
// ********************************************************************

static BOOL _SemaphoreRemove( LPSEMAPHORE lpsem )
{
	//KL_EnterCriticalSection( &csSemList );
	//if( --lpsem->nRefCount == 0 )	// 引用计数 = 0 ?
	{	// 是,没有任何引用 ,释放她 
		LPSEMAPHORE lp = lpSemList;

//		ASSERT( lpSemList );
		//	从链表移出
		if( lp == lpsem )
		{  // head 
			lpSemList = lp->lpNext;
		}
		else
		{	//
		    while( lp && lp->lpNext != lpsem )
			{
				lp = lp->lpNext;
			}
			if( lp && lp->lpNext == lpsem )
			{
				lp->lpNext = lpsem->lpNext;
			}
			else
			{
				ASSERT( lpSemList );
			}
		}
		//lpsem->objType = OBJ_NULL;
		// 释放
		//if( lpsem->lpszName )
		  //  KHeap_FreeString( lpsem->lpszName );
        //KHeap_Free( lpsem, sizeof(SEMAPHORE) );
	}
	//KL_LeaveCriticalSection( &csSemList );
	return TRUE;
}

// ********************************************************************
// 声明:BOOL _SemaphoreDelete( LPSEMAPHORE lpsem )
// 参数:
//		IN lpsem -  SEMAPHORE结构指针
// 返回值:
//		假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
//		与 _SemaphoreCreate 对应,该功能释放所分配的资源
// 引用:
//	
// ********************************************************************
#define DEBUG_SemaphoreDelete 0
static BOOL _SemaphoreDelete( LPSEMAPHORE lpsem )
{
	
	if( lpsem->nRefCount == 0 )
	{// 是,没有任何引用 ,先移出,再释放
		if( _SemaphoreRemove( lpsem ) )
		{	//释放
			if( lpsem->lpszName )
				KHeap_FreeString( lpsem->lpszName );
			KHeap_Free( lpsem, sizeof(SEMAPHORE) );
		}
	}
	else
	{
		//ASSERT( 0 );
		ERRORMSG( DEBUG_SemaphoreDelete, ( "_SemaphoreDelete: error lpsem->nRefCount=%d.\r\n", lpsem->nRefCount ) );
	}
	return TRUE;
}
// ********************************************************************
// 声明:BOOL _SemaphoreRelease( 
//                            LPSEMAPHORE lpsem, 
//							  int lReleaseCount, 
//							  LPINT lpPreviousCount )

// 参数:
//	IN lpsem - SEMAPHORE 结构指针
//	IN lReleaseCount - 释放的资源数
//	OUT lpPreviousCount - 用于接受之前的资源数 
// 返回值:
//	假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
//	释放信号量。假如当前有等待信号量的线程,也释放它们
// 引用:
//	
// ********************************************************************

BOOL _SemaphoreRelease( 
					   LPSEMAPHORE lpsem, 
					   int lReleaseCount, 
					   LPINT lpPreviousCount )
{
	// 保存当前的
	if( lpPreviousCount )
		*lpPreviousCount = lpsem->nCount;
	// 释放信号量 & 线程
	if( lReleaseCount )
	    UpSemaphore( lpsem, lReleaseCount );
	return TRUE;
}


// ********************************************************************
// 声明:VOID _Semaphore_HandleThreadExit( 
//                            LPVOID lpOwnerID  )
// 参数:
//	IN lpOwnerID - 拥有者ID
// 返回值:
//	无
// 功能描述:
//	当线程退出而没有释放sem时,这里做最后的复位
// 引用:
//	
// ********************************************************************

VOID _Semaphore_HandleThreadExit( LPVOID lpOwnerID )
{
	LPSEMAPHORE lpsem;

	KL_EnterCriticalSection( &csSemList );// 进入互斥段

	lpsem = lpSemList;
		
	while( lpsem )
	{
		if( lpsem != csSemList.hSemaphore &&
			lpsem->lpOwner == lpOwnerID )
		{
			UpSemaphore( lpsem, 1 );
			lpsem->lpOwner = NULL;
			lpsem = lpSemList;
			lpsem->nHighPriority = IDLE_PRIORITY;
			continue;
		}
		else
			lpsem = lpsem->lpNext;
	}


	KL_LeaveCriticalSection( &csSemList );// 进入互斥段
}

// ********************************************************************
// 声明:static BOOL _SemaphoreReset( LPSEMAPHORE lpsem )
// 参数:
//	IN lpsem - SEMAPHORE 结构指针
// 返回值:
//	假如成功,返回TRUE; 否则,返回FALSE
// 功能描述:
//	复位信号量到无信号状态
// 引用:
//	
// ********************************************************************

static BOOL _SemaphoreReset( LPSEMAPHORE lpsem )
{
	UINT uiSave;
	LockIRQSave( &uiSave );

	//INTR_OFF(); // 关闭中断
	lpsem->nCount = 0;
	//INTR_ON();  // 打开中断

	UnlockIRQRestore( &uiSave );

	return TRUE;
}


// ********************************************************************
// 声明:static HANDLE _CreateHandleObj(
//                   LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  // must is NULL
//                   int nInitialCount,                         // initial count
//                   int nMaximumCount,                     // maximum count
//                   LPCTSTR lpName,     // must is NULL
//                   UINT uiFlag,
//				     DWORD objType,
//				     LPPROCESS lpOwnerProcess
//                   )
// 参数:
//	IN lpSemaphoreAttributes - 安全属性(不支持,必须为NULL)
//	IN nInitialCount - 初始化信号量计数
//	IN nMaximumCount - 最大的信号量数
//	IN lpName - 已字符串表示的对象名
//	IN uiFlag - 标志,为:
//					SF_SEMAPHORE - 信号量对象
//					SF_MUTEX - 互斥量对象
//					SF_EVENT - 事件对象
//					SF_OWNER - 设定拥有者线程(针对MUTEX对象)
//					SF_MANUALRESET - 手工重设(针对EVENT对象)
//	IN objType - 对象类型,传递给Hanle_Alloc的参数,这里为:
//						OBJ_SEMAPHORE
//						OBJ_MUTEX - 互斥量对象
//						OBJ_EVENT - 事件对象
//	IN lpOwnerProcess - 该对象的拥有者
// 返回值:
//	假如成功,返回句柄;否则,返回NULL
// 功能描述:
//	创建一个基于句柄的对象
// 引用:
//	
// ********************************************************************

static HANDLE _CreateHandleObj(
                   LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  //
                   int nInitialCount,                         // initial count
                   int nMaximumCount,                     // maximum count
                   LPCTSTR lpName,     //
                   UINT uiFlag,
				   DWORD objType,
				   LPPROCESS lpProcess
                   )
{
	LPSEMAPHORE lpvData;
	HANDLE h = NULL;

	KL_EnterCriticalSection( &csSemList );// 进入互斥段
	// 创建内存对象
	lpvData = _SemaphoreCreate( lpSemaphoreAttributes, nInitialCount, nMaximumCount, lpName, uiFlag );

	if( lpvData ) // 成功吗 ?
	{	// 成功,为该对象分配一个句柄
		h = Handle_Alloc( lpProcess, lpvData, objType );
		if( h == NULL )  // 句柄分配成功吗?
		{	// 否,删除之前分配的内存对象
			lpvData->nRefCount = 0;
			_SemaphoreDelete( lpvData );
		}
		else
		{   //2005-01-31, delete
			;//lpvData->hThis = h;
		}
	}
	KL_LeaveCriticalSection( &csSemList );// 离开互斥段
	return h;


}

//释放信号量(原子操作)
BOOL _CloseSemaphoreObj( HANDLE hSemaphore, UINT uObjType )
{
	BOOL retv = FALSE;
	LPSEMAPHORE lpho;

	KL_EnterCriticalSection( &csSemList );
	
	if( uObjType )
		lpho = HandleToPtr( hSemaphore, uObjType );// 由句柄得到对象指针
	else
		lpho = (LPSEMAPHORE)hSemaphore;  //指针对象
	if( lpho )
	{
		if( lpho->nRefCount == 1 )
		{
			lpho->nRefCount = 0;
			if( _SemaphoreDelete( lpho ) )
			{
				retv = TRUE;
			}
		}
		else
		{
			ASSERT( lpho->nRefCount > 1 );
			lpho->nRefCount--;
		}
	}
	KL_LeaveCriticalSection( &csSemList );

	return retv;
}

// ********************************************************************
// 声明:HANDLE WINAPI KL_CreateSemaphore(
//                   LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  //
//                   int nInitialCount,                         // initial count
//                   int nMaximumCount,                     // maximum count
//                   LPCTSTR lpName     //
//                   )

// 参数:
//	IN lpSemaphoreAttributes-安全性描述,为NULL
//	IN nInitialCount-初始计数
//	IN nMaximumCount-最大计数

⌨️ 快捷键说明

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