head	1.37;
access;
symbols
	Version_2_1:1.26
	old_buffer_manager:1.21
	C_Demo_1:1.6;
locks; strict;
comment	@ * @;


1.37
date	91.10.16.16.56.46;	author hong;	state Exp;
branches;
next	1.36;

1.36
date	91.09.05.23.28.23;	author hong;	state Exp;
branches;
next	1.35;

1.35
date	91.08.29.23.54.07;	author mer;	state Exp;
branches;
next	1.34;

1.34
date	91.08.14.12.32.37;	author mer;	state Exp;
branches;
next	1.33;

1.33
date	91.07.24.10.06.28;	author hong;	state Exp;
branches;
next	1.32;

1.32
date	91.07.24.07.46.49;	author mao;	state Exp;
branches;
next	1.31;

1.31
date	91.07.17.23.45.36;	author hong;	state Exp;
branches;
next	1.30;

1.30
date	91.06.12.10.18.47;	author kemnitz;	state Exp;
branches;
next	1.29;

1.29
date	91.06.10.20.57.40;	author kemnitz;	state Exp;
branches;
next	1.28;

1.28
date	91.04.23.17.08.04;	author kemnitz;	state Exp;
branches;
next	1.27;

1.27
date	91.04.01.08.46.47;	author hong;	state Exp;
branches;
next	1.26;

1.26
date	91.03.07.22.04.48;	author hong;	state Exp;
branches;
next	1.25;

1.25
date	91.03.03.17.27.40;	author hong;	state Exp;
branches;
next	1.24;

1.24
date	91.02.28.21.46.04;	author hong;	state Exp;
branches;
next	1.23;

1.23
date	91.02.18.20.39.25;	author hong;	state Exp;
branches;
next	1.22;

1.22
date	91.01.18.22.15.21;	author hong;	state Exp;
branches;
next	1.21;

1.21
date	90.11.28.20.57.13;	author hong;	state Exp;
branches;
next	1.20;

1.20
date	90.11.12.08.15.19;	author hong;	state Exp;
branches;
next	1.19;

1.19
date	90.11.07.12.06.07;	author hong;	state Exp;
branches;
next	1.18;

1.18
date	90.10.23.17.19.06;	author kemnitz;	state Exp;
branches;
next	1.17;

1.17
date	90.10.17.17.09.19;	author hong;	state Exp;
branches;
next	1.16;

1.16
date	90.10.16.23.33.06;	author hong;	state Exp;
branches;
next	1.15;

1.15
date	90.10.02.12.11.10;	author goh;	state Exp;
branches;
next	1.14;

1.14
date	90.10.02.12.06.07;	author goh;	state Exp;
branches;
next	1.13;

1.13
date	90.09.30.15.53.11;	author goh;	state Exp;
branches;
next	1.12;

1.12
date	90.09.25.16.44.28;	author kemnitz;	state Exp;
branches;
next	1.11;

1.11
date	90.04.19.16.34.41;	author kemnitz;	state Exp;
branches;
next	1.10;

1.10
date	90.03.31.19.00.31;	author cimarron;	state Exp;
branches;
next	1.9;

1.9
date	90.03.12.16.26.40;	author cimarron;	state Exp;
branches;
next	1.8;

1.8
date	90.02.13.00.27.54;	author kemnitz;	state Exp;
branches;
next	1.7;

1.7
date	90.02.12.19.48.10;	author cimarron;	state Exp;
branches;
next	1.6;

1.6
date	89.09.05.17.23.33;	author mao;	state C_Demo_1;
branches;
next	1.5;

1.5
date	89.08.03.00.06.06;	author dillon;	state Exp;
branches;
next	1.4;

1.4
date	89.04.19.15.12.31;	author dillon;	state Exp;
branches;
next	1.3;

1.3
date	89.04.14.18.31.00;	author dillon;	state Exp;
branches;
next	1.2;

1.2
date	89.02.02.16.15.58;	author dillon;	state Stab;
branches;
next	1.1;

1.1
date	89.01.17.05.57.19;	author cimarron;	state Exp;
branches;
next	;


desc
@@


1.37
log
@give more accurate termination condition to slave backends
@
text
@/* ----------------------------------------------------------------
 * ipc.c --
 *      POSTGRES inter-process communication definitions.
 *
 * Identification:
 *      $Header: RCS/ipc.c,v 1.36 91/09/05 23:28:23 hong Exp $
 * ----------------------------------------------------------------
 */


#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <errno.h>

/* XXX - the following  dependency should be moved into the defaults.mk file */
#ifndef	_IPC_
#define _IPC_
#ifndef sequent 

#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#else

#include "/usr/att/usr/include/sys/ipc.h"
#include "/usr/att/usr/include/sys/sem.h"
#include "/usr/att/usr/include/sys/shm.h"

#endif /* defined(sequent) */
#endif

#include "storage/ipci.h"		/* for PrivateIPCKey XXX */
#include "storage/ipc.h"
#include "tmp/align.h"
#include "utils/log.h"
#include "tcop/slaves.h"

int UsePrivateMemory = 0;

#ifdef PARALLELDEBUG
#include "executor/paralleldebug.h"
#endif

/* ----------------------------------------------------------------
 *			exit() handling stuff
 * ----------------------------------------------------------------
 */

#define MAX_ON_EXITS 20

static struct ONEXIT {
    void (*function)();
    caddr_t arg;
} onexit_list[ MAX_ON_EXITS ];

static int onexit_index;

typedef struct _PrivateMemStruct {
    int id;
    char *memptr;
} PrivateMem;

PrivateMem IpcPrivateMem[16];

int
PrivateMemoryCreate ( memKey , size , permission )
     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(WARN, "PrivateMemoryCreate: not enough memory to malloc");
    
    return (memid++);
}

char *
PrivateMemoryAttach ( memid , ignored1 , ignored2 )
     IpcMemoryId memid;
     int ignored1;
     int ignored2;
{
    return ( IpcPrivateMem[memid].memptr );
}


/* ----------------------------------------------------------------
 *	exitpg
 *
 *	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
 * ----------------------------------------------------------------
 */
int exitpg_inprogress = 0;

void
exitpg(code)
    int code;
{
    int i;

    /* ----------------
     *	if exitpg_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 (exitpg_inprogress)
	return;

    exitpg_inprogress = 1;

    /* ----------------
     *	call all the callbacks registered before calling exit().
     * ----------------
     */
    for (i = onexit_index - 1; i >= 0; --i)
	(*onexit_list[i].function)(code, onexit_list[i].arg);

    exit(code);
}

/* ------------------
 * Run all of the on_exitpg 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
 * ------------------
 */
void
quasi_exitpg()
{
    int i;

    /* ----------------
     *	if exitpg_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 (exitpg_inprogress)
	return;

    exitpg_inprogress = 1;

    /* ----------------
     *	call all the callbacks registered before calling exit().
     * ----------------
     */
    for (i = onexit_index - 1; i >= 0; --i)
	(*onexit_list[i].function)(0, onexit_list[i].arg);

    onexit_index = 0;
    exitpg_inprogress = 0;
}

/* ----------------------------------------------------------------
 *	on_exitpg
 *
 *	this function adds a callback function to the list of
 *	functions invoked by exitpg().	-cim 2/6/90
 * ----------------------------------------------------------------
 */

on_exitpg(function, arg)
    void (*function)();
    caddr_t arg;
{
    if (onexit_index >= MAX_ON_EXITS)
	return(-1);
    
    onexit_list[ onexit_index ].function = function;
    onexit_list[ onexit_index ].arg = arg;

    ++onexit_index;
    
    return(0);
}

/****************************************************************************/
/*   IPCPrivateSemaphoreKill(status, semId)				    */
/*									    */
/****************************************************************************/
void
IPCPrivateSemaphoreKill(status, semId)
    int	status;
    int	semId;		/* caddr_t */
{
    union semun	semun;
    semctl(semId, 0, IPC_RMID, semun);
}


/****************************************************************************/
/*   IPCPrivateMemoryKill(status, shmId)				    */
/*									    */
/****************************************************************************/
void
IPCPrivateMemoryKill(status, shmId)
    int	status;
    int	shmId;		/* caddr_t */
{
    if ( UsePrivateMemory ) {
	/* free ( IpcPrivateMem[shmId].memptr ); */
    } else {
	shmctl(shmId, IPC_RMID, (struct shmid_ds *)NULL);
    } 
}


/****************************************************************************/
/*   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.
 */
    
IpcSemaphoreId
IpcSemaphoreCreate(semKey, semNum, permission, semStartValue, status)
    IpcSemaphoreKey semKey;   		/* input patameter  */
    int		    semNum;		/* input patameter  */
    int		    permission;		/* input patameter  */
    int		    semStartValue;	/* input patameter  */
    int		    *status;		/* output parameter */
{
    int		i;
    int		errStatus;
    int		semId;
    ushort	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
	fprintf(stderr,"calling semget with %d, %d , %d\n",
		semKey,
		semNum,
		IPC_CREAT|permission );
#endif
	semId = semget(semKey, semNum, IPC_CREAT|permission);

	if (semId < 0) {
	    perror("semget");
	    exitpg(3);
	}
	for (i = 0; i < semNum; i++) {
	    array[i] = semStartValue;
	}
	semun.array = array;
	errStatus = semctl(semId, 0, SETALL, semun);
	if (errStatus == -1) {
	    perror("semctl");
	}
	
	/* if (semKey == PrivateIPCKey) */
	on_exitpg(IPCPrivateSemaphoreKill, (caddr_t)semId);
	
    } else {
	/* there is a semaphore id for this key */
	*status = IpcSemIdExist;
    }

#ifdef DEBUG_IPC
    fprintf(stderr,"\nIpcSemaphoreCreate, status %d, returns %d\n",
	    *status,
	    semId );
    fflush(stdout);
    fflush(stderr);
#endif
    return(semId);
}

/* ----------------
 *	IpcSemaphoreCreateWithoutOnExit
 *
 *	this is a copy of IpcSemaphoreCreate, but it doesn't register
 *	an on_exitpg procedure.  This is necessary for the executor
 *	semaphores because we need a special on-exit procedure to
 *	do the right thing depending on if the postgres process is
 *	a master or a slave process.  In a master process, we should
 *	kill the semaphores when we exit but in a slave process we
 *	should release them.
 * ----------------
 */
IpcSemaphoreId
IpcSemaphoreCreateWithoutOnExit(semKey,
				semNum,
				permission,
				semStartValue,
				status)
    IpcSemaphoreKey semKey;   		/* input patameter  */
    int		    semNum;		/* input patameter  */
    int		    permission;		/* input patameter  */
    int		    semStartValue;	/* input patameter  */
    int		    *status;		/* output parameter */
{
    int		i;
    int		errStatus;
    int		semId;
    ushort	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 */
	semId = semget(semKey, semNum, IPC_CREAT|permission);
	if (semId < 0) {
	    perror("semget");
	    exitpg(3);
	}
	for (i = 0; i < semNum; i++) {
	    array[i] = semStartValue;
	}
	semun.array = array;
	errStatus = semctl(semId, 0, SETALL, semun);
	if (errStatus == -1) {
	    perror("semctl");
	}
    } else {
	/* there is a semaphore id for this key */
	*status = IpcSemIdExist;
    }
    
    return(semId);
}


/****************************************************************************/
/*   IpcSemaphoreSet()		- sets the initial value of the semaphore   */
/*									    */
/*	note: the xxx_return variables are only used for debugging.	    */
/****************************************************************************/
int IpcSemaphoreSet_return;

void
IpcSemaphoreSet(semId, semno, value)
    int		semId;
    int		semno;
    int		value;
{
    int		errStatus;
    union semun	semun;

    semun.val = value;
    errStatus = semctl(semId, semno, SETVAL, semun);
    IpcSemaphoreSet_return = errStatus;
    
    if (errStatus == -1)
	perror("semctl");
}

/****************************************************************************/
/*   IpcSemaphoreKill(key)	- removes a semaphore			    */
/*									    */
/****************************************************************************/
void
IpcSemaphoreKill(key)
    IpcSemaphoreKey key;
{
    int		i;
    int 	semId;
    int		status;
    union semun	semun;
    
    /* kill semaphore if existent */
    
    semId = semget(key, 0, 0);
    if (semId != -1)
	semctl(semId, 0, IPC_RMID, semun);
}

/****************************************************************************/
/*   IpcSemaphoreLock(semId, sem, lock)	- locks a semaphore		    */
/*									    */
/*	note: the xxx_return variables are only used for debugging.	    */
/****************************************************************************/
int IpcSemaphoreLock_return;

void
IpcSemaphoreLock(semId, sem, lock)
    IpcSemaphoreId	semId;
    int			sem;
    int			lock;
{
    extern int		errno;
    int			errStatus;
    struct sembuf	sops;
    
    sops.sem_op = lock;
    sops.sem_flg = 0;
    sops.sem_num = sem;
    
    /* ----------------
     *	Note: if errStatus is -1 and errno == EINTR then it means we
     *        returned from the operation prematurely because we were
     *	      sent a signal.  So we try and lock the semaphore again.
     *	      I am not certain this is correct, but the semantics aren't
     *	      clear it fixes problems with parallel abort synchronization,
     *	      namely that after processing an abort signal, the semaphore
     *	      call returns with -1 (and errno == EINTR) before it should.
     *	      -cim 3/28/90
     * ----------------
     */
    do {
#ifndef SINGLE_USER
	errStatus = semop(semId, (struct sembuf **)&sops, 1);
#else
    errStatus = 0;
#endif
    } while (errStatus == -1 && errno == EINTR);
    
    IpcSemaphoreLock_return = errStatus;
    
    if (errStatus == -1) {
	if (!ParallelExecutorEnabled() && errno == EIDRM)
	    /*
	     * this is a hack. currently the master backend kills the
	     * slave backend by removing the semaphores that they are waiting
	     * on.  does not want it to complain.
	     */
	    perror("semop");
	exitpg(255);
    }
}

/* ----------------
 *	IpcSemaphoreSilentLock
 *
 *	This does what IpcSemaphoreLock() does but does not
 *	produce error messages.  
 *
 *	note: the xxx_return variables are only used for debugging.
 * ----------------
 */
int IpcSemaphoreSilentLock_return;

void
IpcSemaphoreSilentLock(semId, sem, lock)
    IpcSemaphoreId	semId;
    int			sem;
    int			lock;
{
    int			errStatus;
    struct sembuf	sops;
    
    sops.sem_op = lock;
    sops.sem_flg = 0;
    sops.sem_num = sem;
    
    IpcSemaphoreSilentLock_return =
#ifndef SINGLE_USER
	semop(semId, (struct sembuf **)&sops, 1);
#else
	0;
#endif
}

/****************************************************************************/
/*   IpcSemaphoreUnlock(semId, sem, lock)	- unlocks a semaphore	    */
/*									    */
/*	note: the xxx_return variables are only used for debugging.	    */
/****************************************************************************/
int IpcSemaphoreUnlock_return;
    
void
IpcSemaphoreUnlock(semId, sem, lock)
    IpcSemaphoreId	semId;
    int			sem;
    int			lock;
{
    extern int		errno;
    int			errStatus;
    struct sembuf	sops;
    
    sops.sem_op = -lock;
    sops.sem_flg = 0;
    sops.sem_num = sem;

    
    /* ----------------
     *	Note: if errStatus is -1 and errno == EINTR then it means we
     *        returned from the operation prematurely because we were
     *	      sent a signal.  So we try and lock the semaphore again.
     *	      I am not certain this is correct, but the semantics aren't
     *	      clear it fixes problems with parallel abort synchronization,
     *	      namely that after processing an abort signal, the semaphore
     *	      call returns with -1 (and errno == EINTR) before it should.
     *	      -cim 3/28/90
     * ----------------
     */
    do {
#ifndef SINGLE_USER
	errStatus = semop(semId, (struct sembuf **)&sops, 1);
#else
	errStatus = 0;
#endif
    } while (errStatus == -1 && errno == EINTR);
    
    IpcSemaphoreUnlock_return = errStatus;
    
    if (errStatus == -1) {
	perror("semop");
	exitpg(255);
    }
}

/* ----------------
 *	IpcSemaphoreSilentUnlock
 *
 *	This does what IpcSemaphoreUnlock() does but does not
 *	produce error messages.  This is used in the slave backends
 *	when they exit because it is possible that the master backend
 *	may have died and removed the semaphore before this code gets
 *	to execute in the slaves.
 *
 *	note: the xxx_return variables are only used for debugging.
 * ----------------
 */
int IpcSemaphoreSilentUnlock_return;

void
IpcSemaphoreSilentUnlock(semId, sem, lock)
    IpcSemaphoreId	semId;
    int			sem;
    int			lock;
{
    int			errStatus;
    struct sembuf	sops;
    
    sops.sem_op = -lock;
    sops.sem_flg = 0;
    sops.sem_num = sem;
    
    IpcSemaphoreSilentUnlock_return =
#ifndef SINGLE_USER
	semop(semId, (struct sembuf **)&sops, 1);
#else
	0;
#endif
}

int
IpcSemaphoreGetCount(semId, sem)
IpcSemaphoreId	semId;
int		sem;
{
    int semncnt;

    semncnt = semctl(semId, sem, GETNCNT, NULL);
    return semncnt;
}

int
IpcSemaphoreGetValue(semId, sem)
IpcSemaphoreId	semId;
int		sem;
{
    int semval;

    semval = semctl(semId, sem, GETVAL, NULL);
    return semval;
}

/****************************************************************************/
/*   IpcMemoryCreate(memKey)						    */
/*									    */
/*    - returns the memory identifier, if creation succeeds		    */
/*	returns IpcMemCreationFailed, if failure			    */
/****************************************************************************/

IpcMemoryId
IpcMemoryCreate(memKey, size, permission)
    IpcMemoryKey memKey;
    uint32	 size;
    int		 permission;
{
    IpcMemoryId	 shmid;
    int		 errStatus; 

    if ( memKey == PrivateIPCKey && !(ParallelExecutorEnabled()) ) {
	/* private */
	shmid = PrivateMemoryCreate ( memKey, size , IPC_CREAT|permission);
    } else {
	shmid = shmget(memKey, size, IPC_CREAT|permission); 
    }

    if (shmid < 0) {
	fprintf(stderr,"IpcMemoryCreate: memKey=%d , size=%d , permission=%d", 
	     memKey, size , permission );
	perror("IpcMemoryCreate: shmget(..., create, ...) failed");
	return(IpcMemCreationFailed);
    }
    
    /* if (memKey == PrivateIPCKey) */
    on_exitpg(IPCPrivateMemoryKill, (caddr_t)shmid);
    
    return(shmid);
}

/* ----------------
 *	IpcMemoryCreateWithoutOnExit
 *
 *	Like IpcSemaphoreCreateWithoutOnExit(), this function
 *	creates shared memory without registering an on_exit
 *	procedure.
 * ----------------
 */
IpcMemoryId
IpcMemoryCreateWithoutOnExit(memKey, size, permission)
    IpcMemoryKey memKey;
    uint32	 size;
    int		 permission;
{
    IpcMemoryId	 shmid;
    int		 errStatus; 
    
    if ( memKey == PrivateIPCKey && (!(ParallelExecutorEnabled())) ) {
	/* private */
	shmid = PrivateMemoryCreate ( memKey, size , IPC_CREAT|permission);
    } else {
	shmid = shmget(memKey, size, IPC_CREAT|permission); 
    }

    if (shmid < 0) {
	fprintf(stderr,"IpcMemoryCreate: memKey=%d , size=%d , permission=%d", 
	     memKey, size , permission );
	perror("IpcMemoryCreateWithoutOnExit: shmget(, IPC_CREAT,) failed");
	return(IpcMemCreationFailed);
    }

    return(shmid);
}


/****************************************************************************/
/*  IpcMemoryIdGet(memKey, size)    returns the shared memory Id 	    */
/*				    or IpcMemIdGetFailed	            */
/****************************************************************************/
IpcMemoryId
IpcMemoryIdGet(memKey, size)
    IpcMemoryKey	memKey;
    uint32		size;
{
    IpcMemoryId	shmid;
    
    shmid = shmget(memKey, size, 0);

    if (shmid < 0) {
	fprintf(stderr,"IpcMemoryIdGet: memKey=%d , size=%d , permission=%d", 
	     memKey, size , 0 );
	perror("IpcMemoryIdGet:  shmget() failed");
	return(IpcMemIdGetFailed);
    }
    
    return(shmid);
}


/****************************************************************************/
/*  IpcMemoryAttach(memId)    returns the adress of shared memory	    */
/*			      or IpcMemAttachFailed			    */
/*							                    */
/* CALL IT:  addr = (struct <MemoryStructure> *) IpcMemoryAttach(memId);    */
/*									    */
/****************************************************************************/
char *
IpcMemoryAttach(memId)
    IpcMemoryId	memId;
{
    char	*memAddress;
    int		errStatus;
    
    if ( UsePrivateMemory ) {
	memAddress = (char *)PrivateMemoryAttach ( memId , 0 , 0 );
    } else {
	memAddress = (char *) shmat(memId, 0, 0);
    }

    /*	if ( *memAddress == -1) { XXX ??? */
    if ( memAddress == (char *)-1) {
	perror("IpcMemoryAttach: shmat() failed");
	return(IpcMemAttachFailed);
    }
    
    return((char *) memAddress);
}


/****************************************************************************/
/*  IpcMemoryKill(memKey)    		removes a shared memory segment     */
/*									    */
/****************************************************************************/
void
IpcMemoryKill(memKey)
    IpcMemoryKey	memKey;
{	
    IpcMemoryId		shmid;
    
    if (!UsePrivateMemory && (shmid = shmget(memKey, 0, 0)) >= 0) {
	shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
    }
} 

#ifdef HAS_TEST_AND_SET
/* ------------------
 *  use hardware locks to replace semaphores for sequent machines
 *  to avoid costs of swapping processes and to provide unlimited
 *  supply of locks.
 * ------------------
 */
static SLock *SLockArray = NULL;
static SLock **FreeSLockPP;
static int *UnusedSLockIP;
static slock_t *SLockMemoryLock;
static IpcMemoryId SLockMemoryId = -1;
static int SLockMemorySize = sizeof(SLock*) + sizeof(int) + 
			     sizeof(slock_t) + NSLOCKS*sizeof(SLock);
void
CreateAndInitSLockMemory(key)
IPCKey key;
{
    int id;
    SLock *slckP;

    SLockMemoryId = IpcMemoryCreate(key,
				    SLockMemorySize,
				    0700);
    AttachSLockMemory(key);
    *FreeSLockPP = NULL;
    *UnusedSLockIP = (int)FIRSTFREELOCKID;
    for (id=0; id<(int)FIRSTFREELOCKID; id++) {
	slckP = &(SLockArray[id]);
	S_INIT_LOCK(&(slckP->locklock));
	slckP->flag = NOLOCK;
	slckP->nshlocks = 0;
	S_INIT_LOCK(&(slckP->shlock));
	S_INIT_LOCK(&(slckP->exlock));
	S_INIT_LOCK(&(slckP->comlock));
	slckP->next = NULL;
      }
    return;
}

void
AttachSLockMemory(key)
IPCKey key;
{
    char *slockM;
    if (SLockMemoryId == -1)
	   SLockMemoryId = IpcMemoryIdGet(key,SLockMemorySize);
    if (SLockMemoryId == -1)
	   elog(FATAL, "SLockMemory not in shared memory");
    slockM = IpcMemoryAttach(SLockMemoryId);
    if (slockM == IpcMemAttachFailed)
	elog(FATAL, "AttachSLockMemory: could not attach segment");
    FreeSLockPP = (SLock**)slockM;
    UnusedSLockIP = (int*)(FreeSLockPP + 1);
    SLockMemoryLock = (slock_t*)(UnusedSLockIP + 1);
    S_INIT_LOCK(SLockMemoryLock);
    SLockArray = (SLock*)LONGALIGN((SLockMemoryLock + 1));
    return;
}

int
CreateLock()
{
    int lockid;
    SLock *slckP;

    S_LOCK(SLockMemoryLock);
    if (*FreeSLockPP != NULL) {
       lockid = *FreeSLockPP - SLockArray;
       *FreeSLockPP = (*FreeSLockPP)->next;
      }
    else {
       lockid = *UnusedSLockIP;
       (*UnusedSLockIP)++;
     }
    slckP = &(SLockArray[lockid]);
    S_INIT_LOCK(&(slckP->locklock));
    slckP->flag = NOLOCK;
    slckP->nshlocks = 0;
    S_INIT_LOCK(&(slckP->shlock));
    S_INIT_LOCK(&(slckP->exlock));
    S_INIT_LOCK(&(slckP->comlock));
    slckP->next = NULL;
    S_UNLOCK(SLockMemoryLock);
    return lockid;
}

void
RelinquishLock(lockid)
int lockid;
{
    SLock *slckP;
    slckP = &(SLockArray[lockid]);
    S_LOCK(SLockMemoryLock);
    slckP->next = *FreeSLockPP;
    *FreeSLockPP = slckP;
    S_UNLOCK(SLockMemoryLock);
    return;
}

#ifdef LOCKDEBUG
extern int MyPid;
#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
shlock = %d, exlock =%d)\n", LOCK->locklock, \
LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
LOCK->exlock)
#endif

void
SharedLock(lockid)
int lockid;
{
    SLock *slckP;
#ifdef PARALLELDEBUG
    BeginParallelDebugInfo(PDI_SHAREDLOCK);
#endif
    slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
    printf("Proc %d SharedLock(%d)\n", MyPid, lockid);
    printf("IN: ");
    PRINT_LOCK(slckP);
#endif
sh_try_again:
    S_LOCK(&(slckP->locklock));
    switch (slckP->flag) {
    case NOLOCK:
       slckP->flag = SHAREDLOCK;
       slckP->nshlocks = 1;
       S_LOCK(&(slckP->exlock));
       S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
       printf("OUT: ");
       PRINT_LOCK(slckP);
#endif
#ifdef PARALLELDEBUG
       EndParallelDebugInfo(PDI_SHAREDLOCK);
#endif
       return;
    case SHAREDLOCK:
       (slckP->nshlocks)++;
       S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
       printf("OUT: ");
       PRINT_LOCK(slckP);
#endif
#ifdef PARALLELDEBUG
       EndParallelDebugInfo(PDI_SHAREDLOCK);
#endif
       return;
    case EXCLUSIVELOCK:
       (slckP->nshlocks)++;
       S_UNLOCK(&(slckP->locklock));
       S_LOCK(&(slckP->shlock));
       (slckP->nshlocks)--;
       S_UNLOCK(&(slckP->comlock));
       goto sh_try_again;
     }
}

void
SharedUnlock(lockid)
int lockid;
{
    SLock *slckP;
    slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
    printf("Proc %d SharedUnlock(%d)\n", MyPid, lockid);
    printf("IN: ");
    PRINT_LOCK(slckP);
#endif
    S_LOCK(&(slckP->locklock));
    (slckP->nshlocks)--;
    if (slckP->nshlocks == 0) {
       slckP->flag = NOLOCK;
       S_UNLOCK(&(slckP->exlock));
     }
    S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
       printf("OUT: ");
       PRINT_LOCK(slckP);
#endif
    return;
}

void
ExclusiveLock(lockid)
int lockid;
{
    SLock *slckP;
#ifdef PARALLELDEBUG
    BeginParallelDebugInfo(PDI_EXCLUSIVELOCK);
#endif
    slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
    printf("Proc %d ExclusiveLock(%d)\n", MyPid, lockid);
    printf("IN: ");
    PRINT_LOCK(slckP);
#endif
ex_try_again:
    S_LOCK(&(slckP->locklock));
    switch (slckP->flag) {
    case NOLOCK:
	slckP->flag = EXCLUSIVELOCK;
	S_LOCK(&(slckP->exlock));
	S_LOCK(&(slckP->shlock));
	S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
       printf("OUT: ");
       PRINT_LOCK(slckP);
#endif
#ifdef PARALLELDEBUG
	EndParallelDebugInfo(PDI_EXCLUSIVELOCK);
#endif
	return;
    case SHAREDLOCK:
    case EXCLUSIVELOCK:
	S_UNLOCK(&(slckP->locklock));
	S_LOCK(&(slckP->exlock));
	S_UNLOCK(&(slckP->exlock));
	goto ex_try_again;
      }
}

void
ExclusiveUnlock(lockid)
int lockid;
{
    SLock *slckP;
    int i;

    slckP = &(SLockArray[lockid]);
#ifdef LOCKDEBUG
    printf("Proc %d ExclusiveUnlock(%d)\n", MyPid, lockid);
    printf("IN: ");
    PRINT_LOCK(slckP);
#endif
    S_LOCK(&(slckP->locklock));
    /* -------------
     *  give favor to read processes
     * -------------
     */
    slckP->flag = NOLOCK;
    if (slckP->nshlocks > 0) {
	while (slckP->nshlocks > 0) {
	   S_UNLOCK(&(slckP->shlock));
	   S_LOCK(&(slckP->comlock));
	 }
	S_UNLOCK(&(slckP->shlock));
      }
    else {
      S_UNLOCK(&(slckP->shlock));
     }
    S_UNLOCK(&(slckP->exlock));
    S_UNLOCK(&(slckP->locklock));
#ifdef LOCKDEBUG
       printf("OUT: ");
       PRINT_LOCK(slckP);
#endif
    return;
}

bool
LockIsFree(lockid)
int lockid;
{
    return(SLockArray[lockid].flag == NOLOCK);
}

#endif /* HAS_TEST_AND_SET */
@


1.36
log
@fix sequent compilation errors
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.35 91/08/29 23:54:07 mer Exp $
d453 1
a453 1
	if (!ParallelExecutorEnabled())
@


1.35
log
@purge old lmgr code
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.34 91/08/14 12:32:37 mer Exp $
d760 1
a760 1
    LockId id;
d802 1
a802 1
SemId
d852 1
a852 1
SemId lockid;
d903 1
a903 1
SemId lockid;
d928 1
a928 1
SemId lockid;
d967 1
a967 1
SemId lockid;
d1005 1
a1005 1
SemId lockid;
@


1.34
log
@add quasi_exitpg - run all exitpg scripts without exiting!!
@
text
@d6 1
a6 1
 *      $Header: /users/mer/postgres/src/storage/ipc/RCS/ipc.c,v 1.33 91/07/24 10:06:28 hong Exp Locker: mer $
a35 1
#include "storage/plparam.h"
d252 1
a252 1
    ushort	array[NMAXSEM];
d257 1
a257 1
    if (semNum > NMAXSEM || semNum <= 0)  {
d331 1
a331 1
    ushort	array[NMAXSEM];
d336 1
a336 1
    if (semNum > NMAXSEM || semNum <= 0)  {
@


1.33
log
@fixed a compilation error
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.32 91/07/24 07:46:49 mao Exp Locker: hong $
d131 33
@


1.32
log
@cleanup and add main memory storage manager
@
text
@d6 1
a6 1
 *      $Header: /users/mao/postgres/src/storage/ipc/RCS/ipc.c,v 1.31 1991/07/17 23:45:36 hong Exp $
d736 2
a737 2
    *UnusedSLockIP = (SLock) FIRSTFREELOCKID;
    for (id=0; id<(LockId)FIRSTFREELOCKID; id++) {
@


1.31
log
@include slaves.h to get rid of some compile warnings
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.30 91/06/12 10:18:47 kemnitz Exp Locker: hong $
d736 2
a737 2
    *UnusedSLockIP = FIRSTFREELOCKID;
    for (id=0; id<FIRSTFREELOCKID; id++) {
@


1.30
log
@a few fixes to support generalized spinlocks.
@
text
@d6 1
a6 1
 *      $Header: src/storage/ipc/RCS/ipc.c,v 1.29 91/06/10 20:57:40 kemnitz Exp $
d39 1
@


1.29
log
@generalization of spinlocks.
@
text
@d6 1
a6 1
 *      $Header: ipc/RCS/ipc.c,v 1.28 91/04/23 17:08:04 kemnitz Exp Locker: kemnitz $
d37 1
d716 1
a716 1
static SLock *SLockArray;
d765 1
a765 1
    SLockArray = (SLock*)(SLockMemoryLock + 1);
@


1.28
log
@added "SINGLE_USER" to turn off semop
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.27 91/04/01 08:46:47 hong Exp Locker: kemnitz $
d708 1
a708 1
#ifdef sequent
d976 1
a976 1
#endif /* sequent */
@


1.27
log
@gotten rid of a useless constant, IpcMaxNumSem
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.26 91/03/07 22:04:48 hong Exp Locker: hong $
d409 1
d411 3
d455 1
d457 3
d496 1
d498 3
d539 1
d541 3
@


1.26
log
@new parallel debugging facilities plugged in
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.25 91/03/03 17:27:40 hong Exp Locker: hong $
d36 1
d218 1
a218 1
    ushort	array[IpcMaxNumSem];
d223 1
a223 1
    if (semNum > IpcMaxNumSem || semNum <= 0)  {
d297 1
a297 1
    ushort	array[IpcMaxNumSem];
d302 1
a302 1
    if (semNum > IpcMaxNumSem || semNum <= 0)  {
@


1.25
log
@measure time spent in locking for debugging of parallel executor
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.24 91/02/28 21:46:04 hong Exp $
d41 1
a41 5
#include <usclkc.h>
usclk_t ExclusiveLockTime;
usclk_t SharedLockTime;
int ExclusiveLockCount;
int SharedLockCount;
d805 1
a805 3
    usclk_t st;
    st = getusclk();
    SharedLockCount++;
d826 1
a826 1
       SharedLockTime += (getusclk() - st);
d837 1
a837 1
       SharedLockTime += (getusclk() - st);
d881 1
a881 3
    usclk_t st;
    st = getusclk();
    ExclusiveLockCount++;
d902 1
a902 1
	ExclusiveLockTime += (getusclk() - st);
@


1.24
log
@tell slave backends to shut up when exiting.
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.23 91/02/18 20:39:25 hong Exp Locker: hong $
d40 8
d808 5
d831 3
d842 3
d886 5
d908 3
@


1.23
log
@specify size for SLock memory for sequent
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.22 91/01/18 22:15:21 hong Exp Locker: hong $
d410 7
a416 1
	perror("semop");
@


1.22
log
@added two new routines for semaphore handling
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.21 90/11/28 20:57:13 hong Exp Locker: hong $
d693 2
d703 1
a703 4
				    sizeof(SLock*) + 
				    sizeof(int) +
				    sizeof(slock_t) +
				    NSLOCKS*sizeof(SLock),
d705 1
a705 1
    AttachSLockMemory();
d727 1
a727 1
	   SLockMemoryId = IpcMemoryIdGet(key,0);
@


1.21
log
@fixed the locking routines , now deadlock free
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.20 90/11/12 08:15:19 hong Exp Locker: hong $
d519 21
@


1.20
log
@initialize reserved locks
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.19 90/11/07 12:06:07 hong Exp Locker: hong $
d695 1
d742 1
d806 1
a806 1
       S_UNLOCK(&(slckP->shlock));
d889 1
a889 1
	while (slckP->nshlocks > 0)
d891 3
d906 8
@


1.19
log
@changes in the locking routines for sequent
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.18 90/10/23 17:19:06 kemnitz Exp Locker: hong $
d676 3
d687 10
a696 1
    *UnusedSLockIP = 3;  /* 0, 1, 2 are reserved */
@


1.18
log
@fixed problem with SLocks on sequent when postmaster is run
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.17 90/10/17 17:09:19 hong Exp $
d747 8
d761 6
d772 1
d774 4
d782 4
d791 3
a793 2
       SharedLock(lockid);
       return;
d803 5
d815 4
d828 6
d838 2
d841 4
d850 2
a851 2
	ExclusiveLock(lockid);
	return;
d860 2
d863 5
d875 2
a876 2
	slckP->nshlocks = 0;
	S_UNLOCK(&(slckP->shlock));
d879 1
a879 1
      S_UNLOCK(&(slckP->exlock));
d881 1
d883 4
@


1.17
log
@to complain when malloc out of memory
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.16 90/10/16 23:33:06 hong Exp Locker: hong $
d689 2
a690 1
AttachSLockMemory()
d694 3
a696 1
	elog(FATAL, "SLockMemory not in shared memory");
@


1.16
log
@replace semaphores with hardware locks for sequent
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.15 90/10/02 12:11:10 goh Exp Locker: hong $
d72 2
@


1.15
log
@yet another fix to coexist peacefully with parallel executor
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.13 90/09/30 15:53:11 goh Exp $
d36 1
d657 171
@


1.14
log
@fix for parallel stuff
@
text
@d533 1
a533 1
    if ( memKey == PrivateIPCKey ) {
d570 1
a570 1
    if ( memKey == PrivateIPCKey ) {
@


1.13
log
@cleaned up dependencies ... also, if running standalone,
uses private instead of shared memory
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.12 90/08/14 15:41:42 cimarron Exp $
d570 7
a576 1
    shmid = shmget(memKey, size, IPC_CREAT|permission); 
@


1.12
log
@Updating from revision 1.11 to revision 1.12
@
text
@d10 1
d13 2
d16 1
d19 2
a20 1
#ifndef sequent
a21 6
#else
#include "/usr/att/usr/include/sys/ipc.h"
#endif
#endif

#ifndef sequent
d24 1
d26 2
d30 2
a33 2
#include <errno.h>

d37 2
d53 4
d58 27
d169 5
a173 1
    shmctl(shmId, IPC_RMID, (struct shmid_ds *)NULL);
d223 6
d230 1
d251 8
a258 1
    
d516 1
d532 8
a539 2
    
    shmid = shmget(memKey, size, IPC_CREAT|permission); 
d541 2
d572 2
d594 1
d596 2
d620 6
a625 3
    /*	memAddress = (char *) malloc(sizeof(int)); XXX ??? */
    memAddress = (char *) shmat(memId, 0, 0);
    
a630 10

    /* XXX huh?
       switch (errno) {
       case EINVAL:
       case EACCES:
       case ENOMEM:
       case EMFILE: perror("IpcMemoryAttach: shmat() failed:");
       return(IpcMemAttachFailed);
       }
       */
d646 1
a646 1
    if ((shmid = shmget(memKey, 0, 0)) >= 0) {
@


1.11
log
@Added sequent compatilibity stuff
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.10 90/03/31 19:00:31 cimarron Exp Locker: kemnitz $
d32 2
a33 2
#include "ipci.h"		/* for PrivateIPCKey XXX */
#include "ipc.h"
@


1.10
log
@*** empty log message ***
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.9 90/03/12 16:26:40 cimarron Exp $
d15 1
d17 2
d20 1
d22 1
d25 5
@


1.9
log
@Integration Checkin
@
text
@d1 1
a1 1
/*
d6 2
a7 1
 *      $Header: RCS/ipc.c,v 1.8 90/02/13 00:27:54 kemnitz Exp $
d49 1
d57 15
a104 1
static
a118 1
static
d199 60
d260 1
d264 1
d266 2
d269 4
a272 1
IpcSemaphoreSet(semId, value)
a273 1
    int		i;
a274 2
    int		semId;
    ushort	array[IpcMaxNumSem];
d277 3
a279 1
    /* **** RESUME HERE **** */
d281 1
a281 3
    semun.array = array;
    errStatus = semctl(semId, 0, SETALL, semun);
    if (errStatus == -1) {
a282 1
    }
d308 1
d310 2
d318 1
d326 17
a342 1
    errStatus = semop(semId, (struct sembuf **)&sops, 1);
d349 10
d360 17
d378 1
a378 1
/*   IpcSemaphoreUnLock(semId, sem, lock)	- unlocks a semaphore	    */
d380 1
d382 2
d390 1
d397 1
d399 17
a415 1
    errStatus = semop(semId, (struct sembuf **)&sops, 1);
d422 13
d436 16
a452 1

d478 26
@


1.8
log
@Added "code" to arg list of exitpg()
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.7 90/02/12 19:48:10 cimarron Exp Locker: kemnitz $
d184 22
@


1.7
log
@added buffer manager statistics and exitpg() stuff -cim
@
text
@d6 1
a6 1
 *      $Header: RCS/ipc.c,v 1.6 89/09/05 17:23:33 mao C_Demo_1 $
d56 1
a56 1
	(*onexit_list[i].function)(onexit_list[i].arg);
@


1.6
log
@Working version of C-only demo
@
text
@d6 1
a6 1
 *      $Header: /usr6/postgres/mao/postgres/src/storage/ipc/RCS/ipc.c,v 1.5 89/08/03 00:06:06 dillon Exp $
d11 1
d16 1
d20 1
a21 1

d24 3
a26 3
/*
 * IPCPrivateSemaphoreKill --
 *	On_exit(3) termination handler.
d28 21
a48 1
extern
d50 4
a53 4
IPCPrivateSemaphoreKill ARGS((
	int	status,
	int	semId
));
d55 12
a66 3
/*
 * IPCPrivateMemoryKill --
 *	On_exit(3) termination handler.
d68 21
a88 1
extern
d90 7
a96 4
IPCPrivateMemoryKill ARGS((
	int	status,
	int	shmId
));
d98 1
d100 14
d115 7
a121 5
/*		- 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*/
/*									*/
d123 1
d134 1
d137 5
a141 5
IpcSemaphoreKey		semKey;   				/* input patameter  */
int					semNum;					/* input patameter  */
int					permission;				/* input patameter  */
int					semStartValue;			/* input patameter  */
int					*status;				/* output parameter */
d143 20
a162 34
	int	i;
	int	errStatus;
	int	semId;
	ushort		array[IpcMaxNumSem];
	union semun	semun;

	/* get a semaphore if non-existent */
	/* check arguments	*/
	if (semNum > IpcMaxNumSem || 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 	*/
		semId = semget(semKey, semNum, IPC_CREAT|permission);
		if (semId < 0) {
			perror("semget");
			exit(3);
		}
		for (i = 0; i < semNum; i++) {
			array[i] = semStartValue;
		}
		semun.array = array;
		errStatus = semctl(semId, 0, SETALL, semun);
		if (errStatus == -1) {
			perror("semctl");
		}

		/* if (semKey == PrivateIPCKey) */
		on_exit(IPCPrivateSemaphoreKill, (caddr_t)semId);

	} else {	/* there is a semaphore id for this key */
		*status = IpcSemIdExist;
d164 18
a181 1
	return(semId);
d186 2
a187 2
/*   IpcSemaphoreKill(key)	- removes a semaphore						    */
/*																			*/
d191 1
a191 1
IpcSemaphoreKey key;
d193 10
a202 11
	int	i, semId;
	int	status;

	/* kill semaphore if existent */

	semId = semget(key, 0, 0);
	if (semId != -1) {
		union semun	semun;

		semctl(semId, 0, IPC_RMID, semun);
	}
d206 2
a207 2
/*   IpcSemaphoreLock(semId, sem, lock)	- locks a semaphore				    */
/*																			*/
d211 3
a213 3
IpcSemaphoreId		semId;
int					sem;
int					lock;
d215 12
a226 12
	int		errStatus;
	struct sembuf	sops;

	sops.sem_op = lock;
	sops.sem_flg = 0;
	sops.sem_num = sem;

	errStatus = semop(semId, (struct sembuf **)&sops, 1);
	if (errStatus == -1) {
		perror("semop");
		exit(255);
	}
d231 2
a232 2
/*   IpcSemaphoreUnLock(semId, sem, lock)	- unlocks a semaphore		    */
/*																			*/
d236 3
a238 3
IpcSemaphoreId		semId;
int					sem;
int					lock;
d240 12
a251 12
	int		errStatus;
	struct sembuf	sops;

	sops.sem_op = -lock;
	sops.sem_flg = 0;
	sops.sem_num = sem;

	errStatus = semop(semId, (struct sembuf **)&sops, 1);
	if (errStatus == -1) {
		perror("semop");
		exit(255);
	}
d258 4
a261 3
/*   IpcMemoryCreate(memKey)												*/
/*                     - returns the memory identifier, if creation succeeds*/
/*						 returns IpcMemCreationFailed, if failure			*/
d263 1
d266 3
a268 3
IpcMemoryKey		memKey;
uint32				size;
int					permission;
d270 13
a282 13
	IpcMemoryId	shmid;
	int			errStatus; 
	
	shmid = shmget(memKey, size, IPC_CREAT|permission); 
	if (shmid < 0) {
		perror("IpcMemoryCreate: shmget(..., create, ...) failed");
		return(IpcMemCreationFailed);
	}

	/* if (memKey == PrivateIPCKey) */
	on_exit(IPCPrivateMemoryKill, (caddr_t)shmid);

	return(shmid);
d287 2
a288 2
/*  IpcMemoryIdGet(memKey, size)    returns the shared memory Id 			*/
/*									or IpcMemIdGetFailed					*/
d292 2
a293 2
IpcMemoryKey	memKey;
uint32		size;
d295 9
a303 8
	IpcMemoryId	shmid;

	shmid = shmget(memKey, size, 0);
	if (shmid < 0) {
		perror("IpcMemoryIdGet:  shmget() failed");
		return(IpcMemIdGetFailed);
	}
	return(shmid);
d308 5
a312 5
/*  IpcMemoryAttach(memId)    returns the adress of shared memory			*/
/*							  or IpcMemAttachFailed		 					*/
/*																			*/
/* CALL IT:  addr = (struct <MemoryStructure> *) IpcMemoryAttach(memId);	*/
/*																			*/
d316 1
a316 1
IpcMemoryId		memId;
d318 23
a340 20
	char	*memAddress;
	int		errStatus;
	
/*	memAddress = (char *) malloc(sizeof(int));	XXX ??? */
	memAddress = (char *) shmat(memId, 0, 0);
/*	if ( *memAddress == -1) {			XXX ??? */
	if ( memAddress == (char *)-1) {
		perror("IpcMemoryAttach: shmat() failed");
		return(IpcMemAttachFailed);
	}
/* XXX huh?
	switch (errno) {
	case EINVAL:
	case EACCES:
	case ENOMEM:
	case EMFILE: perror("IpcMemoryAttach: shmat() failed:");
				 return(IpcMemAttachFailed);
	}
*/
	return((char *) memAddress);
d345 2
a346 2
/*  IpcMemoryKill(memKey)    		removes a shared memory segment			*/
/*																			*/
d350 1
a350 1
IpcMemoryKey		memKey;
d352 5
a356 5
	IpcMemoryId	shmid;

	if ((shmid = shmget(memKey, 0, 0)) >= 0) {
		shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
	}
a357 19

static
void
IPCPrivateSemaphoreKill(status, semId)
	int	status;
	int	semId;		/* caddr_t */
{
	union semun	semun;
	semctl(semId, 0, IPC_RMID, semun);
}

static
void
IPCPrivateMemoryKill(status, shmId)
	int	status;
	int	shmId;		/* caddr_t */
{
	shmctl(shmId, IPC_RMID, (struct shmid_ds *)NULL);
}
@


1.5
log
@shared memory lock manager code (does not used semaphores)
@
text
@d6 1
a6 1
 *      $Header: ipc.c,v 1.2 89/02/02 16:15:58 dillon Locked $
@


1.4
log
@*** empty log message ***
@
text
@d6 1
a6 1
 *      $Header: /usr6/postgres/dillon/ptree/src/storage/ipc/RCS/ipc.c,v 1.3 89/04/14 18:31:00 dillon Exp $
a8 1
#include <stdio.h>
a82 3
	/*
	printf("%d = semget(%d,%d,0%od)\n", semId, semKey, semNum, permission);
	*/
d84 1
a84 1
		*status = IpcSemIdNotExist;/* there doesn't exist a semaphore*/
a85 5
		/*
		printf("%d = semget(%d,%d,0%od)\n", 
			semId, semKey, semNum, IPC_CREAT|permission
		);
		*/
a198 4
		fprintf(stderr, 
		    "Arguments: memKey=%08lx, size=%ld, perm=0%o\n",
		    memKey, size, permission | IPC_CREAT
		);
@


1.3
log
@*** empty log message ***
@
text
@d6 1
a6 1
 *      $Header: /usr6/postgres/dillon/ptree/src/storage/ipc/RCS/ipc.c,v 1.2 89/02/02 16:15:58 dillon Stab $
d84 3
d88 1
a88 1
		*status = IpcSemIdNotExist;	/* there doesn't exist a semaphore 	*/
d90 5
@


1.2
log
@Txfer from old tree
@
text
@d6 1
a6 1
 *      $Header: ipc.c,v 1.1 88/06/15 17:15:38 dillon Locked $
d9 1
d200 4
@


1.1
log
@Initial revision
@
text
@a0 1

a1 26
 * 
 * POSTGRES Data Base Management System
 * 
 * Copyright (c) 1988 Regents of the University of California
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of the University of California not be used in advertising
 * or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Permission to incorporate this
 * software into commercial products can be obtained from the Campus
 * Software Office, 295 Evans Hall, University of California, Berkeley,
 * Ca., 94720 provided only that the the requestor give the University
 * of California a free licence to any derived software for educational
 * and research purposes.  The University of California makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 * 
 */



/*
d6 1
a6 1
 *      $Header: ipc.c,v 1.1 88/11/11 16:37:37 postgres Exp $
@
