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

📄 ipc.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
 /*------------------------------------------------------------------------- * * ipc.c *	  POSTGRES inter-process communication definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.37 1999/05/25 16:11:07 momjian Exp $ * * NOTES * *	  Currently, semaphores are used (my understanding anyway) in two *	  different ways: *		1. as mutexes on machines that don't have test-and-set (eg. *		   mips R3000). *		2. for putting processes to sleep when waiting on a lock *		   and waking them up when the lock is free. *	  The number of semaphores in (1) is fixed and those are shared *	  among all backends. In (2), there is 1 semaphore per process and those *	  are not shared with anyone else. *														  -ay 4/95 * *------------------------------------------------------------------------- */#include <sys/types.h>#include <sys/file.h>#include <stdio.h>#include <string.h>#include <errno.h>#include "postgres.h"#include "storage/ipc.h"#include "storage/s_lock.h"/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */#include <sys/sem.h>#include <sys/shm.h>#include "utils/memutils.h"#include "libpq/libpq.h"#include "utils/trace.h"#if defined(solaris_sparc)#include <string.h>#include <sys/ipc.h>#endifstatic int	UsePrivateMemory = 0;static void IpcMemoryDetach(int status, char *shmaddr);/* ---------------------------------------------------------------- *						exit() handling stuff * ---------------------------------------------------------------- */#define MAX_ON_EXITS 20static struct ONEXIT{	void		(*function) ();	caddr_t		arg;}			on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];static int	on_proc_exit_index,			on_shmem_exit_index;typedef struct _PrivateMemStruct{	int			id;	char	   *memptr;} PrivateMem;PrivateMem	IpcPrivateMem[16];static intPrivateMemoryCreate(IpcMemoryKey memKey,					uint32 size){	static int	memid = 0;	UsePrivateMemory = 1;	IpcPrivateMem[memid].id = memid;	IpcPrivateMem[memid].memptr = malloc(size);	if (IpcPrivateMem[memid].memptr == NULL)		elog(ERROR, "PrivateMemoryCreate: not enough memory to malloc");	MemSet(IpcPrivateMem[memid].memptr, 0, size);		/* XXX PURIFY */	return memid++;}static char *PrivateMemoryAttach(IpcMemoryId memid){	return IpcPrivateMem[memid].memptr;}/* ---------------------------------------------------------------- *		proc_exit * *		this function calls all the callbacks registered *		for it (to free resources) and then calls exit. *		This should be the only function to call exit(). *		-cim 2/6/90 * ---------------------------------------------------------------- */static int	proc_exit_inprogress = 0;voidproc_exit(int code){	int			i;	TPRINTF(TRACE_VERBOSE, "proc_exit(%d) [#%d]", code, proc_exit_inprogress);	/*	 * If proc_exit is called too many times something bad is happenig, so	 * exit immediately.	 */	if (proc_exit_inprogress > 9)	{		elog(ERROR, "infinite recursion in proc_exit");		goto exit;	}	/* ----------------	 *	if proc_exit_inprocess is true, then it means that we	 *	are being invoked from within an on_exit() handler	 *	and so we return immediately to avoid recursion.	 * ----------------	 */	if (proc_exit_inprogress++)		return;	/* do our shared memory exits first */	shmem_exit(code);	/* ----------------	 *	call all the callbacks registered before calling exit().	 * ----------------	 */	for (i = on_proc_exit_index - 1; i >= 0; --i)		(*on_proc_exit_list[i].function) (code, on_proc_exit_list[i].arg);exit:	TPRINTF(TRACE_VERBOSE, "exit(%d)", code);	exit(code);}/* ------------------ * Run all of the on_shmem_exit routines but don't exit in the end. * This is used by the postmaster to re-initialize shared memory and * semaphores after a backend dies horribly * ------------------ */static int	shmem_exit_inprogress = 0;voidshmem_exit(int code){	int			i;	TPRINTF(TRACE_VERBOSE, "shmem_exit(%d) [#%d]",			code, shmem_exit_inprogress);	/*	 * If shmem_exit is called too many times something bad is happenig,	 * so exit immediately.	 */	if (shmem_exit_inprogress > 9)	{		elog(ERROR, "infinite recursion in shmem_exit");		exit(-1);	}	/* ----------------	 *	if shmem_exit_inprocess is true, then it means that we	 *	are being invoked from within an on_exit() handler	 *	and so we return immediately to avoid recursion.	 * ----------------	 */	if (shmem_exit_inprogress++)		return;	/* ----------------	 *	call all the callbacks registered before calling exit().	 * ----------------	 */	for (i = on_shmem_exit_index - 1; i >= 0; --i)		(*on_shmem_exit_list[i].function) (code, on_shmem_exit_list[i].arg);	on_shmem_exit_index = 0;	shmem_exit_inprogress = 0;}/* ---------------------------------------------------------------- *		on_proc_exit * *		this function adds a callback function to the list of *		functions invoked by proc_exit().	-cim 2/6/90 * ---------------------------------------------------------------- */int			on_proc_exit(void (*function) (), caddr_t arg){	if (on_proc_exit_index >= MAX_ON_EXITS)		return -1;	on_proc_exit_list[on_proc_exit_index].function = function;	on_proc_exit_list[on_proc_exit_index].arg = arg;	++on_proc_exit_index;	return 0;}/* ---------------------------------------------------------------- *		on_shmem_exit * *		this function adds a callback function to the list of *		functions invoked by shmem_exit().	-cim 2/6/90 * ---------------------------------------------------------------- */int			on_shmem_exit(void (*function) (), caddr_t arg){	if (on_shmem_exit_index >= MAX_ON_EXITS)		return -1;	on_shmem_exit_list[on_shmem_exit_index].function = function;	on_shmem_exit_list[on_shmem_exit_index].arg = arg;	++on_shmem_exit_index;	return 0;}/* ---------------------------------------------------------------- *		on_exit_reset * *		this function clears all proc_exit() registered functions. * ---------------------------------------------------------------- */voidon_exit_reset(void){	on_shmem_exit_index = 0;	on_proc_exit_index = 0;}/****************************************************************************//*	 IPCPrivateSemaphoreKill(status, semId)									*//*																			*//****************************************************************************/static voidIPCPrivateSemaphoreKill(int status,						int semId)		/* caddr_t */{	union semun semun;	semctl(semId, 0, IPC_RMID, semun);}/****************************************************************************//*	 IPCPrivateMemoryKill(status, shmId)									*//*																			*//****************************************************************************/static voidIPCPrivateMemoryKill(int status,					 int shmId) /* caddr_t */{	if (UsePrivateMemory)	{		/* free ( IpcPrivateMem[shmId].memptr ); */	}	else	{		if (shmctl(shmId, IPC_RMID, (struct shmid_ds *) NULL) < 0)		{			elog(NOTICE, "IPCPrivateMemoryKill: shmctl(%d, %d, 0) failed: %m",				 shmId, IPC_RMID);		}	}}/****************************************************************************//*	 IpcSemaphoreCreate(semKey, semNum, permission, semStartValue)			*//*																			*//*	  - returns a semaphore identifier:										*//*																			*//* if key doesn't exist: return a new id,      status:= IpcSemIdNotExist    *//* if key exists:		 return the old id,    status:= IpcSemIdExist		*//* if semNum > MAX :	 return # of argument, status:=IpcInvalidArgument	*//*																			*//****************************************************************************//* * Note: * XXX	This should be split into two different calls.	One should * XXX	be used to create a semaphore set.	The other to "attach" a * XXX	existing set.  It should be an error for the semaphore set * XXX	to to already exist or for it not to, respectively. * *		Currently, the semaphore sets are "attached" and an error *		is detected only when a later shared memory attach fails. */IpcSemaphoreIdIpcSemaphoreCreate(IpcSemaphoreKey semKey,				   int semNum,				   int permission,				   int semStartValue,				   int removeOnExit,				   int *status){	int			i;	int			errStatus;	int			semId;	u_short		array[IPC_NMAXSEM];	union semun semun;	/* get a semaphore if non-existent */	/* check arguments	*/	if (semNum > IPC_NMAXSEM || semNum <= 0)	{		*status = IpcInvalidArgument;		return 2;				/* returns the number of the invalid								 * argument   */	}	semId = semget(semKey, 0, 0);	if (semId == -1)	{		*status = IpcSemIdNotExist;		/* there doesn't exist a semaphore */#ifdef DEBUG_IPC		EPRINTF("calling semget with %d, %d , %d\n",				semKey,				semNum,				IPC_CREAT | permission);#endif		semId = semget(semKey, semNum, IPC_CREAT | permission);		if (semId < 0)		{			EPRINTF("IpcSemaphoreCreate: semget failed (%s) "					"key=%d, num=%d, permission=%o",					strerror(errno), semKey, semNum, permission);			proc_exit(3);		}		for (i = 0; i < semNum; i++)			array[i] = semStartValue;		semun.array = array;		errStatus = semctl(semId, 0, SETALL, semun);		if (errStatus == -1)		{			EPRINTF("IpcSemaphoreCreate: semctl failed (%s) id=%d",					strerror(errno), semId);		}		if (removeOnExit)			on_shmem_exit(IPCPrivateSemaphoreKill, (caddr_t) semId);	}	else	{		/* there is a semaphore id for this key */		*status = IpcSemIdExist;	}#ifdef DEBUG_IPC

⌨️ 快捷键说明

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