📄 semaphor.c
字号:
/******************************************************
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 + -