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

📄 sem.c

📁 PostgreSQL7.4.6 for Linux
💻 C
字号:
/*------------------------------------------------------------------------- * * sem.c *	  BeOS System V Semaphores Emulation * * Copyright (c) 1999-2000, Cyril VELTER * *------------------------------------------------------------------------- */#include "postgres.h"#include <errno.h>#include <unistd.h>#include <OS.h>/*#define TDBG*/#ifdef TDBG#define TRACEDBG(x) printf(x);printf("\n")#define TRACEDBGP(x,y) printf(x,y);printf("\n")#define TRACEDBGPP(x,y,z) printf(x,y,z);printf("\n")#else#define TRACEDBG(x)#define TRACEDBGP(x,y)#define TRACEDBGPP(x,y,z)#endif/* Control of a semaphore pool. The pool is an area in which we stored allthe semIds of the pool. The first 4 bytes are the number of semaphore allocatedin the pool followed by SemIds */intsemctl(int semId, int semNum, int flag, union semun semun){	int32	   *Address;	area_info	info;	TRACEDBG("->semctl");	/* Try to find the pool */	if (get_area_info(semId, &info) != B_OK)	{		/* pool is invalid (BeOS area id is invalid) */		errno = EINVAL;		TRACEDBG("<-semctl invalid pool");		return -1;	}	/* Get the pool address */	Address = (int32 *) info.address;	TRACEDBGP("--semctl address %d", Address);	/* semNum might be 0 */	/* semun.array contain the sem initial values */	/* Fix the count of all sem of the pool to semun.array */	if (flag == SETALL)	{		long		i;		TRACEDBG("--semctl setall");		for (i = 0; i < Address[0]; i++)		{			int32		cnt;			/* Get the current count */			get_sem_count(Address[2 * i + 1], &cnt);			TRACEDBGP("--semctl setall %d", semun.array[i]);			/* Compute and set the new count (relative to the old one) */			cnt -= semun.array[i];			TRACEDBGPP("--semctl acquire id : %d cnt : %d", Address[2 * i + 1], cnt);			if (cnt > 0)				while (acquire_sem_etc(Address[2 * i + 1], cnt, 0, 0) == B_INTERRUPTED);			if (cnt < 0)				release_sem_etc(Address[2 * i + 1], -cnt, 0);		}		return 1;	}	/* Fix the count of one semaphore to semun.val */	if (flag == SETVAL)	{		int32		cnt;		TRACEDBGP("--semctl setval %d", semun.val);		/* Get the current count */		get_sem_count(Address[2 * semNum + 1], &cnt);		/* Compute and set the new count (relative to the old one) */		cnt -= semun.val;		TRACEDBGPP("--semctl acquire id : %d cnt : %d", Address[2 * semNum + 1], cnt);		if (cnt > 0)			while (acquire_sem_etc(Address[2 * semNum + 1], cnt, 0, 0) == B_INTERRUPTED);		if (cnt < 0)			release_sem_etc(Address[2 * semNum + 1], -cnt, 0);		return 1;	}	/* Get the last pid which accessed the sem */	if (flag == GETPID)	{		TRACEDBG("->semctl getpid");		return Address[2 * semNum + 2];	}	/* Delete the pool */	if (flag == IPC_RMID)	{		long		i;		thread_info ti;		TRACEDBG("->semctl rmid");		get_thread_info(find_thread(NULL), &ti);		/* Loop over all semaphore to delete them */		TRACEDBGP("->semctl nmbre %d", Address[0]);		for (i = 0; i < Address[0]; i++)		{			/*			 * Make sure to have ownership of the semaphore (if created by			 * another team)			 */			TRACEDBGP("->semctl id %d", Address[2 * i + 1]);			set_sem_owner(Address[2 * i + 1], ti.team);			/* Delete the semaphore */			delete_sem(Address[2 * i + 1]);			/*			 * Reset to an invalid semId (in case other process try to get			 * the infos from a cloned area			 */			Address[2 * i + 1] = 0;		}		/* Set the semaphore count to 0 */		Address[0] = 0;		/*		 * Delete the area (it might be cloned by other process. Let them		 * live with it, in all cases semIds are 0 so if another process		 * try to use it, it will fail		 */		delete_area(semId);		return 1;	}	/* Get the current semaphore count */	if (flag == GETNCNT)	{		/* TO BE IMPLEMENTED */		TRACEDBG("--semctl getncnt");		elog(ERROR, "semctl error: GETNCNT not implemented");		return 0;	}	/* Get the current semaphore count of the first semaphore in the pool */	if (flag == GETVAL)	{		int32		cnt;		TRACEDBG("--semctl getval");		get_sem_count(Address[2 * semNum + 1], &cnt);		TRACEDBGP("--semctl val %d", cnt);		return cnt;	}	elog(ERROR, "semctl error: unknown flag");	TRACEDBG("<-semctl unknown flag");	return 0;}/* Find a pool id based on IPC key */intsemget(int semKey, int semNum, int flags){	char		Nom[50];	area_id		parea;	void	   *Address;	TRACEDBGPP("->semget key : %d num : %d", semKey, semNum);	/* Name of the area to find */	sprintf(Nom, "SYSV_IPC_SEM : %d", semKey);	/* find area */	parea = find_area(Nom);	/* Test of area existence */	if (parea != B_NAME_NOT_FOUND)	{		/* Area exist and creation is requested, error */		if ((flags & IPC_CREAT) && (flags & IPC_EXCL))		{			errno = EEXIST;			return -1;		}		/* Get an area clone (in case it's not in our address space) */		/*		 * TODO : a check of address space might be done to avoid		 * duplicate areas in the same address space		 */		parea = clone_area(Nom, &Address, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, parea);		return parea;	}	else	{		/* Area does not  exist, but creation is requested, so create it */		if (flags & IPC_CREAT)		{			int32	   *Address;			void	   *Ad;			long		i;			/*			 * Limit to 250 (8 byte per sem : 4 for the semid and 4 for			 * the last pid which accessed the semaphore in a pool			 */			if (semNum > 250)			{				errno = ENOSPC;				return -1;			}			/* Create the shared memory area which will hold the pool */			parea = create_area(Nom, &Ad, B_ANY_ADDRESS, 4096, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);			if ((parea == B_BAD_VALUE) || (parea == B_NO_MEMORY) || (parea == B_ERROR))			{				errno = ENOMEM;				return -1;			}			/* fill up informations (sem number and sem ids) */			Address = (int32 *) Ad;			Address[0] = semNum;			for (i = 0; i < Address[0]; i++)			{				/* Create the semaphores */				Address[2 * i + 1] = create_sem(0, Nom);				if ((Address[2 * i + 1] == B_BAD_VALUE) || (Address[2 * i + 1] == B_NO_MEMORY) || (Address[2 * i + 1] == B_NO_MORE_SEMS))				{					errno = ENOMEM;					return -1;				}			}			return parea;		}		else		{			/* Area does not exist and no creation is requested */			errno = ENOENT;			return -1;		}	}}/* Acquire or release in the semaphore pool */intsemop(int semId, struct sembuf * sops, int nsops){	int32	   *Address;		/* Pool address */	area_info	info;	long		i;	long		ret;	/* Get the pool address (semId IS an area id) */	get_area_info(semId, &info);	Address = (int32 *) info.address;	/* Check the validity of semId (it should be an area id) */	if ((semId == B_BAD_VALUE) || (semId == B_NO_MEMORY) || (semId == B_ERROR))	{		errno = EINVAL;		return -1;	}	/* Perform acquire or release */	for (i = 0; i < nsops; i++)	{		/* remember the PID */		Address[2 * (sops[i].sem_num) + 2] = getpid();		/* For each sem in the pool, check the operation to perform */		if (sops[i].sem_op < 0)		{			/*			 * Try acquiring the semaphore till we are not interrupted by			 * a signal			 */			if (sops[i].sem_flg == IPC_NOWAIT)			{				/* Try to lock ... */				while ((ret = acquire_sem_etc(Address[2 * (sops[i].sem_num) + 1], -sops[i].sem_op, B_RELATIVE_TIMEOUT, 0)) == B_INTERRUPTED);				if (ret != B_OK)					return EWOULDBLOCK;			}			else				while (acquire_sem_etc(Address[2 * (sops[i].sem_num) + 1], -sops[i].sem_op, 0, 0) == B_INTERRUPTED);		}		if (sops[i].sem_op > 0)			release_sem_etc(Address[2 * (sops[i].sem_num) + 1], sops[i].sem_op, 0);	}	return 0;}

⌨️ 快捷键说明

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