diff options
author | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
commit | 1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch) | |
tree | 8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/storage/ipc | |
parent | 8fecd4febf8357f3cc20383ed29ced484877d5ac (diff) | |
download | postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip |
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/storage/ipc')
-rw-r--r-- | src/backend/storage/ipc/ipc.c | 991 | ||||
-rw-r--r-- | src/backend/storage/ipc/ipci.c | 178 | ||||
-rw-r--r-- | src/backend/storage/ipc/s_lock.c | 384 | ||||
-rw-r--r-- | src/backend/storage/ipc/shmem.c | 951 | ||||
-rw-r--r-- | src/backend/storage/ipc/shmqueue.c | 274 | ||||
-rw-r--r-- | src/backend/storage/ipc/sinval.c | 222 | ||||
-rw-r--r-- | src/backend/storage/ipc/sinvaladt.c | 1129 | ||||
-rw-r--r-- | src/backend/storage/ipc/spin.c | 246 |
8 files changed, 2276 insertions, 2099 deletions
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c index a5573e89151..3dd6d2ec094 100644 --- a/src/backend/storage/ipc/ipc.c +++ b/src/backend/storage/ipc/ipc.c @@ -1,26 +1,26 @@ /*------------------------------------------------------------------------- * * ipc.c-- - * POSTGRES inter-process communication definitions. + * POSTGRES inter-process communication definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.11 1997/08/19 21:32:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.12 1997/09/07 04:48:30 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 + * 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 * *------------------------------------------------------------------------- */ @@ -44,94 +44,98 @@ #endif #if defined(bsd44) -int UsePrivateMemory = 1; +int UsePrivateMemory = 1; + #else -int UsePrivateMemory = 0; +int UsePrivateMemory = 0; + #endif -static void IpcMemoryDetach(int status, char *shmaddr); +static void IpcMemoryDetach(int status, char *shmaddr); /* ---------------------------------------------------------------- - * exit() handling stuff + * exit() handling stuff * ---------------------------------------------------------------- */ #define MAX_ON_EXITS 20 -static struct ONEXIT { - void (*function)(); - caddr_t arg; -} onexit_list[ MAX_ON_EXITS ]; +static struct ONEXIT +{ + void (*function) (); + caddr_t arg; +} onexit_list[MAX_ON_EXITS]; -static int onexit_index; -static void IpcConfigTip(void); +static int onexit_index; +static void IpcConfigTip(void); -typedef struct _PrivateMemStruct { - int id; - char *memptr; -} PrivateMem; +typedef struct _PrivateMemStruct +{ + int id; + char *memptr; +} PrivateMem; -PrivateMem IpcPrivateMem[16]; +PrivateMem IpcPrivateMem[16]; static int PrivateMemoryCreate(IpcMemoryKey memKey, - uint32 size) + 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"); - memset(IpcPrivateMem[memid].memptr, 0, size); /* XXX PURIFY */ - - return (memid++); + 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"); + memset(IpcPrivateMem[memid].memptr, 0, size); /* XXX PURIFY */ + + return (memid++); } -static char * +static char * PrivateMemoryAttach(IpcMemoryId memid) { - return ( IpcPrivateMem[memid].memptr ); + return (IpcPrivateMem[memid].memptr); } /* ---------------------------------------------------------------- - * exitpg + * 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 + * 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 exitpg_inprogress = 0; +static int exitpg_inprogress = 0; void exitpg(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); + 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); } /* ------------------ @@ -143,591 +147,628 @@ exitpg(int code) 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; + 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 + * on_exitpg * - * this function adds a callback function to the list of - * functions invoked by exitpg(). -cim 2/6/90 + * this function adds a callback function to the list of + * functions invoked by exitpg(). -cim 2/6/90 * ---------------------------------------------------------------- */ int -on_exitpg(void (*function)(), caddr_t arg) + on_exitpg(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); + 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) */ -/* */ +/* IPCPrivateSemaphoreKill(status, semId) */ +/* */ /****************************************************************************/ static void IPCPrivateSemaphoreKill(int status, - int semId) /* caddr_t */ + int semId) /* caddr_t */ { - union semun semun; - semctl(semId, 0, IPC_RMID, semun); + union semun semun; + + semctl(semId, 0, IPC_RMID, semun); } /****************************************************************************/ -/* IPCPrivateMemoryKill(status, shmId) */ -/* */ +/* IPCPrivateMemoryKill(status, shmId) */ +/* */ /****************************************************************************/ static void IPCPrivateMemoryKill(int status, - int shmId) /* caddr_t */ + 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); + 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: */ -/* */ +/* 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 */ -/* */ +/* 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 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. + * Currently, the semaphore sets are "attached" and an error + * is detected only when a later shared memory attach fails. */ IpcSemaphoreId IpcSemaphoreCreate(IpcSemaphoreKey semKey, - int semNum, - int permission, - int semStartValue, - int removeOnExit, - int *status) + 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 */ + 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 - fprintf(stderr,"calling semget with %d, %d , %d\n", - semKey, - semNum, - IPC_CREAT|permission ); + fprintf(stderr, "calling semget with %d, %d , %d\n", + semKey, + semNum, + IPC_CREAT | permission); #endif - semId = semget(semKey, semNum, IPC_CREAT|permission); + semId = semget(semKey, semNum, IPC_CREAT | permission); + + if (semId < 0) + { + perror("semget"); + IpcConfigTip(); + 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"); + IpcConfigTip(); + } + + if (removeOnExit) + on_exitpg(IPCPrivateSemaphoreKill, (caddr_t) semId); - if (semId < 0) { - perror("semget"); - IpcConfigTip(); - 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"); - IpcConfigTip(); + else + { + /* there is a semaphore id for this key */ + *status = IpcSemIdExist; } - - if (removeOnExit) - 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); + fprintf(stderr, "\nIpcSemaphoreCreate, status %d, returns %d\n", + *status, + semId); + fflush(stdout); + fflush(stderr); #endif - return(semId); + return (semId); } /****************************************************************************/ -/* IpcSemaphoreSet() - sets the initial value of the semaphore */ -/* */ -/* note: the xxx_return variables are only used for debugging. */ +/* IpcSemaphoreSet() - sets the initial value of the semaphore */ +/* */ +/* note: the xxx_return variables are only used for debugging. */ /****************************************************************************/ #ifdef NOT_USED -static int IpcSemaphoreSet_return; +static int IpcSemaphoreSet_return; void IpcSemaphoreSet(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"); - IpcConfigTip(); - } + int errStatus; + union semun semun; + + semun.val = value; + errStatus = semctl(semId, semno, SETVAL, semun); + IpcSemaphoreSet_return = errStatus; + + if (errStatus == -1) + { + perror("semctl"); + IpcConfigTip(); + } } + #endif /****************************************************************************/ -/* IpcSemaphoreKill(key) - removes a semaphore */ -/* */ +/* IpcSemaphoreKill(key) - removes a semaphore */ +/* */ /****************************************************************************/ void IpcSemaphoreKill(IpcSemaphoreKey key) { - int semId; - union semun semun; - - /* kill semaphore if existent */ - - semId = semget(key, 0, 0); - if (semId != -1) - semctl(semId, 0, IPC_RMID, semun); + int semId; + 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. */ +/* IpcSemaphoreLock(semId, sem, lock) - locks a semaphore */ +/* */ +/* note: the xxx_return variables are only used for debugging. */ /****************************************************************************/ -static int IpcSemaphoreLock_return; +static int IpcSemaphoreLock_return; void IpcSemaphoreLock(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 { - errStatus = semop(semId, &sops, 1); - } while (errStatus == -1 && errno == EINTR); - - IpcSemaphoreLock_return = errStatus; - - if (errStatus == -1) { - perror("semop"); - IpcConfigTip(); - exitpg(255); - } + 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 + { + errStatus = semop(semId, &sops, 1); + } while (errStatus == -1 && errno == EINTR); + + IpcSemaphoreLock_return = errStatus; + + if (errStatus == -1) + { + perror("semop"); + IpcConfigTip(); + exitpg(255); + } } /****************************************************************************/ -/* IpcSemaphoreUnlock(semId, sem, lock) - unlocks a semaphore */ -/* */ -/* note: the xxx_return variables are only used for debugging. */ +/* IpcSemaphoreUnlock(semId, sem, lock) - unlocks a semaphore */ +/* */ +/* note: the xxx_return variables are only used for debugging. */ /****************************************************************************/ -static int IpcSemaphoreUnlock_return; +static int IpcSemaphoreUnlock_return; void IpcSemaphoreUnlock(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 { - errStatus = semop(semId, &sops, 1); - } while (errStatus == -1 && errno == EINTR); - - IpcSemaphoreUnlock_return = errStatus; - - if (errStatus == -1) { - perror("semop"); - IpcConfigTip(); - exitpg(255); - } + 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 + { + errStatus = semop(semId, &sops, 1); + } while (errStatus == -1 && errno == EINTR); + + IpcSemaphoreUnlock_return = errStatus; + + if (errStatus == -1) + { + perror("semop"); + IpcConfigTip(); + exitpg(255); + } } int -IpcSemaphoreGetCount(IpcSemaphoreId semId, int sem) +IpcSemaphoreGetCount(IpcSemaphoreId semId, int sem) { - int semncnt; - union semun dummy; /* for Solaris */ - - semncnt = semctl(semId, sem, GETNCNT, dummy); - return semncnt; + int semncnt; + union semun dummy; /* for Solaris */ + + semncnt = semctl(semId, sem, GETNCNT, dummy); + return semncnt; } int -IpcSemaphoreGetValue(IpcSemaphoreId semId, int sem) +IpcSemaphoreGetValue(IpcSemaphoreId semId, int sem) { - int semval; - union semun dummy; /* for Solaris */ - - semval = semctl(semId, sem, GETVAL, dummy); - return semval; + int semval; + union semun dummy; /* for Solaris */ + + semval = semctl(semId, sem, GETVAL, dummy); + return semval; } /****************************************************************************/ -/* IpcMemoryCreate(memKey) */ -/* */ -/* - returns the memory identifier, if creation succeeds */ -/* returns IpcMemCreationFailed, if failure */ +/* IpcMemoryCreate(memKey) */ +/* */ +/* - returns the memory identifier, if creation succeeds */ +/* returns IpcMemCreationFailed, if failure */ /****************************************************************************/ IpcMemoryId IpcMemoryCreate(IpcMemoryKey memKey, uint32 size, int permission) { - IpcMemoryId shmid; - - if (memKey == PrivateIPCKey) { - /* private */ - shmid = PrivateMemoryCreate(memKey, size); - }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"); - IpcConfigTip(); - return(IpcMemCreationFailed); - } - - /* if (memKey == PrivateIPCKey) */ - on_exitpg(IPCPrivateMemoryKill, (caddr_t)shmid); - - return(shmid); + IpcMemoryId shmid; + + if (memKey == PrivateIPCKey) + { + /* private */ + shmid = PrivateMemoryCreate(memKey, size); + } + 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"); + IpcConfigTip(); + return (IpcMemCreationFailed); + } + + /* if (memKey == PrivateIPCKey) */ + on_exitpg(IPCPrivateMemoryKill, (caddr_t) shmid); + + return (shmid); } /****************************************************************************/ -/* IpcMemoryIdGet(memKey, size) returns the shared memory Id */ -/* or IpcMemIdGetFailed */ +/* IpcMemoryIdGet(memKey, size) returns the shared memory Id */ +/* or IpcMemIdGetFailed */ /****************************************************************************/ IpcMemoryId IpcMemoryIdGet(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"); - IpcConfigTip(); - return(IpcMemIdGetFailed); - } - - return(shmid); + 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"); + IpcConfigTip(); + return (IpcMemIdGetFailed); + } + + return (shmid); } /****************************************************************************/ -/* IpcMemoryDetach(status, shmaddr) removes a shared memory segment */ -/* from a backend address space */ -/* (only called by backends running under the postmaster) */ +/* IpcMemoryDetach(status, shmaddr) removes a shared memory segment */ +/* from a backend address space */ +/* (only called by backends running under the postmaster) */ /****************************************************************************/ static void IpcMemoryDetach(int status, char *shmaddr) { - if (shmdt(shmaddr) < 0) { - elog(NOTICE, "IpcMemoryDetach: shmdt(0x%x): %m", shmaddr); - } + if (shmdt(shmaddr) < 0) + { + elog(NOTICE, "IpcMemoryDetach: shmdt(0x%x): %m", shmaddr); + } } /****************************************************************************/ -/* IpcMemoryAttach(memId) returns the adress of shared memory */ -/* or IpcMemAttachFailed */ -/* */ -/* CALL IT: addr = (struct <MemoryStructure> *) IpcMemoryAttach(memId); */ -/* */ +/* IpcMemoryAttach(memId) returns the adress of shared memory */ +/* or IpcMemAttachFailed */ +/* */ +/* CALL IT: addr = (struct <MemoryStructure> *) IpcMemoryAttach(memId); */ +/* */ /****************************************************************************/ -char * +char * IpcMemoryAttach(IpcMemoryId memId) { - char *memAddress; - - if (UsePrivateMemory) { - memAddress = (char *) PrivateMemoryAttach(memId); - } else { - memAddress = (char *) shmat(memId, 0, 0); - } - - /* if ( *memAddress == -1) { XXX ??? */ - if ( memAddress == (char *)-1) { - perror("IpcMemoryAttach: shmat() failed"); - IpcConfigTip(); - return(IpcMemAttachFailed); - } - - if (!UsePrivateMemory) - on_exitpg(IpcMemoryDetach, (caddr_t) memAddress); - - return((char *) memAddress); + char *memAddress; + + if (UsePrivateMemory) + { + memAddress = (char *) PrivateMemoryAttach(memId); + } + else + { + memAddress = (char *) shmat(memId, 0, 0); + } + + /* if ( *memAddress == -1) { XXX ??? */ + if (memAddress == (char *) -1) + { + perror("IpcMemoryAttach: shmat() failed"); + IpcConfigTip(); + return (IpcMemAttachFailed); + } + + if (!UsePrivateMemory) + on_exitpg(IpcMemoryDetach, (caddr_t) memAddress); + + return ((char *) memAddress); } /****************************************************************************/ -/* IpcMemoryKill(memKey) removes a shared memory segment */ -/* (only called by the postmaster and standalone backends) */ +/* IpcMemoryKill(memKey) removes a shared memory segment */ +/* (only called by the postmaster and standalone backends) */ /****************************************************************************/ void IpcMemoryKill(IpcMemoryKey memKey) -{ - IpcMemoryId shmid; - - if (!UsePrivateMemory && (shmid = shmget(memKey, 0, 0)) >= 0) { - if (shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL) < 0) { - elog(NOTICE, "IpcMemoryKill: shmctl(%d, %d, 0) failed: %m", - shmid, IPC_RMID); +{ + IpcMemoryId shmid; + + if (!UsePrivateMemory && (shmid = shmget(memKey, 0, 0)) >= 0) + { + if (shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL) < 0) + { + elog(NOTICE, "IpcMemoryKill: shmctl(%d, %d, 0) failed: %m", + shmid, IPC_RMID); + } } - } -} +} #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. + * 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 *SLockArray = NULL; +static SLock **FreeSLockPP; +static int *UnusedSLockIP; static slock_t *SLockMemoryLock; static IpcMemoryId SLockMemoryId = -1; -struct ipcdummy { /* to get alignment/size right */ - SLock *free; - int unused; - slock_t memlock; - SLock slocks[NSLOCKS]; +struct ipcdummy +{ /* to get alignment/size right */ + SLock *free; + int unused; + slock_t memlock; + SLock slocks[NSLOCKS]; }; -static int SLockMemorySize = sizeof(struct ipcdummy); +static int SLockMemorySize = sizeof(struct ipcdummy); void CreateAndInitSLockMemory(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; + 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(IPCKey key) { - struct ipcdummy *slockM; - - if (SLockMemoryId == -1) - SLockMemoryId = IpcMemoryIdGet(key,SLockMemorySize); - if (SLockMemoryId == -1) - elog(FATAL, "SLockMemory not in shared memory"); - slockM = (struct ipcdummy *) IpcMemoryAttach(SLockMemoryId); - if (slockM == IpcMemAttachFailed) - elog(FATAL, "AttachSLockMemory: could not attach segment"); - FreeSLockPP = (SLock **) &(slockM->free); - UnusedSLockIP = (int *) &(slockM->unused); - SLockMemoryLock = (slock_t *) &(slockM->memlock); - S_INIT_LOCK(SLockMemoryLock); - SLockArray = (SLock *) &(slockM->slocks[0]); - return; + struct ipcdummy *slockM; + + if (SLockMemoryId == -1) + SLockMemoryId = IpcMemoryIdGet(key, SLockMemorySize); + if (SLockMemoryId == -1) + elog(FATAL, "SLockMemory not in shared memory"); + slockM = (struct ipcdummy *) IpcMemoryAttach(SLockMemoryId); + if (slockM == IpcMemAttachFailed) + elog(FATAL, "AttachSLockMemory: could not attach segment"); + FreeSLockPP = (SLock **) & (slockM->free); + UnusedSLockIP = (int *) &(slockM->unused); + SLockMemoryLock = (slock_t *) & (slockM->memlock); + S_INIT_LOCK(SLockMemoryLock); + SLockArray = (SLock *) & (slockM->slocks[0]); + return; } #ifdef LOCKDEBUG #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) + LOCK->flag, LOCK->nshlocks, LOCK->shlock, \ + LOCK->exlock) #endif void ExclusiveLock(int lockid) { - SLock *slckP; - slckP = &(SLockArray[lockid]); + SLock *slckP; + + slckP = &(SLockArray[lockid]); #ifdef LOCKDEBUG - printf("ExclusiveLock(%d)\n", lockid); - printf("IN: "); - PRINT_LOCK(slckP); + printf("ExclusiveLock(%d)\n", 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)); +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); + printf("OUT: "); + PRINT_LOCK(slckP); #endif - return; - case SHAREDLOCK: - case EXCLUSIVELOCK: - S_UNLOCK(&(slckP->locklock)); - S_LOCK(&(slckP->exlock)); - S_UNLOCK(&(slckP->exlock)); - goto ex_try_again; - } + return; + case SHAREDLOCK: + case EXCLUSIVELOCK: + S_UNLOCK(&(slckP->locklock)); + S_LOCK(&(slckP->exlock)); + S_UNLOCK(&(slckP->exlock)); + goto ex_try_again; + } } void ExclusiveUnlock(int lockid) { - SLock *slckP; - - slckP = &(SLockArray[lockid]); + SLock *slckP; + + slckP = &(SLockArray[lockid]); #ifdef LOCKDEBUG - printf("ExclusiveUnlock(%d)\n", lockid); - printf("IN: "); - PRINT_LOCK(slckP); + printf("ExclusiveUnlock(%d)\n", 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_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)); } - S_UNLOCK(&(slckP->shlock)); - } - else { - S_UNLOCK(&(slckP->shlock)); - } - S_UNLOCK(&(slckP->exlock)); - S_UNLOCK(&(slckP->locklock)); + else + { + S_UNLOCK(&(slckP->shlock)); + } + S_UNLOCK(&(slckP->exlock)); + S_UNLOCK(&(slckP->locklock)); #ifdef LOCKDEBUG - printf("OUT: "); - PRINT_LOCK(slckP); + printf("OUT: "); + PRINT_LOCK(slckP); #endif - return; + return; } bool LockIsFree(int lockid) { - return(SLockArray[lockid].flag == NOLOCK); + return (SLockArray[lockid].flag == NOLOCK); } -#endif /* HAS_TEST_AND_SET */ +#endif /* HAS_TEST_AND_SET */ static void IpcConfigTip(void) { - fprintf(stderr,"This type of error is usually caused by improper\n"); - fprintf(stderr,"shared memory or System V IPC semaphore configuration.\n"); - fprintf(stderr,"See the FAQ for more detailed information\n"); + fprintf(stderr, "This type of error is usually caused by improper\n"); + fprintf(stderr, "shared memory or System V IPC semaphore configuration.\n"); + fprintf(stderr, "See the FAQ for more detailed information\n"); } diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index f949041f44d..4aad8e85f54 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * ipci.c-- - * POSTGRES inter-process communication initialization code. + * POSTGRES inter-process communication initialization code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.5 1997/01/08 08:32:03 bryanh Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.6 1997/09/07 04:48:33 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,129 +23,131 @@ #include "storage/proc.h" #include "storage/smgr.h" #include "storage/lock.h" -#include "miscadmin.h" /* for DebugLvl */ +#include "miscadmin.h" /* for DebugLvl */ /* * SystemPortAddressCreateMemoryKey -- - * Returns a memory key given a port address. + * Returns a memory key given a port address. */ IPCKey SystemPortAddressCreateIPCKey(SystemPortAddress address) { - Assert(address < 32768); /* XXX */ - - return (SystemPortAddressGetIPCKey(address)); + Assert(address < 32768); /* XXX */ + + return (SystemPortAddressGetIPCKey(address)); } /* * CreateSharedMemoryAndSemaphores -- - * Creates and initializes shared memory and semaphores. + * Creates and initializes shared memory and semaphores. */ /************************************************** - + CreateSharedMemoryAndSemaphores is called exactly *ONCE* by the postmaster. It is *NEVER* called by the postgres backend - + 0) destroy any existing semaphores for both buffer and lock managers. 1) create the appropriate *SHARED* memory segments for the two resource managers. - + **************************************************/ void CreateSharedMemoryAndSemaphores(IPCKey key) { - int size; - + int size; + #ifdef HAS_TEST_AND_SET - /* --------------- - * create shared memory for slocks - * -------------- - */ - CreateAndInitSLockMemory(IPCKeyGetSLockSharedMemoryKey(key)); + /* --------------- + * create shared memory for slocks + * -------------- + */ + CreateAndInitSLockMemory(IPCKeyGetSLockSharedMemoryKey(key)); #endif - /* ---------------- - * kill and create the buffer manager buffer pool (and semaphore) - * ---------------- - */ - CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key)); - size = BufferShmemSize() + LockShmemSize(); - + /* ---------------- + * kill and create the buffer manager buffer pool (and semaphore) + * ---------------- + */ + CreateSpinlocks(IPCKeyGetSpinLockSemaphoreKey(key)); + size = BufferShmemSize() + LockShmemSize(); + #ifdef MAIN_MEMORY - size += MMShmemSize(); -#endif /* MAIN_MEMORY */ - - if (DebugLvl > 1) { - fprintf(stderr, "binding ShmemCreate(key=%x, size=%d)\n", - IPCKeyGetBufferMemoryKey(key), size); - } - ShmemCreate(IPCKeyGetBufferMemoryKey(key), size); - ShmemBindingTabReset(); - InitShmem(key, size); - InitBufferPool(key); - - /* ---------------- - * do the lock table stuff - * ---------------- - */ - InitLocks(); - InitMultiLevelLockm(); - if (InitMultiLevelLockm() == INVALID_TABLEID) - elog(FATAL, "Couldn't create the lock table"); - - /* ---------------- - * do process table stuff - * ---------------- - */ - InitProcGlobal(key); - on_exitpg(ProcFreeAllSemaphores, 0); - - CreateSharedInvalidationState(key); + size += MMShmemSize(); +#endif /* MAIN_MEMORY */ + + if (DebugLvl > 1) + { + fprintf(stderr, "binding ShmemCreate(key=%x, size=%d)\n", + IPCKeyGetBufferMemoryKey(key), size); + } + ShmemCreate(IPCKeyGetBufferMemoryKey(key), size); + ShmemBindingTabReset(); + InitShmem(key, size); + InitBufferPool(key); + + /* ---------------- + * do the lock table stuff + * ---------------- + */ + InitLocks(); + InitMultiLevelLockm(); + if (InitMultiLevelLockm() == INVALID_TABLEID) + elog(FATAL, "Couldn't create the lock table"); + + /* ---------------- + * do process table stuff + * ---------------- + */ + InitProcGlobal(key); + on_exitpg(ProcFreeAllSemaphores, 0); + + CreateSharedInvalidationState(key); } /* * AttachSharedMemoryAndSemaphores -- - * Attachs existant shared memory and semaphores. + * Attachs existant shared memory and semaphores. */ void AttachSharedMemoryAndSemaphores(IPCKey key) { - int size; - - /* ---------------- - * create rather than attach if using private key - * ---------------- - */ - if (key == PrivateIPCKey) { - CreateSharedMemoryAndSemaphores(key); - return; - } - + int size; + + /* ---------------- + * create rather than attach if using private key + * ---------------- + */ + if (key == PrivateIPCKey) + { + CreateSharedMemoryAndSemaphores(key); + return; + } + #ifdef HAS_TEST_AND_SET - /* ---------------- - * attach the slock shared memory - * ---------------- - */ - AttachSLockMemory(IPCKeyGetSLockSharedMemoryKey(key)); + /* ---------------- + * attach the slock shared memory + * ---------------- + */ + AttachSLockMemory(IPCKeyGetSLockSharedMemoryKey(key)); #endif - /* ---------------- - * attach the buffer manager buffer pool (and semaphore) - * ---------------- - */ - size = BufferShmemSize() + LockShmemSize(); - InitShmem(key, size); - InitBufferPool(key); - - /* ---------------- - * initialize lock table stuff - * ---------------- - */ - InitLocks(); - if (InitMultiLevelLockm() == INVALID_TABLEID) - elog(FATAL, "Couldn't attach to the lock table"); - - AttachSharedInvalidationState(key); + /* ---------------- + * attach the buffer manager buffer pool (and semaphore) + * ---------------- + */ + size = BufferShmemSize() + LockShmemSize(); + InitShmem(key, size); + InitBufferPool(key); + + /* ---------------- + * initialize lock table stuff + * ---------------- + */ + InitLocks(); + if (InitMultiLevelLockm() == INVALID_TABLEID) + elog(FATAL, "Couldn't attach to the lock table"); + + AttachSharedInvalidationState(key); } diff --git a/src/backend/storage/ipc/s_lock.c b/src/backend/storage/ipc/s_lock.c index 146c2d7080a..70f0deb62c9 100644 --- a/src/backend/storage/ipc/s_lock.c +++ b/src/backend/storage/ipc/s_lock.c @@ -1,40 +1,40 @@ /*------------------------------------------------------------------------- * * s_lock.c-- - * This file contains the implementation (if any) for spinlocks. + * This file contains the implementation (if any) for spinlocks. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/s_lock.c,v 1.21 1997/09/05 18:10:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/s_lock.c,v 1.22 1997/09/07 04:48:35 momjian Exp $ * *------------------------------------------------------------------------- */ /* - * DESCRIPTION - * The following code fragment should be written (in assembly - * language) on machines that have a native test-and-set instruction: + * DESCRIPTION + * The following code fragment should be written (in assembly + * language) on machines that have a native test-and-set instruction: * - * void - * S_LOCK(char_address) - * char *char_address; - * { - * while (test_and_set(char_address)) - * ; - * } + * void + * S_LOCK(char_address) + * char *char_address; + * { + * while (test_and_set(char_address)) + * ; + * } * - * If this is not done, POSTGRES will default to using System V - * semaphores (and take a large performance hit -- around 40% of - * its time on a DS5000/240 is spent in semop(3)...). + * If this is not done, POSTGRES will default to using System V + * semaphores (and take a large performance hit -- around 40% of + * its time on a DS5000/240 is spent in semop(3)...). * - * NOTES - * AIX has a test-and-set but the recommended interface is the cs(3) - * system call. This provides an 8-instruction (plus system call - * overhead) uninterruptible compare-and-set operation. True - * spinlocks might be faster but using cs(3) still speeds up the - * regression test suite by about 25%. I don't have an assembler - * manual for POWER in any case. + * NOTES + * AIX has a test-and-set but the recommended interface is the cs(3) + * system call. This provides an 8-instruction (plus system call + * overhead) uninterruptible compare-and-set operation. True + * spinlocks might be faster but using cs(3) still speeds up the + * regression test suite by about 25%. I don't have an assembler + * manual for POWER in any case. * */ #include "postgres.h" @@ -50,71 +50,71 @@ * slock_t is defined as a struct mutex. */ void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { mutex_lock(lock); } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { mutex_unlock(lock); } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - mutex_init(lock); + mutex_init(lock); } /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */ int - S_LOCK_FREE(slock_t *lock) +S_LOCK_FREE(slock_t * lock) { /* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */ - return (lock->lock == 0); + return (lock->lock == 0); } -#endif /* next */ +#endif /* next */ #if defined(irix5) /* * SGI IRIX 5 - * slock_t is defined as a struct abilock_t, which has a single unsigned long + * slock_t is defined as a struct abilock_t, which has a single unsigned long * member. - * + * * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II * assembly from his NECEWS SVR4 port, but we probably ought to retain this * for the R3000 chips out there. */ void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { /* spin_lock(lock); */ while (!acquire_lock(lock)) - ; + ; } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { release_lock(lock); } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - init_lock(lock); + init_lock(lock); } /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */ int -S_LOCK_FREE(slock_t *lock) +S_LOCK_FREE(slock_t * lock) { - return(stat_lock(lock)==UNLOCKED); + return (stat_lock(lock) == UNLOCKED); } -#endif /* irix5 */ +#endif /* irix5 */ /* @@ -127,62 +127,62 @@ S_LOCK_FREE(slock_t *lock) #if defined(__alpha__) || defined(__alpha) void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - while (msem_lock(lock, MSEM_IF_NOWAIT) < 0) - ; + while (msem_lock(lock, MSEM_IF_NOWAIT) < 0) + ; } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - msem_unlock(lock, 0); + msem_unlock(lock, 0); } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - msem_init(lock, MSEM_UNLOCKED); + msem_init(lock, MSEM_UNLOCKED); } int -S_LOCK_FREE(slock_t *lock) +S_LOCK_FREE(slock_t * lock) { - return(lock->msem_state ? 0 : 1); + return (lock->msem_state ? 0 : 1); } -#endif /* alpha */ +#endif /* alpha */ /* * Solaris 2 */ #if defined(i386_solaris) || \ - defined(sparc_solaris) + defined(sparc_solaris) /* for xxxxx_solaris, this is defined in port/.../tas.s */ -static int tas(slock_t *lock); +static int tas(slock_t * lock); void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - while (tas(lock)) - ; + while (tas(lock)) + ; } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = 0; + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } -#endif /* i86pc_solaris || sparc_solaris */ +#endif /* i86pc_solaris || sparc_solaris */ /* * AIX (POWER) @@ -194,25 +194,25 @@ S_INIT_LOCK(slock_t *lock) #if defined(aix) void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - while (cs((int *) lock, 0, 1)) - ; + while (cs((int *) lock, 0, 1)) + ; } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = 0; + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } -#endif /* aix */ +#endif /* aix */ /* * HP-UX (PA-RISC) @@ -224,90 +224,90 @@ S_INIT_LOCK(slock_t *lock) #if defined(hpux) /* -* a "set" slock_t has a single word cleared. a "clear" slock_t has +* a "set" slock_t has a single word cleared. a "clear" slock_t has * all words set to non-zero. */ -static slock_t clear_lock = { -1, -1, -1, -1 }; +static slock_t clear_lock = {-1, -1, -1, -1}; -static int tas(slock_t *lock); +static int tas(slock_t * lock); void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - while (tas(lock)) - ; + while (tas(lock)) + ; } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = clear_lock; /* struct assignment */ + *lock = clear_lock; /* struct assignment */ } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } int -S_LOCK_FREE(slock_t *lock) +S_LOCK_FREE(slock_t * lock) { - register int *lock_word = (int *) (((long) lock + 15) & ~15); + register int *lock_word = (int *) (((long) lock + 15) & ~15); - return(*lock_word != 0); + return (*lock_word != 0); } -#endif /* hpux */ +#endif /* hpux */ /* * sun3 */ - + #if defined(sun3) -static int tas(slock_t *lock); +static int tas(slock_t * lock); -void -S_LOCK(slock_t *lock) +void +S_LOCK(slock_t * lock) { - while (tas(lock)); + while (tas(lock)); } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = 0; + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } static int tas_dummy() { - asm("LLA0:"); - asm(" .data"); - asm(" .text"); - asm("|#PROC# 04"); - asm(" .globl _tas"); - asm("_tas:"); - asm("|#PROLOGUE# 1"); - asm(" movel sp@(0x4),a0"); - asm(" tas a0@"); - asm(" beq LLA1"); - asm(" moveq #-128,d0"); - asm(" rts"); - asm("LLA1:"); - asm(" moveq #0,d0"); - asm(" rts"); - asm(" .data"); -} - -#endif /* sun3 */ + asm("LLA0:"); + asm(" .data"); + asm(" .text"); + asm("|#PROC# 04"); + asm(" .globl _tas"); + asm("_tas:"); + asm("|#PROLOGUE# 1"); + asm(" movel sp@(0x4),a0"); + asm(" tas a0@"); + asm(" beq LLA1"); + asm(" moveq #-128,d0"); + asm(" rts"); + asm("LLA1:"); + asm(" moveq #0,d0"); + asm(" rts"); + asm(" .data"); +} + +#endif /* sun3 */ /* * sparc machines @@ -317,48 +317,48 @@ tas_dummy() /* if we're using -ansi w/ gcc, use __asm__ instead of asm */ #if defined(__STRICT_ANSI__) -#define asm(x) __asm__(x) -#endif +#define asm(x) __asm__(x) +#endif -static int tas(slock_t *lock); +static int tas(slock_t * lock); static int tas_dummy() { - asm(".seg \"data\""); - asm(".seg \"text\""); - asm(".global _tas"); - asm("_tas:"); - - /* - * Sparc atomic test and set (sparc calls it "atomic load-store") - */ - - asm("ldstub [%r8], %r8"); - - /* - * Did test and set actually do the set? - */ - - asm("tst %r8"); - - asm("be,a ReturnZero"); - - /* - * otherwise, just return. - */ - - asm("clr %r8"); - asm("mov 0x1, %r8"); - asm("ReturnZero:"); - asm("retl"); - asm("nop"); + asm(".seg \"data\""); + asm(".seg \"text\""); + asm(".global _tas"); + asm("_tas:"); + + /* + * Sparc atomic test and set (sparc calls it "atomic load-store") + */ + + asm("ldstub [%r8], %r8"); + + /* + * Did test and set actually do the set? + */ + + asm("tst %r8"); + + asm("be,a ReturnZero"); + + /* + * otherwise, just return. + */ + + asm("clr %r8"); + asm("mov 0x1, %r8"); + asm("ReturnZero:"); + asm("retl"); + asm("nop"); } void S_LOCK(unsigned char *addr) { - while (tas(addr)); + while (tas(addr)); } @@ -368,16 +368,16 @@ S_LOCK(unsigned char *addr) void S_UNLOCK(unsigned char *addr) { - *addr = 0; + *addr = 0; } void S_INIT_LOCK(unsigned char *addr) { - *addr = 0; + *addr = 0; } -#endif /* NEED_SPARC_TAS_ASM */ +#endif /* NEED_SPARC_TAS_ASM */ /* * i386 based things @@ -386,39 +386,41 @@ S_INIT_LOCK(unsigned char *addr) #if defined(NEED_I386_TAS_ASM) void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - slock_t res; + slock_t res; - do{ - __asm__("xchgb %0,%1":"=q" (res),"=m" (*lock):"0" (0x1)); - }while(res != 0); + do + { +__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); + } while (res != 0); } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = 0; + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } -#endif /* NEED_I386_TAS_ASM */ +#endif /* NEED_I386_TAS_ASM */ #if defined(__alpha__) && defined(linux) void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - slock_t res; + slock_t res; - do{ - __asm__(" ldq $0, %0 \n\ + do + { +__asm__(" ldq $0, %0 \n\ bne $0, already_set \n\ ldq_l $0, %0 \n\ bne $0, already_set \n\ @@ -430,56 +432,58 @@ S_LOCK(slock_t *lock) jmp $31, end \n\ stqc_fail: or $31, 1, $0 \n\ already_set: bis $0, $0, %1 \n\ - end: nop " : "=m" (*lock), "=r" (res) :: "0" ); - }while(res != 0); + end: nop ": "=m"(*lock), "=r"(res): :"0"); + } while (res != 0); } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - __asm__("mb"); - *lock = 0; + __asm__("mb"); + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } -#endif /* defined(__alpha__) && defined(linux) */ +#endif /* defined(__alpha__) && defined(linux) */ #if defined(linux) && defined(sparc) - + void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - slock_t res; + slock_t res; - do{ - __asm__("ldstub [%1], %0" - : "=&r" (res) - : "r" (lock)); - }while(!res != 0); + do + { + __asm__("ldstub [%1], %0" +: "=&r"(res) +: "r"(lock)); + } while (!res != 0); } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = 0; + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } -#endif /* defined(linux) && defined(sparc) */ +#endif /* defined(linux) && defined(sparc) */ #if defined(linux) && defined(PPC) -static int tas_dummy() +static int +tas_dummy() { __asm__(" \n\ tas: \n\ @@ -496,26 +500,26 @@ success: \n\ blr \n\ "); } - + void -S_LOCK(slock_t *lock) +S_LOCK(slock_t * lock) { - while (tas(lock)) - ; + while (tas(lock)) + ; } void -S_UNLOCK(slock_t *lock) +S_UNLOCK(slock_t * lock) { - *lock = 0; + *lock = 0; } void -S_INIT_LOCK(slock_t *lock) +S_INIT_LOCK(slock_t * lock) { - S_UNLOCK(lock); + S_UNLOCK(lock); } -#endif /* defined(linux) && defined(PPC) */ +#endif /* defined(linux) && defined(PPC) */ -#endif /* HAS_TEST_AND_SET */ +#endif /* HAS_TEST_AND_SET */ diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index c839059ea9b..63848171a1f 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * shmem.c-- - * create shared memory and initialize shared memory data structures. + * create shared memory and initialize shared memory data structures. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.10 1997/08/12 22:53:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.11 1997/09/07 04:48:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,43 +18,43 @@ * allocating and binding to shared memory data structures. * * NOTES: - * (a) There are three kinds of shared memory data structures - * available to POSTGRES: fixed-size structures, queues and hash - * tables. Fixed-size structures contain things like global variables - * for a module and should never be allocated after the process - * initialization phase. Hash tables have a fixed maximum size, but - * their actual size can vary dynamically. When entries are added - * to the table, more space is allocated. Queues link data structures - * that have been allocated either as fixed size structures or as hash - * buckets. Each shared data structure has a string name to identify - * it (assigned in the module that declares it). + * (a) There are three kinds of shared memory data structures + * available to POSTGRES: fixed-size structures, queues and hash + * tables. Fixed-size structures contain things like global variables + * for a module and should never be allocated after the process + * initialization phase. Hash tables have a fixed maximum size, but + * their actual size can vary dynamically. When entries are added + * to the table, more space is allocated. Queues link data structures + * that have been allocated either as fixed size structures or as hash + * buckets. Each shared data structure has a string name to identify + * it (assigned in the module that declares it). * - * (b) During initialization, each module looks for its - * shared data structures in a hash table called the "Binding Table". - * If the data structure is not present, the caller can allocate - * a new one and initialize it. If the data structure is present, - * the caller "attaches" to the structure by initializing a pointer - * in the local address space. - * The binding table has two purposes: first, it gives us - * a simple model of how the world looks when a backend process - * initializes. If something is present in the binding table, - * it is initialized. If it is not, it is uninitialized. Second, - * the binding table allows us to allocate shared memory on demand - * instead of trying to preallocate structures and hard-wire the - * sizes and locations in header files. If you are using a lot - * of shared memory in a lot of different places (and changing - * things during development), this is important. + * (b) During initialization, each module looks for its + * shared data structures in a hash table called the "Binding Table". + * If the data structure is not present, the caller can allocate + * a new one and initialize it. If the data structure is present, + * the caller "attaches" to the structure by initializing a pointer + * in the local address space. + * The binding table has two purposes: first, it gives us + * a simple model of how the world looks when a backend process + * initializes. If something is present in the binding table, + * it is initialized. If it is not, it is uninitialized. Second, + * the binding table allows us to allocate shared memory on demand + * instead of trying to preallocate structures and hard-wire the + * sizes and locations in header files. If you are using a lot + * of shared memory in a lot of different places (and changing + * things during development), this is important. * - * (c) memory allocation model: shared memory can never be - * freed, once allocated. Each hash table has its own free list, - * so hash buckets can be reused when an item is deleted. However, - * if one hash table grows very large and then shrinks, its space - * cannot be redistributed to other tables. We could build a simple - * hash bucket garbage collector if need be. Right now, it seems - * unnecessary. + * (c) memory allocation model: shared memory can never be + * freed, once allocated. Each hash table has its own free list, + * so hash buckets can be reused when an item is deleted. However, + * if one hash table grows very large and then shrinks, its space + * cannot be redistributed to other tables. We could build a simple + * hash bucket garbage collector if need be. Right now, it seems + * unnecessary. * - * See InitSem() in sem.c for an example of how to use the - * binding table. + * See InitSem() in sem.c for an example of how to use the + * binding table. * */ #include <stdio.h> @@ -70,27 +70,23 @@ /* shared memory global variables */ -unsigned long ShmemBase = 0; /* start and end address of - * shared memory - */ -static unsigned long ShmemEnd = 0; -static unsigned long ShmemSize = 0; /* current size (and default) */ +unsigned long ShmemBase = 0; /* start and end address of shared memory */ +static unsigned long ShmemEnd = 0; +static unsigned long ShmemSize = 0; /* current size (and default) */ -SPINLOCK ShmemLock; /* lock for shared memory allocation */ +SPINLOCK ShmemLock; /* lock for shared memory allocation */ -SPINLOCK BindingLock; /* lock for binding table access */ +SPINLOCK BindingLock; /* lock for binding table access */ -static unsigned long *ShmemFreeStart = NULL; /* pointer to the OFFSET of - * first free shared memory - */ -static unsigned long *ShmemBindingTabOffset = NULL; /* start of the binding - * table (for bootstrap) - */ -static int ShmemBootstrap = FALSE; /* flag becomes true when shared mem - * is created by POSTMASTER - */ +static unsigned long *ShmemFreeStart = NULL; /* pointer to the OFFSET + * of first free shared + * memory */ +static unsigned long *ShmemBindingTabOffset = NULL; /* start of the binding + * table (for bootstrap) */ +static int ShmemBootstrap = FALSE; /* flag becomes true when shared + * mem is created by POSTMASTER */ -static HTAB *BindingTable = NULL; +static HTAB *BindingTable = NULL; /* --------------------- * ShmemBindingTabReset() - Resets the binding table to NULL.... @@ -101,16 +97,16 @@ static HTAB *BindingTable = NULL; void ShmemBindingTabReset(void) { - BindingTable = (HTAB *)NULL; + BindingTable = (HTAB *) NULL; } /* - * CreateSharedRegion() -- + * CreateSharedRegion() -- * - * This routine is called once by the postmaster to - * initialize the shared buffer pool. Assume there is - * only one postmaster so no synchronization is necessary - * until after this routine completes successfully. + * This routine is called once by the postmaster to + * initialize the shared buffer pool. Assume there is + * only one postmaster so no synchronization is necessary + * until after this routine completes successfully. * * key is a unique identifier for the shmem region. * size is the size of the region. @@ -120,202 +116,220 @@ static IpcMemoryId ShmemId; void ShmemCreate(unsigned int key, unsigned int size) { - if (size) - ShmemSize = size; - /* create shared mem region */ - if ((ShmemId=IpcMemoryCreate(key,ShmemSize,IPCProtection)) - ==IpcMemCreationFailed) { - elog(FATAL,"ShmemCreate: cannot create region"); - exit(1); - } - - /* ShmemBootstrap is true if shared memory has been - * created, but not yet initialized. Only the - * postmaster/creator-of-all-things should have - * this flag set. - */ - ShmemBootstrap = TRUE; + if (size) + ShmemSize = size; + /* create shared mem region */ + if ((ShmemId = IpcMemoryCreate(key, ShmemSize, IPCProtection)) + == IpcMemCreationFailed) + { + elog(FATAL, "ShmemCreate: cannot create region"); + exit(1); + } + + /* + * ShmemBootstrap is true if shared memory has been created, but not + * yet initialized. Only the postmaster/creator-of-all-things should + * have this flag set. + */ + ShmemBootstrap = TRUE; } /* - * InitShmem() -- map region into process address space - * and initialize shared data structures. + * InitShmem() -- map region into process address space + * and initialize shared data structures. * */ int InitShmem(unsigned int key, unsigned int size) { - Pointer sharedRegion; - unsigned long currFreeSpace; - - HASHCTL info; - int hash_flags; - BindingEnt * result,item; - bool found; - IpcMemoryId shmid; - - /* if zero key, use default memory size */ - if (size) - ShmemSize = size; - - /* default key is 0 */ - - /* attach to shared memory region (SysV or BSD OS specific) */ - if (ShmemBootstrap && key == PrivateIPCKey) - /* if we are running backend alone */ - shmid = ShmemId; - else - shmid = IpcMemoryIdGet(IPCKeyGetBufferMemoryKey(key), ShmemSize); - sharedRegion = IpcMemoryAttach(shmid); - if (sharedRegion == NULL) { - elog(FATAL,"AttachSharedRegion: couldn't attach to shmem\n"); - return(FALSE); - } - - /* get pointers to the dimensions of shared memory */ - ShmemBase = (unsigned long) sharedRegion; - ShmemEnd = (unsigned long) sharedRegion + ShmemSize; - currFreeSpace = 0; - - /* First long in shared memory is the count of available space */ - ShmemFreeStart = (unsigned long *) ShmemBase; - /* next is a shmem pointer to the binding table */ - ShmemBindingTabOffset = ShmemFreeStart + 1; - - currFreeSpace += - sizeof(ShmemFreeStart) + sizeof(ShmemBindingTabOffset); - - /* bootstrap initialize spin locks so we can start to use the - * allocator and binding table. - */ - if (! InitSpinLocks(ShmemBootstrap, IPCKeyGetSpinLockSemaphoreKey(key))) { - return(FALSE); - } - - /* We have just allocated additional space for two spinlocks. - * Now setup the global free space count - */ - if (ShmemBootstrap) { - *ShmemFreeStart = currFreeSpace; - } - - /* if ShmemFreeStart is NULL, then the allocator won't work */ - Assert(*ShmemFreeStart); - - /* create OR attach to the shared memory binding table */ - info.keysize = BTABLE_KEYSIZE; - info.datasize = BTABLE_DATASIZE; - hash_flags = (HASH_ELEM); - - /* This will acquire the binding table lock, but not release it. */ - BindingTable = ShmemInitHash("BindingTable", - BTABLE_SIZE,BTABLE_SIZE, - &info,hash_flags); - - if (! BindingTable) { - elog(FATAL,"InitShmem: couldn't initialize Binding Table"); - return(FALSE); - } - - /* Now, check the binding table for an entry to the binding - * table. If there is an entry there, someone else created - * the table. Otherwise, we did and we have to initialize it. - */ - memset(item.key, 0, BTABLE_KEYSIZE); - strncpy(item.key,"BindingTable",BTABLE_KEYSIZE); - - result = (BindingEnt *) - hash_search(BindingTable,(char *) &item,HASH_ENTER, &found); - - - if (! result ) { - elog(FATAL,"InitShmem: corrupted binding table"); - return(FALSE); - } - - if (! found) { - /* bootstrapping shmem: we have to initialize the - * binding table now. + Pointer sharedRegion; + unsigned long currFreeSpace; + + HASHCTL info; + int hash_flags; + BindingEnt *result, + item; + bool found; + IpcMemoryId shmid; + + /* if zero key, use default memory size */ + if (size) + ShmemSize = size; + + /* default key is 0 */ + + /* attach to shared memory region (SysV or BSD OS specific) */ + if (ShmemBootstrap && key == PrivateIPCKey) + /* if we are running backend alone */ + shmid = ShmemId; + else + shmid = IpcMemoryIdGet(IPCKeyGetBufferMemoryKey(key), ShmemSize); + sharedRegion = IpcMemoryAttach(shmid); + if (sharedRegion == NULL) + { + elog(FATAL, "AttachSharedRegion: couldn't attach to shmem\n"); + return (FALSE); + } + + /* get pointers to the dimensions of shared memory */ + ShmemBase = (unsigned long) sharedRegion; + ShmemEnd = (unsigned long) sharedRegion + ShmemSize; + currFreeSpace = 0; + + /* First long in shared memory is the count of available space */ + ShmemFreeStart = (unsigned long *) ShmemBase; + /* next is a shmem pointer to the binding table */ + ShmemBindingTabOffset = ShmemFreeStart + 1; + + currFreeSpace += + sizeof(ShmemFreeStart) + sizeof(ShmemBindingTabOffset); + + /* + * bootstrap initialize spin locks so we can start to use the + * allocator and binding table. */ - - Assert(ShmemBootstrap); - result->location = MAKE_OFFSET(BindingTable->hctl); - *ShmemBindingTabOffset = result->location; - result->size = BTABLE_SIZE; - - ShmemBootstrap = FALSE; - - } else { - Assert(! ShmemBootstrap); - } - /* now release the lock acquired in ShmemHashInit */ - SpinRelease (BindingLock); - - Assert (result->location == MAKE_OFFSET(BindingTable->hctl)); - - return(TRUE); + if (!InitSpinLocks(ShmemBootstrap, IPCKeyGetSpinLockSemaphoreKey(key))) + { + return (FALSE); + } + + /* + * We have just allocated additional space for two spinlocks. Now + * setup the global free space count + */ + if (ShmemBootstrap) + { + *ShmemFreeStart = currFreeSpace; + } + + /* if ShmemFreeStart is NULL, then the allocator won't work */ + Assert(*ShmemFreeStart); + + /* create OR attach to the shared memory binding table */ + info.keysize = BTABLE_KEYSIZE; + info.datasize = BTABLE_DATASIZE; + hash_flags = (HASH_ELEM); + + /* This will acquire the binding table lock, but not release it. */ + BindingTable = ShmemInitHash("BindingTable", + BTABLE_SIZE, BTABLE_SIZE, + &info, hash_flags); + + if (!BindingTable) + { + elog(FATAL, "InitShmem: couldn't initialize Binding Table"); + return (FALSE); + } + + /* + * Now, check the binding table for an entry to the binding table. If + * there is an entry there, someone else created the table. + * Otherwise, we did and we have to initialize it. + */ + memset(item.key, 0, BTABLE_KEYSIZE); + strncpy(item.key, "BindingTable", BTABLE_KEYSIZE); + + result = (BindingEnt *) + hash_search(BindingTable, (char *) &item, HASH_ENTER, &found); + + + if (!result) + { + elog(FATAL, "InitShmem: corrupted binding table"); + return (FALSE); + } + + if (!found) + { + + /* + * bootstrapping shmem: we have to initialize the binding table + * now. + */ + + Assert(ShmemBootstrap); + result->location = MAKE_OFFSET(BindingTable->hctl); + *ShmemBindingTabOffset = result->location; + result->size = BTABLE_SIZE; + + ShmemBootstrap = FALSE; + + } + else + { + Assert(!ShmemBootstrap); + } + /* now release the lock acquired in ShmemHashInit */ + SpinRelease(BindingLock); + + Assert(result->location == MAKE_OFFSET(BindingTable->hctl)); + + return (TRUE); } /* * ShmemAlloc -- allocate word-aligned byte string from - * shared memory + * shared memory * * Assumes ShmemLock and ShmemFreeStart are initialized. * Returns: real pointer to memory or NULL if we are out - * of space. Has to return a real pointer in order - * to be compatable with malloc(). + * of space. Has to return a real pointer in order + * to be compatable with malloc(). */ -long * +long * ShmemAlloc(unsigned long size) { - unsigned long tmpFree; - long *newSpace; - - /* - * ensure space is word aligned. - * - * Word-alignment is not good enough. We have to be more - * conservative: doubles need 8-byte alignment. (We probably only need - * this on RISC platforms but this is not a big waste of space.) - * - ay 12/94 - */ - if (size % sizeof(double)) - size += sizeof(double) - (size % sizeof(double)); - - Assert(*ShmemFreeStart); - - SpinAcquire(ShmemLock); - - tmpFree = *ShmemFreeStart + size; - if (tmpFree <= ShmemSize) { - newSpace = (long *)MAKE_PTR(*ShmemFreeStart); - *ShmemFreeStart += size; - } else { - newSpace = NULL; - } - - SpinRelease(ShmemLock); - - if (! newSpace) { - elog(NOTICE,"ShmemAlloc: out of memory "); - } - return(newSpace); + unsigned long tmpFree; + long *newSpace; + + /* + * ensure space is word aligned. + * + * Word-alignment is not good enough. We have to be more conservative: + * doubles need 8-byte alignment. (We probably only need this on RISC + * platforms but this is not a big waste of space.) - ay 12/94 + */ + if (size % sizeof(double)) + size += sizeof(double) - (size % sizeof(double)); + + Assert(*ShmemFreeStart); + + SpinAcquire(ShmemLock); + + tmpFree = *ShmemFreeStart + size; + if (tmpFree <= ShmemSize) + { + newSpace = (long *) MAKE_PTR(*ShmemFreeStart); + *ShmemFreeStart += size; + } + else + { + newSpace = NULL; + } + + SpinRelease(ShmemLock); + + if (!newSpace) + { + elog(NOTICE, "ShmemAlloc: out of memory "); + } + return (newSpace); } /* - * ShmemIsValid -- test if an offset refers to valid shared memory - * + * ShmemIsValid -- test if an offset refers to valid shared memory + * * Returns TRUE if the pointer is valid. */ int ShmemIsValid(unsigned long addr) { - return ((addr<ShmemEnd) && (addr>=ShmemBase)); + return ((addr < ShmemEnd) && (addr >= ShmemBase)); } /* - * ShmemInitHash -- Create/Attach to and initialize - * shared memory hash table. + * ShmemInitHash -- Create/Attach to and initialize + * shared memory hash table. * * Notes: * @@ -324,281 +338,308 @@ ShmemIsValid(unsigned long addr) * table at once. Use SpinAlloc() to create a spinlock * for the structure before creating the structure itself. */ -HTAB * -ShmemInitHash(char *name, /* table string name for binding */ - long init_size, /* initial size */ - long max_size, /* max size of the table */ - HASHCTL *infoP, /* info about key and bucket size */ - int hash_flags) /* info about infoP */ +HTAB * +ShmemInitHash(char *name, /* table string name for binding */ + long init_size, /* initial size */ + long max_size, /* max size of the table */ + HASHCTL * infoP, /* info about key and bucket size */ + int hash_flags) /* info about infoP */ { - bool found; - long * location; - - /* shared memory hash tables have a fixed max size so that the - * control structures don't try to grow. The segbase is for - * calculating pointer values. The shared memory allocator - * must be specified. - */ - infoP->segbase = (long *) ShmemBase; - infoP->alloc = ShmemAlloc; - infoP->max_size = max_size; - hash_flags |= HASH_SHARED_MEM; - - /* look it up in the binding table */ - location = - ShmemInitStruct(name,my_log2(max_size) + sizeof(HHDR),&found); - - /* binding table is corrupted. Let someone else give the - * error message since they have more information - */ - if (location == NULL) { - return(0); - } - - /* it already exists, attach to it rather than allocate and - * initialize new space - */ - if (found) { - hash_flags |= HASH_ATTACH; - } - - /* these structures were allocated or bound in ShmemInitStruct */ - /* control information and parameters */ - infoP->hctl = (long *) location; - /* directory for hash lookup */ - infoP->dir = (long *) (location + sizeof(HHDR)); - - return(hash_create(init_size, infoP, hash_flags));; + bool found; + long *location; + + /* + * shared memory hash tables have a fixed max size so that the control + * structures don't try to grow. The segbase is for calculating + * pointer values. The shared memory allocator must be specified. + */ + infoP->segbase = (long *) ShmemBase; + infoP->alloc = ShmemAlloc; + infoP->max_size = max_size; + hash_flags |= HASH_SHARED_MEM; + + /* look it up in the binding table */ + location = + ShmemInitStruct(name, my_log2(max_size) + sizeof(HHDR), &found); + + /* + * binding table is corrupted. Let someone else give the error + * message since they have more information + */ + if (location == NULL) + { + return (0); + } + + /* + * it already exists, attach to it rather than allocate and initialize + * new space + */ + if (found) + { + hash_flags |= HASH_ATTACH; + } + + /* these structures were allocated or bound in ShmemInitStruct */ + /* control information and parameters */ + infoP->hctl = (long *) location; + /* directory for hash lookup */ + infoP->dir = (long *) (location + sizeof(HHDR)); + + return (hash_create(init_size, infoP, hash_flags));; } /* * ShmemPIDLookup -- lookup process data structure using process id * * Returns: TRUE if no error. locationPtr is initialized if PID is - * found in the binding table. + * found in the binding table. * * NOTES: - * only information about success or failure is the value of - * locationPtr. + * only information about success or failure is the value of + * locationPtr. */ bool -ShmemPIDLookup(int pid, SHMEM_OFFSET* locationPtr) +ShmemPIDLookup(int pid, SHMEM_OFFSET * locationPtr) { - BindingEnt * result,item; - bool found; - - Assert (BindingTable); - memset(item.key, 0, BTABLE_KEYSIZE); - sprintf(item.key,"PID %d",pid); - - SpinAcquire(BindingLock); - result = (BindingEnt *) - hash_search(BindingTable,(char *) &item, HASH_ENTER, &found); - - if (! result) { - + BindingEnt *result, + item; + bool found; + + Assert(BindingTable); + memset(item.key, 0, BTABLE_KEYSIZE); + sprintf(item.key, "PID %d", pid); + + SpinAcquire(BindingLock); + result = (BindingEnt *) + hash_search(BindingTable, (char *) &item, HASH_ENTER, &found); + + if (!result) + { + + SpinRelease(BindingLock); + elog(WARN, "ShmemInitPID: BindingTable corrupted"); + return (FALSE); + + } + + if (found) + { + *locationPtr = result->location; + } + else + { + result->location = *locationPtr; + } + SpinRelease(BindingLock); - elog(WARN,"ShmemInitPID: BindingTable corrupted"); - return(FALSE); - - } - - if (found) { - *locationPtr = result->location; - } else { - result->location = *locationPtr; - } - - SpinRelease(BindingLock); - return (TRUE); + return (TRUE); } /* * ShmemPIDDestroy -- destroy binding table entry for process - * using process id + * using process id * * Returns: offset of the process struct in shared memory or - * INVALID_OFFSET if not found. + * INVALID_OFFSET if not found. * * Side Effect: removes the entry from the binding table */ SHMEM_OFFSET ShmemPIDDestroy(int pid) { - BindingEnt * result,item; - bool found; - SHMEM_OFFSET location = 0; - - Assert(BindingTable); - - memset(item.key, 0, BTABLE_KEYSIZE); - sprintf(item.key,"PID %d",pid); - - SpinAcquire(BindingLock); - result = (BindingEnt *) - hash_search(BindingTable,(char *) &item, HASH_REMOVE, &found); - - if (found) - location = result->location; - SpinRelease(BindingLock); - - if (! result) { - - elog(WARN,"ShmemPIDDestroy: PID table corrupted"); - return(INVALID_OFFSET); - - } - - if (found) - return (location); - else { - return(INVALID_OFFSET); - } + BindingEnt *result, + item; + bool found; + SHMEM_OFFSET location = 0; + + Assert(BindingTable); + + memset(item.key, 0, BTABLE_KEYSIZE); + sprintf(item.key, "PID %d", pid); + + SpinAcquire(BindingLock); + result = (BindingEnt *) + hash_search(BindingTable, (char *) &item, HASH_REMOVE, &found); + + if (found) + location = result->location; + SpinRelease(BindingLock); + + if (!result) + { + + elog(WARN, "ShmemPIDDestroy: PID table corrupted"); + return (INVALID_OFFSET); + + } + + if (found) + return (location); + else + { + return (INVALID_OFFSET); + } } /* * ShmemInitStruct -- Create/attach to a structure in shared - * memory. + * memory. * - * This is called during initialization to find or allocate - * a data structure in shared memory. If no other processes - * have created the structure, this routine allocates space - * for it. If it exists already, a pointer to the existing - * table is returned. + * This is called during initialization to find or allocate + * a data structure in shared memory. If no other processes + * have created the structure, this routine allocates space + * for it. If it exists already, a pointer to the existing + * table is returned. * - * Returns: real pointer to the object. FoundPtr is TRUE if - * the object is already in the binding table (hence, already - * initialized). + * Returns: real pointer to the object. FoundPtr is TRUE if + * the object is already in the binding table (hence, already + * initialized). */ -long * -ShmemInitStruct(char *name, unsigned long size, bool *foundPtr) +long * +ShmemInitStruct(char *name, unsigned long size, bool * foundPtr) { - BindingEnt * result,item; - long * structPtr; - - strncpy(item.key,name,BTABLE_KEYSIZE); - item.location = BAD_LOCATION; - - SpinAcquire(BindingLock); - - if (! BindingTable) { - /* Assert() is a macro now. substitutes inside quotes. */ -#ifndef NO_ASSERT_CHECKING - char *strname = "BindingTable"; + BindingEnt *result, + item; + long *structPtr; + + strncpy(item.key, name, BTABLE_KEYSIZE); + item.location = BAD_LOCATION; + + SpinAcquire(BindingLock); + + if (!BindingTable) + { + /* Assert() is a macro now. substitutes inside quotes. */ +#ifndef NO_ASSERT_CHECKING + char *strname = "BindingTable"; + #endif - - /* If the binding table doesnt exist, we fake it. - * - * If we are creating the first binding table, then let - * shmemalloc() allocate the space for a new HTAB. Otherwise, - * find the old one and return that. Notice that the - * BindingLock is held until the binding table has been completely - * initialized. - */ - Assert (! strcmp(name,strname)) ; - if (ShmemBootstrap) { - /* in POSTMASTER/Single process */ - - *foundPtr = FALSE; - return((long *)ShmemAlloc(size)); - - } else { - Assert (ShmemBindingTabOffset); - - *foundPtr = TRUE; - return((long *)MAKE_PTR(*ShmemBindingTabOffset)); + + /* + * If the binding table doesnt exist, we fake it. + * + * If we are creating the first binding table, then let shmemalloc() + * allocate the space for a new HTAB. Otherwise, find the old one + * and return that. Notice that the BindingLock is held until the + * binding table has been completely initialized. + */ + Assert(!strcmp(name, strname)); + if (ShmemBootstrap) + { + /* in POSTMASTER/Single process */ + + *foundPtr = FALSE; + return ((long *) ShmemAlloc(size)); + + } + else + { + Assert(ShmemBindingTabOffset); + + *foundPtr = TRUE; + return ((long *) MAKE_PTR(*ShmemBindingTabOffset)); + } + + } - - - } else { - /* look it up in the bindint table */ - result = (BindingEnt *) - hash_search(BindingTable,(char *) &item,HASH_ENTER, foundPtr); - } - - if (! result) { - - SpinRelease(BindingLock); - - elog(WARN,"ShmemInitStruct: Binding Table corrupted"); - return(NULL); - - } else if (*foundPtr) { - /* - * Structure is in the binding table so someone else has allocated - * it already. The size better be the same as the size we are - * trying to initialize to or there is a name conflict (or worse). - */ - if (result->size != size) { - SpinRelease(BindingLock); - - elog(NOTICE,"ShmemInitStruct: BindingTable entry size is wrong"); - /* let caller print its message too */ - return(NULL); + else + { + /* look it up in the bindint table */ + result = (BindingEnt *) + hash_search(BindingTable, (char *) &item, HASH_ENTER, foundPtr); + } + + if (!result) + { + + SpinRelease(BindingLock); + + elog(WARN, "ShmemInitStruct: Binding Table corrupted"); + return (NULL); + } - structPtr = (long *)MAKE_PTR(result->location); - } else { - - /* It isn't in the table yet. allocate and initialize it */ - structPtr = ShmemAlloc((long)size); - if (! structPtr) { - /* out of memory */ - Assert (BindingTable); - hash_search(BindingTable,(char *) &item,HASH_REMOVE, foundPtr); - SpinRelease(BindingLock); - *foundPtr = FALSE; - - elog(NOTICE,"ShmemInitStruct: cannot allocate '%s'", - name); - return(NULL); - } - result->size = size; - result->location = MAKE_OFFSET(structPtr); - } - Assert (ShmemIsValid((unsigned long)structPtr)); - - SpinRelease(BindingLock); - return(structPtr); + else if (*foundPtr) + { + + /* + * Structure is in the binding table so someone else has allocated + * it already. The size better be the same as the size we are + * trying to initialize to or there is a name conflict (or worse). + */ + if (result->size != size) + { + SpinRelease(BindingLock); + + elog(NOTICE, "ShmemInitStruct: BindingTable entry size is wrong"); + /* let caller print its message too */ + return (NULL); + } + structPtr = (long *) MAKE_PTR(result->location); + } + else + { + + /* It isn't in the table yet. allocate and initialize it */ + structPtr = ShmemAlloc((long) size); + if (!structPtr) + { + /* out of memory */ + Assert(BindingTable); + hash_search(BindingTable, (char *) &item, HASH_REMOVE, foundPtr); + SpinRelease(BindingLock); + *foundPtr = FALSE; + + elog(NOTICE, "ShmemInitStruct: cannot allocate '%s'", + name); + return (NULL); + } + result->size = size; + result->location = MAKE_OFFSET(structPtr); + } + Assert(ShmemIsValid((unsigned long) structPtr)); + + SpinRelease(BindingLock); + return (structPtr); } /* * TransactionIdIsInProgress -- is given transaction running by some backend * - * Strange place for this func, but we have to lookup process data structures + * Strange place for this func, but we have to lookup process data structures * for all running backends. - vadim 11/26/96 */ bool -TransactionIdIsInProgress (TransactionId xid) +TransactionIdIsInProgress(TransactionId xid) { - BindingEnt *result; - PROC *proc; - - Assert (BindingTable); - - SpinAcquire(BindingLock); - - hash_seq ((HTAB *)NULL); - while ( (result = (BindingEnt *) hash_seq (BindingTable)) != NULL ) - { - if ( result == (BindingEnt *) TRUE ) - { - SpinRelease(BindingLock); - return (false); - } - if ( result->location == INVALID_OFFSET || - strncmp (result->key, "PID ", 4) != 0 ) - continue; - proc = (PROC *) MAKE_PTR (result->location); - if ( proc->xid == xid ) - { - SpinRelease(BindingLock); - return (true); + BindingEnt *result; + PROC *proc; + + Assert(BindingTable); + + SpinAcquire(BindingLock); + + hash_seq((HTAB *) NULL); + while ((result = (BindingEnt *) hash_seq(BindingTable)) != NULL) + { + if (result == (BindingEnt *) TRUE) + { + SpinRelease(BindingLock); + return (false); + } + if (result->location == INVALID_OFFSET || + strncmp(result->key, "PID ", 4) != 0) + continue; + proc = (PROC *) MAKE_PTR(result->location); + if (proc->xid == xid) + { + SpinRelease(BindingLock); + return (true); + } } - } - - SpinRelease(BindingLock); - elog (WARN,"TransactionIdIsInProgress: BindingTable corrupted"); - return (false); -} + SpinRelease(BindingLock); + elog(WARN, "TransactionIdIsInProgress: BindingTable corrupted"); + return (false); +} diff --git a/src/backend/storage/ipc/shmqueue.c b/src/backend/storage/ipc/shmqueue.c index f727b5719f5..8080fc70208 100644 --- a/src/backend/storage/ipc/shmqueue.c +++ b/src/backend/storage/ipc/shmqueue.c @@ -1,19 +1,19 @@ /*------------------------------------------------------------------------- * * shmqueue.c-- - * shared memory linked lists + * shared memory linked lists * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmqueue.c,v 1.3 1997/08/19 21:33:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmqueue.c,v 1.4 1997/09/07 04:48:42 momjian Exp $ * * NOTES * * Package for managing doubly-linked lists in shared memory. - * The only tricky thing is that SHM_QUEUE will usually be a field - * in a larger record. SHMQueueGetFirst has to return a pointer + * The only tricky thing is that SHM_QUEUE will usually be a field + * in a larger record. SHMQueueGetFirst has to return a pointer * to the record itself instead of a pointer to the SHMQueue field * of the record. It takes an extra pointer and does some extra * pointer arithmetic to do this correctly. @@ -22,178 +22,181 @@ * *------------------------------------------------------------------------- */ -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include "postgres.h" -#include "storage/shmem.h" /* where the declarations go */ +#include "storage/shmem.h" /* where the declarations go */ /*#define SHMQUEUE_DEBUG*/ #ifdef SHMQUEUE_DEBUG -#define SHMQUEUE_DEBUG_DEL /* deletions */ -#define SHMQUEUE_DEBUG_HD /* head inserts */ -#define SHMQUEUE_DEBUG_TL /* tail inserts */ +#define SHMQUEUE_DEBUG_DEL /* deletions */ +#define SHMQUEUE_DEBUG_HD /* head inserts */ +#define SHMQUEUE_DEBUG_TL /* tail inserts */ #define SHMQUEUE_DEBUG_ELOG NOTICE -#endif /* SHMQUEUE_DEBUG */ +#endif /* SHMQUEUE_DEBUG */ /* * ShmemQueueInit -- make the head of a new queue point - * to itself + * to itself */ void -SHMQueueInit(SHM_QUEUE *queue) +SHMQueueInit(SHM_QUEUE * queue) { - Assert(SHM_PTR_VALID(queue)); - (queue)->prev = (queue)->next = MAKE_OFFSET(queue); + Assert(SHM_PTR_VALID(queue)); + (queue)->prev = (queue)->next = MAKE_OFFSET(queue); } /* * SHMQueueIsDetached -- TRUE if element is not currently - * in a queue. + * in a queue. */ #ifdef NOT_USED bool -SHMQueueIsDetached(SHM_QUEUE *queue) +SHMQueueIsDetached(SHM_QUEUE * queue) { - Assert(SHM_PTR_VALID(queue)); - return ((queue)->prev == INVALID_OFFSET); + Assert(SHM_PTR_VALID(queue)); + return ((queue)->prev == INVALID_OFFSET); } + #endif /* * SHMQueueElemInit -- clear an element's links */ void -SHMQueueElemInit(SHM_QUEUE *queue) +SHMQueueElemInit(SHM_QUEUE * queue) { - Assert(SHM_PTR_VALID(queue)); - (queue)->prev = (queue)->next = INVALID_OFFSET; + Assert(SHM_PTR_VALID(queue)); + (queue)->prev = (queue)->next = INVALID_OFFSET; } /* * SHMQueueDelete -- remove an element from the queue and - * close the links + * close the links */ void -SHMQueueDelete(SHM_QUEUE *queue) +SHMQueueDelete(SHM_QUEUE * queue) { - SHM_QUEUE *nextElem = (SHM_QUEUE *) MAKE_PTR((queue)->next); - SHM_QUEUE *prevElem = (SHM_QUEUE *) MAKE_PTR((queue)->prev); - - Assert(SHM_PTR_VALID(queue)); - Assert(SHM_PTR_VALID(nextElem)); - Assert(SHM_PTR_VALID(prevElem)); - + SHM_QUEUE *nextElem = (SHM_QUEUE *) MAKE_PTR((queue)->next); + SHM_QUEUE *prevElem = (SHM_QUEUE *) MAKE_PTR((queue)->prev); + + Assert(SHM_PTR_VALID(queue)); + Assert(SHM_PTR_VALID(nextElem)); + Assert(SHM_PTR_VALID(prevElem)); + #ifdef SHMQUEUE_DEBUG_DEL - dumpQ(queue, "in SHMQueueDelete: begin"); -#endif /* SHMQUEUE_DEBUG_DEL */ - - prevElem->next = (queue)->next; - nextElem->prev = (queue)->prev; - + dumpQ(queue, "in SHMQueueDelete: begin"); +#endif /* SHMQUEUE_DEBUG_DEL */ + + prevElem->next = (queue)->next; + nextElem->prev = (queue)->prev; + #ifdef SHMQUEUE_DEBUG_DEL - dumpQ((SHM_QUEUE *)MAKE_PTR(queue->prev), "in SHMQueueDelete: end"); -#endif /* SHMQUEUE_DEBUG_DEL */ + dumpQ((SHM_QUEUE *) MAKE_PTR(queue->prev), "in SHMQueueDelete: end"); +#endif /* SHMQUEUE_DEBUG_DEL */ } #ifdef SHMQUEUE_DEBUG void -dumpQ(SHM_QUEUE *q, char *s) +dumpQ(SHM_QUEUE * q, char *s) { - char elem[16]; - char buf[1024]; - SHM_QUEUE *start = q; - int count = 0; - - sprintf(buf, "q prevs: %x", MAKE_OFFSET(q)); - q = (SHM_QUEUE *)MAKE_PTR(q->prev); - while (q != start) + char elem[16]; + char buf[1024]; + SHM_QUEUE *start = q; + int count = 0; + + sprintf(buf, "q prevs: %x", MAKE_OFFSET(q)); + q = (SHM_QUEUE *) MAKE_PTR(q->prev); + while (q != start) { - sprintf(elem, "--->%x", MAKE_OFFSET(q)); - strcat(buf, elem); - q = (SHM_QUEUE *)MAKE_PTR(q->prev); - if (q->prev == MAKE_OFFSET(q)) - break; - if (count++ > 40) + sprintf(elem, "--->%x", MAKE_OFFSET(q)); + strcat(buf, elem); + q = (SHM_QUEUE *) MAKE_PTR(q->prev); + if (q->prev == MAKE_OFFSET(q)) + break; + if (count++ > 40) { - strcat(buf, "BAD PREV QUEUE!!"); - break; + strcat(buf, "BAD PREV QUEUE!!"); + break; } } - sprintf(elem, "--->%x", MAKE_OFFSET(q)); - strcat(buf, elem); - elog(SHMQUEUE_DEBUG_ELOG, "%s: %s", s, buf); - - sprintf(buf, "q nexts: %x", MAKE_OFFSET(q)); - count = 0; - q = (SHM_QUEUE *)MAKE_PTR(q->next); - while (q != start) + sprintf(elem, "--->%x", MAKE_OFFSET(q)); + strcat(buf, elem); + elog(SHMQUEUE_DEBUG_ELOG, "%s: %s", s, buf); + + sprintf(buf, "q nexts: %x", MAKE_OFFSET(q)); + count = 0; + q = (SHM_QUEUE *) MAKE_PTR(q->next); + while (q != start) { - sprintf(elem, "--->%x", MAKE_OFFSET(q)); - strcat(buf, elem); - q = (SHM_QUEUE *)MAKE_PTR(q->next); - if (q->next == MAKE_OFFSET(q)) - break; - if (count++ > 10) + sprintf(elem, "--->%x", MAKE_OFFSET(q)); + strcat(buf, elem); + q = (SHM_QUEUE *) MAKE_PTR(q->next); + if (q->next == MAKE_OFFSET(q)) + break; + if (count++ > 10) { - strcat(buf, "BAD NEXT QUEUE!!"); - break; + strcat(buf, "BAD NEXT QUEUE!!"); + break; } } - sprintf(elem, "--->%x", MAKE_OFFSET(q)); - strcat(buf, elem); - elog(SHMQUEUE_DEBUG_ELOG, "%s: %s", s, buf); + sprintf(elem, "--->%x", MAKE_OFFSET(q)); + strcat(buf, elem); + elog(SHMQUEUE_DEBUG_ELOG, "%s: %s", s, buf); } -#endif /* SHMQUEUE_DEBUG */ + +#endif /* SHMQUEUE_DEBUG */ /* * SHMQueueInsertHD -- put elem in queue between the queue head - * and its "prev" element. + * and its "prev" element. */ #ifdef NOT_USED void -SHMQueueInsertHD(SHM_QUEUE *queue, SHM_QUEUE *elem) +SHMQueueInsertHD(SHM_QUEUE * queue, SHM_QUEUE * elem) { - SHM_QUEUE *prevPtr = (SHM_QUEUE *) MAKE_PTR((queue)->prev); - SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem); - - Assert(SHM_PTR_VALID(queue)); - Assert(SHM_PTR_VALID(elem)); - + SHM_QUEUE *prevPtr = (SHM_QUEUE *) MAKE_PTR((queue)->prev); + SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem); + + Assert(SHM_PTR_VALID(queue)); + Assert(SHM_PTR_VALID(elem)); + #ifdef SHMQUEUE_DEBUG_HD - dumpQ(queue, "in SHMQueueInsertHD: begin"); -#endif /* SHMQUEUE_DEBUG_HD */ - - (elem)->next = prevPtr->next; - (elem)->prev = queue->prev; - (queue)->prev = elemOffset; - prevPtr->next = elemOffset; - + dumpQ(queue, "in SHMQueueInsertHD: begin"); +#endif /* SHMQUEUE_DEBUG_HD */ + + (elem)->next = prevPtr->next; + (elem)->prev = queue->prev; + (queue)->prev = elemOffset; + prevPtr->next = elemOffset; + #ifdef SHMQUEUE_DEBUG_HD - dumpQ(queue, "in SHMQueueInsertHD: end"); -#endif /* SHMQUEUE_DEBUG_HD */ + dumpQ(queue, "in SHMQueueInsertHD: end"); +#endif /* SHMQUEUE_DEBUG_HD */ } + #endif void -SHMQueueInsertTL(SHM_QUEUE *queue, SHM_QUEUE *elem) +SHMQueueInsertTL(SHM_QUEUE * queue, SHM_QUEUE * elem) { - SHM_QUEUE *nextPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next); - SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem); - - Assert(SHM_PTR_VALID(queue)); - Assert(SHM_PTR_VALID(elem)); - + SHM_QUEUE *nextPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next); + SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem); + + Assert(SHM_PTR_VALID(queue)); + Assert(SHM_PTR_VALID(elem)); + #ifdef SHMQUEUE_DEBUG_TL - dumpQ(queue, "in SHMQueueInsertTL: begin"); -#endif /* SHMQUEUE_DEBUG_TL */ - - (elem)->prev = nextPtr->prev; - (elem)->next = queue->next; - (queue)->next = elemOffset; - nextPtr->prev = elemOffset; - + dumpQ(queue, "in SHMQueueInsertTL: begin"); +#endif /* SHMQUEUE_DEBUG_TL */ + + (elem)->prev = nextPtr->prev; + (elem)->next = queue->next; + (queue)->next = elemOffset; + nextPtr->prev = elemOffset; + #ifdef SHMQUEUE_DEBUG_TL - dumpQ(queue, "in SHMQueueInsertTL: end"); -#endif /* SHMQUEUE_DEBUG_TL */ + dumpQ(queue, "in SHMQueueInsertTL: end"); +#endif /* SHMQUEUE_DEBUG_TL */ } /* @@ -203,52 +206,51 @@ SHMQueueInsertTL(SHM_QUEUE *queue, SHM_QUEUE *elem) * a larger structure, we want to return a pointer to the * whole structure rather than a pointer to its SHMQueue field. * I.E. struct { - * int stuff; - * SHMQueue elem; - * } ELEMType; + * int stuff; + * SHMQueue elem; + * } ELEMType; * when this element is in a queue (queue->next) is struct.elem. * nextQueue allows us to calculate the offset of the SHMQueue * field in the structure. * * call to SHMQueueFirst should take these parameters: * - * &(queueHead),&firstElem,&(firstElem->next) + * &(queueHead),&firstElem,&(firstElem->next) * * Note that firstElem may well be uninitialized. if firstElem * is initially K, &(firstElem->next) will be K+ the offset to * next. */ void -SHMQueueFirst(SHM_QUEUE *queue, Pointer *nextPtrPtr, SHM_QUEUE *nextQueue) +SHMQueueFirst(SHM_QUEUE * queue, Pointer * nextPtrPtr, SHM_QUEUE * nextQueue) { - SHM_QUEUE *elemPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next); - - Assert(SHM_PTR_VALID(queue)); - *nextPtrPtr = (Pointer) (((unsigned long) *nextPtrPtr) + - ((unsigned long) elemPtr) - ((unsigned long) nextQueue)); - - /* - nextPtrPtr a ptr to a structure linked in the queue - nextQueue is the SHMQueue field of the structure - *nextPtrPtr - nextQueue is 0 minus the offset of the queue - field n the record - elemPtr + (*nextPtrPtr - nexQueue) is the start of the - structure containing elemPtr. - */ + SHM_QUEUE *elemPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next); + + Assert(SHM_PTR_VALID(queue)); + *nextPtrPtr = (Pointer) (((unsigned long) *nextPtrPtr) + + ((unsigned long) elemPtr) - ((unsigned long) nextQueue)); + + /* + * nextPtrPtr a ptr to a structure linked in the queue nextQueue is + * the SHMQueue field of the structure nextPtrPtr - nextQueue is 0 + * minus the offset of the queue field n the record elemPtr + + * (*nextPtrPtr - nexQueue) is the start of the structure containing + * elemPtr. + */ } /* * SHMQueueEmpty -- TRUE if queue head is only element, FALSE otherwise */ bool -SHMQueueEmpty(SHM_QUEUE *queue) +SHMQueueEmpty(SHM_QUEUE * queue) { - Assert(SHM_PTR_VALID(queue)); - - if (queue->prev == MAKE_OFFSET(queue)) + Assert(SHM_PTR_VALID(queue)); + + if (queue->prev == MAKE_OFFSET(queue)) { - Assert(queue->next = MAKE_OFFSET(queue)); - return(TRUE); + Assert(queue->next = MAKE_OFFSET(queue)); + return (TRUE); } - return(FALSE); + return (FALSE); } diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index 5f391669113..af16c8a7196 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * sinval.c-- - * POSTGRES shared cache invalidation communication code. + * POSTGRES shared cache invalidation communication code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.7 1997/08/12 22:53:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.8 1997/09/07 04:48:43 momjian Exp $ * *------------------------------------------------------------------------- */ -/* #define INVALIDDEBUG 1 */ +/* #define INVALIDDEBUG 1 */ #include <sys/types.h> @@ -22,150 +22,156 @@ #include "storage/sinvaladt.h" #include "storage/spin.h" -extern SISeg *shmInvalBuffer;/* the shared buffer segment, set by*/ - /* SISegmentAttach() */ -extern BackendId MyBackendId; -extern BackendTag MyBackendTag; +extern SISeg *shmInvalBuffer; /* the shared buffer segment, set by */ + + /* SISegmentAttach() */ +extern BackendId MyBackendId; +extern BackendTag MyBackendTag; SPINLOCK SInvalLock = (SPINLOCK) NULL; /****************************************************************************/ -/* CreateSharedInvalidationState(key) Create a buffer segment */ -/* */ -/* should be called only by the POSTMASTER */ +/* CreateSharedInvalidationState(key) Create a buffer segment */ +/* */ +/* should be called only by the POSTMASTER */ /****************************************************************************/ void CreateSharedInvalidationState(IPCKey key) { - int status; - - /* REMOVED - SISyncKill(IPCKeyGetSIBufferMemorySemaphoreKey(key)); - SISyncInit(IPCKeyGetSIBufferMemorySemaphoreKey(key)); - */ - - /* SInvalLock gets set in spin.c, during spinlock init */ - status = SISegmentInit(true, IPCKeyGetSIBufferMemoryBlock(key)); - - if (status == -1) { - elog(FATAL, "CreateSharedInvalidationState: failed segment init"); - } + int status; + + /* + * REMOVED SISyncKill(IPCKeyGetSIBufferMemorySemaphoreKey(key)); + * SISyncInit(IPCKeyGetSIBufferMemorySemaphoreKey(key)); + */ + + /* SInvalLock gets set in spin.c, during spinlock init */ + status = SISegmentInit(true, IPCKeyGetSIBufferMemoryBlock(key)); + + if (status == -1) + { + elog(FATAL, "CreateSharedInvalidationState: failed segment init"); + } } + /****************************************************************************/ -/* AttachSharedInvalidationState(key) Attach a buffer segment */ -/* */ -/* should be called only by the POSTMASTER */ +/* AttachSharedInvalidationState(key) Attach a buffer segment */ +/* */ +/* should be called only by the POSTMASTER */ /****************************************************************************/ void AttachSharedInvalidationState(IPCKey key) { - int status; - - if (key == PrivateIPCKey) { - CreateSharedInvalidationState(key); - return; - } - /* SInvalLock gets set in spin.c, during spinlock init */ - status = SISegmentInit(false, IPCKeyGetSIBufferMemoryBlock(key)); - - if (status == -1) { - elog(FATAL, "AttachSharedInvalidationState: failed segment init"); - } + int status; + + if (key == PrivateIPCKey) + { + CreateSharedInvalidationState(key); + return; + } + /* SInvalLock gets set in spin.c, during spinlock init */ + status = SISegmentInit(false, IPCKeyGetSIBufferMemoryBlock(key)); + + if (status == -1) + { + elog(FATAL, "AttachSharedInvalidationState: failed segment init"); + } } void InitSharedInvalidationState(void) { - SpinAcquire(SInvalLock); - if (!SIBackendInit(shmInvalBuffer)) + SpinAcquire(SInvalLock); + if (!SIBackendInit(shmInvalBuffer)) { - SpinRelease(SInvalLock); - elog(FATAL, "Backend cache invalidation initialization failed"); + SpinRelease(SInvalLock); + elog(FATAL, "Backend cache invalidation initialization failed"); } - SpinRelease(SInvalLock); + SpinRelease(SInvalLock); } /* * RegisterSharedInvalid -- - * Returns a new local cache invalidation state containing a new entry. + * Returns a new local cache invalidation state containing a new entry. * * Note: - * Assumes hash index is valid. - * Assumes item pointer is valid. + * Assumes hash index is valid. + * Assumes item pointer is valid. */ /****************************************************************************/ -/* RegisterSharedInvalid(cacheId, hashIndex, pointer) */ -/* */ -/* register a message in the buffer */ -/* should be called by a backend */ +/* RegisterSharedInvalid(cacheId, hashIndex, pointer) */ +/* */ +/* register a message in the buffer */ +/* should be called by a backend */ /****************************************************************************/ void -RegisterSharedInvalid(int cacheId, /* XXX */ - Index hashIndex, - ItemPointer pointer) +RegisterSharedInvalid(int cacheId, /* XXX */ + Index hashIndex, + ItemPointer pointer) { - SharedInvalidData newInvalid; - - /* - * This code has been hacked to accept two types of messages. This might - * be treated more generally in the future. - * - * (1) - * cacheId= system cache id - * hashIndex= system cache hash index for a (possibly) cached tuple - * pointer= pointer of (possibly) cached tuple - * - * (2) - * cacheId= special non-syscache id - * hashIndex= object id contained in (possibly) cached relation descriptor - * pointer= null - */ - - newInvalid.cacheId = cacheId; - newInvalid.hashIndex = hashIndex; - - if (ItemPointerIsValid(pointer)) { - ItemPointerCopy(pointer, &newInvalid.pointerData); - } else { - ItemPointerSetInvalid(&newInvalid.pointerData); - } - - SpinAcquire(SInvalLock); - if (!SISetDataEntry(shmInvalBuffer, &newInvalid)) { - /* buffer full */ - /* release a message, mark process cache states to be invalid */ - SISetProcStateInvalid(shmInvalBuffer); - - if (!SIDelDataEntry(shmInvalBuffer)) { - /* inconsistent buffer state -- shd never happen */ - SpinRelease(SInvalLock); - elog(FATAL, "RegisterSharedInvalid: inconsistent buffer state"); - } - - /* write again */ - SISetDataEntry(shmInvalBuffer, &newInvalid); - } - SpinRelease(SInvalLock); + SharedInvalidData newInvalid; + + /* + * This code has been hacked to accept two types of messages. This + * might be treated more generally in the future. + * + * (1) cacheId= system cache id hashIndex= system cache hash index for a + * (possibly) cached tuple pointer= pointer of (possibly) cached tuple + * + * (2) cacheId= special non-syscache id hashIndex= object id contained in + * (possibly) cached relation descriptor pointer= null + */ + + newInvalid.cacheId = cacheId; + newInvalid.hashIndex = hashIndex; + + if (ItemPointerIsValid(pointer)) + { + ItemPointerCopy(pointer, &newInvalid.pointerData); + } + else + { + ItemPointerSetInvalid(&newInvalid.pointerData); + } + + SpinAcquire(SInvalLock); + if (!SISetDataEntry(shmInvalBuffer, &newInvalid)) + { + /* buffer full */ + /* release a message, mark process cache states to be invalid */ + SISetProcStateInvalid(shmInvalBuffer); + + if (!SIDelDataEntry(shmInvalBuffer)) + { + /* inconsistent buffer state -- shd never happen */ + SpinRelease(SInvalLock); + elog(FATAL, "RegisterSharedInvalid: inconsistent buffer state"); + } + + /* write again */ + SISetDataEntry(shmInvalBuffer, &newInvalid); + } + SpinRelease(SInvalLock); } /* * InvalidateSharedInvalid -- - * Processes all entries in a shared cache invalidation state. + * Processes all entries in a shared cache invalidation state. */ /****************************************************************************/ -/* InvalidateSharedInvalid(invalFunction, resetFunction) */ -/* */ -/* invalidate a message in the buffer (read and clean up) */ -/* should be called by a backend */ +/* InvalidateSharedInvalid(invalFunction, resetFunction) */ +/* */ +/* invalidate a message in the buffer (read and clean up) */ +/* should be called by a backend */ /****************************************************************************/ void -InvalidateSharedInvalid(void (*invalFunction)(), - void (*resetFunction)()) + InvalidateSharedInvalid(void (*invalFunction) (), + void (*resetFunction) ()) { - SpinAcquire(SInvalLock); - SIReadEntryData(shmInvalBuffer, MyBackendId, - invalFunction, resetFunction); - - SIDelExpiredDataEntries(shmInvalBuffer); - SpinRelease(SInvalLock); + SpinAcquire(SInvalLock); + SIReadEntryData(shmInvalBuffer, MyBackendId, + invalFunction, resetFunction); + + SIDelExpiredDataEntries(shmInvalBuffer); + SpinRelease(SInvalLock); } diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 9400e872617..43c4d7c0ac2 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * sinvaladt.c-- - * POSTGRES shared cache invalidation segment definitions. + * POSTGRES shared cache invalidation segment definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.5 1997/08/12 22:54:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.6 1997/09/07 04:48:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -22,420 +22,445 @@ #include "utils/palloc.h" /* ---------------- - * global variable notes + * global variable notes * - * SharedInvalidationSemaphore + * SharedInvalidationSemaphore * - * shmInvalBuffer - * the shared buffer segment, set by SISegmentAttach() + * shmInvalBuffer + * the shared buffer segment, set by SISegmentAttach() * - * MyBackendId - * might be removed later, used only for - * debugging in debug routines (end of file) + * MyBackendId + * might be removed later, used only for + * debugging in debug routines (end of file) * - * SIDbId - * identification of buffer (disappears) + * SIDbId + * identification of buffer (disappears) * - * SIRelId \ - * SIDummyOid \ identification of buffer - * SIXidData / - * SIXid / + * SIRelId \ + * SIDummyOid \ identification of buffer + * SIXidData / + * SIXid / * - * XXX This file really needs to be cleaned up. We switched to using - * spinlocks to protect critical sections (as opposed to using fake - * relations and going through the lock manager) and some of the old - * cruft was 'ifdef'ed out, while other parts (now unused) are still - * compiled into the system. -mer 5/24/92 + * XXX This file really needs to be cleaned up. We switched to using + * spinlocks to protect critical sections (as opposed to using fake + * relations and going through the lock manager) and some of the old + * cruft was 'ifdef'ed out, while other parts (now unused) are still + * compiled into the system. -mer 5/24/92 * ---------------- */ #ifdef HAS_TEST_AND_SET -int SharedInvalidationLockId; +int SharedInvalidationLockId; + #else IpcSemaphoreId SharedInvalidationSemaphore; + #endif -SISeg *shmInvalBuffer; +SISeg *shmInvalBuffer; extern BackendId MyBackendId; -static void CleanupInvalidationState(int status, SISeg *segInOutP); -static BackendId SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag); -static int SIGetNumEntries(SISeg *segP); +static void CleanupInvalidationState(int status, SISeg * segInOutP); +static BackendId SIAssignBackendId(SISeg * segInOutP, BackendTag backendTag); +static int SIGetNumEntries(SISeg * segP); /************************************************************************/ /* SISetActiveProcess(segP, backendId) set the backend status active */ -/* should be called only by the postmaster when creating a backend */ +/* should be called only by the postmaster when creating a backend */ /************************************************************************/ /* XXX I suspect that the segP parameter is extraneous. -hirohama */ static void -SISetActiveProcess(SISeg *segInOutP, BackendId backendId) +SISetActiveProcess(SISeg * segInOutP, BackendId backendId) { - /* mark all messages as read */ - - /* Assert(segP->procState[backendId - 1].tag == MyBackendTag); */ - - segInOutP->procState[backendId - 1].resetState = false; - segInOutP->procState[backendId - 1].limit = SIGetNumEntries(segInOutP); + /* mark all messages as read */ + + /* Assert(segP->procState[backendId - 1].tag == MyBackendTag); */ + + segInOutP->procState[backendId - 1].resetState = false; + segInOutP->procState[backendId - 1].limit = SIGetNumEntries(segInOutP); } /****************************************************************************/ -/* SIBackendInit() initializes a backend to operate on the buffer */ +/* SIBackendInit() initializes a backend to operate on the buffer */ /****************************************************************************/ int -SIBackendInit(SISeg *segInOutP) -{ - LRelId LtCreateRelId(); - TransactionId LMITransactionIdCopy(); - - Assert(MyBackendTag > 0); - - MyBackendId = SIAssignBackendId(segInOutP, MyBackendTag); - if (MyBackendId == InvalidBackendTag) - return 0; - +SIBackendInit(SISeg * segInOutP) +{ + LRelId LtCreateRelId(); + TransactionId LMITransactionIdCopy(); + + Assert(MyBackendTag > 0); + + MyBackendId = SIAssignBackendId(segInOutP, MyBackendTag); + if (MyBackendId == InvalidBackendTag) + return 0; + #ifdef INVALIDDEBUG - elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.", - MyBackendTag, MyBackendId); -#endif /* INVALIDDEBUG */ - - SISetActiveProcess(segInOutP, MyBackendId); - on_exitpg(CleanupInvalidationState, (caddr_t)segInOutP); - return 1; + elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.", + MyBackendTag, MyBackendId); +#endif /* INVALIDDEBUG */ + + SISetActiveProcess(segInOutP, MyBackendId); + on_exitpg(CleanupInvalidationState, (caddr_t) segInOutP); + return 1; } /* ---------------- - * SIAssignBackendId + * SIAssignBackendId * ---------------- */ -static BackendId -SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag) -{ - Index index; - ProcState *stateP; - - stateP = NULL; - - for (index = 0; index < MaxBackendId; index += 1) { - if (segInOutP->procState[index].tag == InvalidBackendTag || - segInOutP->procState[index].tag == backendTag) - { - stateP = &segInOutP->procState[index]; - break; - } - - if (!PointerIsValid(stateP) || - (segInOutP->procState[index].resetState && - (!stateP->resetState || - stateP->tag < backendTag)) || - (!stateP->resetState && - (segInOutP->procState[index].limit < - stateP->limit || - stateP->tag < backendTag))) - { - stateP = &segInOutP->procState[index]; - } - } - - /* verify that all "procState" entries checked for matching tags */ - - for (index += 1; index < MaxBackendId; index += 1) { - if (segInOutP->procState[index].tag == backendTag) { - elog (FATAL, "SIAssignBackendId: tag %d found twice", - backendTag); +static BackendId +SIAssignBackendId(SISeg * segInOutP, BackendTag backendTag) +{ + Index index; + ProcState *stateP; + + stateP = NULL; + + for (index = 0; index < MaxBackendId; index += 1) + { + if (segInOutP->procState[index].tag == InvalidBackendTag || + segInOutP->procState[index].tag == backendTag) + { + stateP = &segInOutP->procState[index]; + break; + } + + if (!PointerIsValid(stateP) || + (segInOutP->procState[index].resetState && + (!stateP->resetState || + stateP->tag < backendTag)) || + (!stateP->resetState && + (segInOutP->procState[index].limit < + stateP->limit || + stateP->tag < backendTag))) + { + stateP = &segInOutP->procState[index]; + } + } + + /* verify that all "procState" entries checked for matching tags */ + + for (index += 1; index < MaxBackendId; index += 1) + { + if (segInOutP->procState[index].tag == backendTag) + { + elog(FATAL, "SIAssignBackendId: tag %d found twice", + backendTag); + } } - } - - if (stateP->tag != InvalidBackendTag) { - if (stateP->tag == backendTag) { - elog(NOTICE, "SIAssignBackendId: reusing tag %d", - backendTag); - } else { - elog(NOTICE, - "SIAssignBackendId: discarding tag %d", - stateP->tag); - return InvalidBackendTag; + + if (stateP->tag != InvalidBackendTag) + { + if (stateP->tag == backendTag) + { + elog(NOTICE, "SIAssignBackendId: reusing tag %d", + backendTag); + } + else + { + elog(NOTICE, + "SIAssignBackendId: discarding tag %d", + stateP->tag); + return InvalidBackendTag; + } } - } - - stateP->tag = backendTag; - - return (1 + stateP - &segInOutP->procState[0]); + + stateP->tag = backendTag; + + return (1 + stateP - &segInOutP->procState[0]); } /************************************************************************/ -/* The following function should be called only by the postmaster !! */ +/* The following function should be called only by the postmaster !! */ /************************************************************************/ /************************************************************************/ -/* SISetDeadProcess(segP, backendId) set the backend status DEAD */ -/* should be called only by the postmaster when a backend died */ +/* SISetDeadProcess(segP, backendId) set the backend status DEAD */ +/* should be called only by the postmaster when a backend died */ /************************************************************************/ static void -SISetDeadProcess(SISeg *segP, int backendId) +SISetDeadProcess(SISeg * segP, int backendId) { - /* XXX call me.... */ - - segP->procState[backendId - 1].resetState = false; - segP->procState[backendId - 1].limit = -1; - segP->procState[backendId - 1].tag = InvalidBackendTag; + /* XXX call me.... */ + + segP->procState[backendId - 1].resetState = false; + segP->procState[backendId - 1].limit = -1; + segP->procState[backendId - 1].tag = InvalidBackendTag; } /* * CleanupInvalidationState -- * Note: - * This is a temporary hack. ExitBackend should call this instead - * of exit (via on_exitpg). + * This is a temporary hack. ExitBackend should call this instead + * of exit (via on_exitpg). */ static void -CleanupInvalidationState(int status, /* XXX */ - SISeg *segInOutP) /* XXX style */ +CleanupInvalidationState(int status, /* XXX */ + SISeg * segInOutP) /* XXX style */ { - Assert(PointerIsValid(segInOutP)); - - SISetDeadProcess(segInOutP, MyBackendId); + Assert(PointerIsValid(segInOutP)); + + SISetDeadProcess(segInOutP, MyBackendId); } /************************************************************************/ -/* SIComputeSize() - retuns the size of a buffer segment */ +/* SIComputeSize() - retuns the size of a buffer segment */ /************************************************************************/ static SISegOffsets * SIComputeSize(int *segSize) { - int A, B, a, b, totalSize; - SISegOffsets *oP; - - A = 0; - a = SizeSISeg; /* offset to first data entry */ - b = SizeOfOneSISegEntry * MAXNUMMESSAGES; - B = A + a + b; - totalSize = B - A; - *segSize = totalSize; - - oP = (SISegOffsets *) palloc(sizeof(SISegOffsets)); - oP->startSegment = A; - oP->offsetToFirstEntry = a; /* relatiove to A */ - oP->offsetToEndOfSegemnt = totalSize; /* relative to A */ - return(oP); + int A, + B, + a, + b, + totalSize; + SISegOffsets *oP; + + A = 0; + a = SizeSISeg; /* offset to first data entry */ + b = SizeOfOneSISegEntry * MAXNUMMESSAGES; + B = A + a + b; + totalSize = B - A; + *segSize = totalSize; + + oP = (SISegOffsets *) palloc(sizeof(SISegOffsets)); + oP->startSegment = A; + oP->offsetToFirstEntry = a; /* relatiove to A */ + oP->offsetToEndOfSegemnt = totalSize; /* relative to A */ + return (oP); } /************************************************************************/ -/* SISetStartEntrySection(segP, offset) - sets the offset */ +/* SISetStartEntrySection(segP, offset) - sets the offset */ /************************************************************************/ static void -SISetStartEntrySection(SISeg *segP, Offset offset) +SISetStartEntrySection(SISeg * segP, Offset offset) { - segP->startEntrySection = offset; + segP->startEntrySection = offset; } /************************************************************************/ -/* SIGetStartEntrySection(segP) - returnss the offset */ +/* SIGetStartEntrySection(segP) - returnss the offset */ /************************************************************************/ -static Offset -SIGetStartEntrySection(SISeg *segP) +static Offset +SIGetStartEntrySection(SISeg * segP) { - return(segP->startEntrySection); + return (segP->startEntrySection); } /************************************************************************/ -/* SISetEndEntrySection(segP, offset) - sets the offset */ +/* SISetEndEntrySection(segP, offset) - sets the offset */ /************************************************************************/ static void -SISetEndEntrySection(SISeg *segP, Offset offset) +SISetEndEntrySection(SISeg * segP, Offset offset) { - segP->endEntrySection = offset; + segP->endEntrySection = offset; } /************************************************************************/ -/* SISetEndEntryChain(segP, offset) - sets the offset */ +/* SISetEndEntryChain(segP, offset) - sets the offset */ /************************************************************************/ static void -SISetEndEntryChain(SISeg *segP, Offset offset) +SISetEndEntryChain(SISeg * segP, Offset offset) { - segP->endEntryChain = offset; + segP->endEntryChain = offset; } /************************************************************************/ -/* SIGetEndEntryChain(segP) - returnss the offset */ +/* SIGetEndEntryChain(segP) - returnss the offset */ /************************************************************************/ -static Offset -SIGetEndEntryChain(SISeg *segP) +static Offset +SIGetEndEntryChain(SISeg * segP) { - return(segP->endEntryChain); + return (segP->endEntryChain); } /************************************************************************/ -/* SISetStartEntryChain(segP, offset) - sets the offset */ +/* SISetStartEntryChain(segP, offset) - sets the offset */ /************************************************************************/ static void -SISetStartEntryChain(SISeg *segP, Offset offset) +SISetStartEntryChain(SISeg * segP, Offset offset) { - segP->startEntryChain = offset; + segP->startEntryChain = offset; } /************************************************************************/ -/* SIGetStartEntryChain(segP) - returns the offset */ +/* SIGetStartEntryChain(segP) - returns the offset */ /************************************************************************/ -static Offset -SIGetStartEntryChain(SISeg *segP) +static Offset +SIGetStartEntryChain(SISeg * segP) { - return(segP->startEntryChain); + return (segP->startEntryChain); } /************************************************************************/ -/* SISetNumEntries(segP, num) sets the current nuber of entries */ +/* SISetNumEntries(segP, num) sets the current nuber of entries */ /************************************************************************/ -static bool -SISetNumEntries(SISeg *segP, int num) +static bool +SISetNumEntries(SISeg * segP, int num) { - if ( num <= MAXNUMMESSAGES) { - segP->numEntries = num; - return(true); - } else { - return(false); /* table full */ - } + if (num <= MAXNUMMESSAGES) + { + segP->numEntries = num; + return (true); + } + else + { + return (false); /* table full */ + } } /************************************************************************/ -/* SIGetNumEntries(segP) - returns the current nuber of entries */ +/* SIGetNumEntries(segP) - returns the current nuber of entries */ /************************************************************************/ static int -SIGetNumEntries(SISeg *segP) +SIGetNumEntries(SISeg * segP) { - return(segP->numEntries); + return (segP->numEntries); } /************************************************************************/ -/* SISetMaxNumEntries(segP, num) sets the maximal number of entries */ +/* SISetMaxNumEntries(segP, num) sets the maximal number of entries */ /************************************************************************/ -static bool -SISetMaxNumEntries(SISeg *segP, int num) +static bool +SISetMaxNumEntries(SISeg * segP, int num) { - if ( num <= MAXNUMMESSAGES) { - segP->maxNumEntries = num; - return(true); - } else { - return(false); /* wrong number */ - } + if (num <= MAXNUMMESSAGES) + { + segP->maxNumEntries = num; + return (true); + } + else + { + return (false); /* wrong number */ + } } /************************************************************************/ -/* SIGetProcStateLimit(segP, i) returns the limit of read messages */ +/* SIGetProcStateLimit(segP, i) returns the limit of read messages */ /************************************************************************/ static int -SIGetProcStateLimit(SISeg *segP, int i) +SIGetProcStateLimit(SISeg * segP, int i) { - return(segP->procState[i].limit); + return (segP->procState[i].limit); } /************************************************************************/ -/* SIIncNumEntries(segP, num) increments the current nuber of entries */ +/* SIIncNumEntries(segP, num) increments the current nuber of entries */ /************************************************************************/ -static bool -SIIncNumEntries(SISeg *segP, int num) +static bool +SIIncNumEntries(SISeg * segP, int num) { - if ((segP->numEntries + num) <= MAXNUMMESSAGES) { - segP->numEntries = segP->numEntries + num; - return(true); - } else { - return(false); /* table full */ - } + if ((segP->numEntries + num) <= MAXNUMMESSAGES) + { + segP->numEntries = segP->numEntries + num; + return (true); + } + else + { + return (false); /* table full */ + } } /************************************************************************/ -/* SIDecNumEntries(segP, num) decrements the current nuber of entries */ +/* SIDecNumEntries(segP, num) decrements the current nuber of entries */ /************************************************************************/ -static bool -SIDecNumEntries(SISeg *segP, int num) +static bool +SIDecNumEntries(SISeg * segP, int num) { - if ((segP->numEntries - num) >= 0) { - segP->numEntries = segP->numEntries - num; - return(true); - } else { - return(false); /* not enough entries in table */ - } + if ((segP->numEntries - num) >= 0) + { + segP->numEntries = segP->numEntries - num; + return (true); + } + else + { + return (false); /* not enough entries in table */ + } } /************************************************************************/ -/* SISetStartFreeSpace(segP, offset) - sets the offset */ +/* SISetStartFreeSpace(segP, offset) - sets the offset */ /************************************************************************/ static void -SISetStartFreeSpace(SISeg *segP, Offset offset) +SISetStartFreeSpace(SISeg * segP, Offset offset) { - segP->startFreeSpace = offset; + segP->startFreeSpace = offset; } /************************************************************************/ -/* SIGetStartFreeSpace(segP) - returns the offset */ +/* SIGetStartFreeSpace(segP) - returns the offset */ /************************************************************************/ -static Offset -SIGetStartFreeSpace(SISeg *segP) +static Offset +SIGetStartFreeSpace(SISeg * segP) { - return(segP->startFreeSpace); + return (segP->startFreeSpace); } /************************************************************************/ -/* SIGetFirstDataEntry(segP) returns first data entry */ +/* SIGetFirstDataEntry(segP) returns first data entry */ /************************************************************************/ static SISegEntry * -SIGetFirstDataEntry(SISeg *segP) +SIGetFirstDataEntry(SISeg * segP) { - SISegEntry *eP; - Offset startChain; - - startChain = SIGetStartEntryChain(segP); - - if (startChain == InvalidOffset) - return(NULL); - - eP = (SISegEntry *) ((Pointer) segP + - SIGetStartEntrySection(segP) + - startChain ); - return(eP); + SISegEntry *eP; + Offset startChain; + + startChain = SIGetStartEntryChain(segP); + + if (startChain == InvalidOffset) + return (NULL); + + eP = (SISegEntry *) ((Pointer) segP + + SIGetStartEntrySection(segP) + + startChain); + return (eP); } /************************************************************************/ -/* SIGetLastDataEntry(segP) returns last data entry in the chain */ +/* SIGetLastDataEntry(segP) returns last data entry in the chain */ /************************************************************************/ static SISegEntry * -SIGetLastDataEntry(SISeg *segP) +SIGetLastDataEntry(SISeg * segP) { - SISegEntry *eP; - Offset endChain; - - endChain = SIGetEndEntryChain(segP); - - if (endChain == InvalidOffset) - return(NULL); - - eP = (SISegEntry *) ((Pointer) segP + - SIGetStartEntrySection(segP) + - endChain ); - return(eP); + SISegEntry *eP; + Offset endChain; + + endChain = SIGetEndEntryChain(segP); + + if (endChain == InvalidOffset) + return (NULL); + + eP = (SISegEntry *) ((Pointer) segP + + SIGetStartEntrySection(segP) + + endChain); + return (eP); } /************************************************************************/ -/* SIGetNextDataEntry(segP, offset) returns next data entry */ +/* SIGetNextDataEntry(segP, offset) returns next data entry */ /************************************************************************/ static SISegEntry * -SIGetNextDataEntry(SISeg *segP, Offset offset) +SIGetNextDataEntry(SISeg * segP, Offset offset) { - SISegEntry *eP; - - if (offset == InvalidOffset) - return(NULL); - - eP = (SISegEntry *) ((Pointer) segP + - SIGetStartEntrySection(segP) + - offset); - return(eP); + SISegEntry *eP; + + if (offset == InvalidOffset) + return (NULL); + + eP = (SISegEntry *) ((Pointer) segP + + SIGetStartEntrySection(segP) + + offset); + return (eP); } @@ -443,352 +468,396 @@ SIGetNextDataEntry(SISeg *segP, Offset offset) /* SIGetNthDataEntry(segP, n) returns the n-th data entry in chain */ /************************************************************************/ static SISegEntry * -SIGetNthDataEntry(SISeg *segP, - int n) /* must range from 1 to MaxMessages */ +SIGetNthDataEntry(SISeg * segP, + int n) /* must range from 1 to MaxMessages */ { - SISegEntry *eP; - int i; - - if (n <= 0) return(NULL); - - eP = SIGetFirstDataEntry(segP); - for (i = 1; i < n; i++) { - /* skip one and get the next */ - eP = SIGetNextDataEntry(segP, eP->next); - } - - return(eP); + SISegEntry *eP; + int i; + + if (n <= 0) + return (NULL); + + eP = SIGetFirstDataEntry(segP); + for (i = 1; i < n; i++) + { + /* skip one and get the next */ + eP = SIGetNextDataEntry(segP, eP->next); + } + + return (eP); } /************************************************************************/ -/* SIEntryOffset(segP, entryP) returns the offset for an pointer */ +/* SIEntryOffset(segP, entryP) returns the offset for an pointer */ /************************************************************************/ -static Offset -SIEntryOffset(SISeg *segP, SISegEntry *entryP) +static Offset +SIEntryOffset(SISeg * segP, SISegEntry * entryP) { - /* relative to B !! */ - return ((Offset) ((Pointer) entryP - - (Pointer) segP - - SIGetStartEntrySection(segP) )); + /* relative to B !! */ + return ((Offset) ((Pointer) entryP - + (Pointer) segP - + SIGetStartEntrySection(segP))); } /************************************************************************/ -/* SISetDataEntry(segP, data) - sets a message in the segemnt */ +/* SISetDataEntry(segP, data) - sets a message in the segemnt */ /************************************************************************/ bool -SISetDataEntry(SISeg *segP, SharedInvalidData *data) -{ - Offset offsetToNewData; - SISegEntry *eP, *lastP; - - if (!SIIncNumEntries(segP, 1)) - return(false); /* no space */ - - /* get a free entry */ - offsetToNewData = SIGetStartFreeSpace(segP); - eP = SIGetNextDataEntry(segP, offsetToNewData); /* it's a free one */ - SISetStartFreeSpace(segP, eP->next); - /* fill it up */ - eP->entryData = *data; - eP->isfree = false; - eP->next = InvalidOffset; - - /* handle insertion point at the end of the chain !!*/ - lastP = SIGetLastDataEntry(segP); - if (lastP == NULL) { - /* there is no chain, insert the first entry */ - SISetStartEntryChain(segP, SIEntryOffset(segP, eP)); - } else { - /* there is a last entry in the chain */ - lastP->next = SIEntryOffset(segP, eP); - } - SISetEndEntryChain(segP, SIEntryOffset(segP, eP)); - return(true); -} - - -/************************************************************************/ -/* SIDecProcLimit(segP, num) decrements all process limits */ +SISetDataEntry(SISeg * segP, SharedInvalidData * data) +{ + Offset offsetToNewData; + SISegEntry *eP, + *lastP; + + if (!SIIncNumEntries(segP, 1)) + return (false); /* no space */ + + /* get a free entry */ + offsetToNewData = SIGetStartFreeSpace(segP); + eP = SIGetNextDataEntry(segP, offsetToNewData); /* it's a free one */ + SISetStartFreeSpace(segP, eP->next); + /* fill it up */ + eP->entryData = *data; + eP->isfree = false; + eP->next = InvalidOffset; + + /* handle insertion point at the end of the chain !! */ + lastP = SIGetLastDataEntry(segP); + if (lastP == NULL) + { + /* there is no chain, insert the first entry */ + SISetStartEntryChain(segP, SIEntryOffset(segP, eP)); + } + else + { + /* there is a last entry in the chain */ + lastP->next = SIEntryOffset(segP, eP); + } + SISetEndEntryChain(segP, SIEntryOffset(segP, eP)); + return (true); +} + + +/************************************************************************/ +/* SIDecProcLimit(segP, num) decrements all process limits */ /************************************************************************/ static void -SIDecProcLimit(SISeg *segP, int num) -{ - int i; - for (i=0; i < MaxBackendId; i++) { - /* decrement only, if there is a limit > 0 */ - if (segP->procState[i].limit > 0) { - segP->procState[i].limit = segP->procState[i].limit - num; - if (segP->procState[i].limit < 0) { - /* limit was not high enough, reset to zero */ - /* negative means it's a dead backend */ - segP->procState[i].limit = 0; - } - } - } +SIDecProcLimit(SISeg * segP, int num) +{ + int i; + + for (i = 0; i < MaxBackendId; i++) + { + /* decrement only, if there is a limit > 0 */ + if (segP->procState[i].limit > 0) + { + segP->procState[i].limit = segP->procState[i].limit - num; + if (segP->procState[i].limit < 0) + { + /* limit was not high enough, reset to zero */ + /* negative means it's a dead backend */ + segP->procState[i].limit = 0; + } + } + } } /************************************************************************/ -/* SIDelDataEntry(segP) - free the FIRST entry */ +/* SIDelDataEntry(segP) - free the FIRST entry */ /************************************************************************/ bool -SIDelDataEntry(SISeg *segP) +SIDelDataEntry(SISeg * segP) { - SISegEntry *e1P; - - if (!SIDecNumEntries(segP, 1)) { - /* no entries in buffer */ - return(false); - } - - e1P = SIGetFirstDataEntry(segP); - SISetStartEntryChain(segP, e1P->next); - if (SIGetStartEntryChain(segP) == InvalidOffset) { - /* it was the last entry */ - SISetEndEntryChain(segP, InvalidOffset); - } - /* free the entry */ - e1P->isfree = true; - e1P->next = SIGetStartFreeSpace(segP); - SISetStartFreeSpace(segP, SIEntryOffset(segP, e1P)); - SIDecProcLimit(segP, 1); - return(true); + SISegEntry *e1P; + + if (!SIDecNumEntries(segP, 1)) + { + /* no entries in buffer */ + return (false); + } + + e1P = SIGetFirstDataEntry(segP); + SISetStartEntryChain(segP, e1P->next); + if (SIGetStartEntryChain(segP) == InvalidOffset) + { + /* it was the last entry */ + SISetEndEntryChain(segP, InvalidOffset); + } + /* free the entry */ + e1P->isfree = true; + e1P->next = SIGetStartFreeSpace(segP); + SISetStartFreeSpace(segP, SIEntryOffset(segP, e1P)); + SIDecProcLimit(segP, 1); + return (true); } /************************************************************************/ -/* SISetProcStateInvalid(segP) checks and marks a backends state as */ -/* invalid */ +/* SISetProcStateInvalid(segP) checks and marks a backends state as */ +/* invalid */ /************************************************************************/ void -SISetProcStateInvalid(SISeg *segP) -{ - int i; - - for (i=0; i < MaxBackendId; i++) { - if (segP->procState[i].limit == 0) { - /* backend i didn't read any message */ - segP->procState[i].resetState = true; - /*XXX signal backend that it has to reset its internal cache ? */ - } - } +SISetProcStateInvalid(SISeg * segP) +{ + int i; + + for (i = 0; i < MaxBackendId; i++) + { + if (segP->procState[i].limit == 0) + { + /* backend i didn't read any message */ + segP->procState[i].resetState = true; + + /* + * XXX signal backend that it has to reset its internal cache + * ? + */ + } + } } /************************************************************************/ -/* SIReadEntryData(segP, backendId, function) */ -/* - marks messages to be read by id */ -/* and executes function */ +/* SIReadEntryData(segP, backendId, function) */ +/* - marks messages to be read by id */ +/* and executes function */ /************************************************************************/ void -SIReadEntryData(SISeg *segP, - int backendId, - void (*invalFunction)(), - void (*resetFunction)()) -{ - int i = 0; - SISegEntry *data; - - Assert(segP->procState[backendId - 1].tag == MyBackendTag); - - if (!segP->procState[backendId - 1].resetState) { - /* invalidate data, but only those, you have not seen yet !!*/ - /* therefore skip read messages */ - data = SIGetNthDataEntry(segP, - SIGetProcStateLimit(segP, backendId - 1) + 1); - while (data != NULL) { - i++; - segP->procState[backendId - 1].limit++; /* one more message read */ - invalFunction(data->entryData.cacheId, - data->entryData.hashIndex, - &data->entryData.pointerData); - data = SIGetNextDataEntry(segP, data->next); - } - /* SIDelExpiredDataEntries(segP); */ - } else { - /*backend must not read messages, its own state has to be reset */ - elog(NOTICE, "SIMarkEntryData: cache state reset"); - resetFunction(); /* XXXX call it here, parameters? */ - - /* new valid state--mark all messages "read" */ - segP->procState[backendId - 1].resetState = false; - segP->procState[backendId - 1].limit = SIGetNumEntries(segP); - } - /* check whether we can remove dead messages */ - if (i > MAXNUMMESSAGES) { - elog(FATAL, "SIReadEntryData: Invalid segment state"); - } +SIReadEntryData(SISeg * segP, + int backendId, + void (*invalFunction) (), + void (*resetFunction) ()) +{ + int i = 0; + SISegEntry *data; + + Assert(segP->procState[backendId - 1].tag == MyBackendTag); + + if (!segP->procState[backendId - 1].resetState) + { + /* invalidate data, but only those, you have not seen yet !! */ + /* therefore skip read messages */ + data = SIGetNthDataEntry(segP, + SIGetProcStateLimit(segP, backendId - 1) + 1); + while (data != NULL) + { + i++; + segP->procState[backendId - 1].limit++; /* one more message read */ + invalFunction(data->entryData.cacheId, + data->entryData.hashIndex, + &data->entryData.pointerData); + data = SIGetNextDataEntry(segP, data->next); + } + /* SIDelExpiredDataEntries(segP); */ + } + else + { + /* backend must not read messages, its own state has to be reset */ + elog(NOTICE, "SIMarkEntryData: cache state reset"); + resetFunction(); /* XXXX call it here, parameters? */ + + /* new valid state--mark all messages "read" */ + segP->procState[backendId - 1].resetState = false; + segP->procState[backendId - 1].limit = SIGetNumEntries(segP); + } + /* check whether we can remove dead messages */ + if (i > MAXNUMMESSAGES) + { + elog(FATAL, "SIReadEntryData: Invalid segment state"); + } } /************************************************************************/ -/* SIDelExpiredDataEntries (segP) - removes irrelevant messages */ +/* SIDelExpiredDataEntries (segP) - removes irrelevant messages */ /************************************************************************/ void -SIDelExpiredDataEntries(SISeg *segP) -{ - int min, i, h; - - min = 9999999; - for (i = 0; i < MaxBackendId; i++) { - h = SIGetProcStateLimit(segP, i); - if (h >= 0) { /* backend active */ - if (h < min ) min = h; - } - } - if (min != 9999999) { - /* we can remove min messages */ - for (i = 1; i <= min; i++) { - /* this adjusts also the state limits!*/ - if (!SIDelDataEntry(segP)) { - elog(FATAL, "SIDelExpiredDataEntries: Invalid segment state"); - } - } - } +SIDelExpiredDataEntries(SISeg * segP) +{ + int min, + i, + h; + + min = 9999999; + for (i = 0; i < MaxBackendId; i++) + { + h = SIGetProcStateLimit(segP, i); + if (h >= 0) + { /* backend active */ + if (h < min) + min = h; + } + } + if (min != 9999999) + { + /* we can remove min messages */ + for (i = 1; i <= min; i++) + { + /* this adjusts also the state limits! */ + if (!SIDelDataEntry(segP)) + { + elog(FATAL, "SIDelExpiredDataEntries: Invalid segment state"); + } + } + } } /************************************************************************/ -/* SISegInit(segP) - initializes the segment */ +/* SISegInit(segP) - initializes the segment */ /************************************************************************/ static void -SISegInit(SISeg *segP) -{ - SISegOffsets *oP; - int segSize, i; - SISegEntry *eP; - - oP = SIComputeSize(&segSize); - /* set sempahore ids in the segment */ - /* XXX */ - SISetStartEntrySection(segP, oP->offsetToFirstEntry); - SISetEndEntrySection(segP, oP->offsetToEndOfSegemnt); - SISetStartFreeSpace(segP, 0); - SISetStartEntryChain(segP, InvalidOffset); - SISetEndEntryChain(segP, InvalidOffset); - SISetNumEntries(segP, 0); - SISetMaxNumEntries(segP, MAXNUMMESSAGES); - for (i = 0; i < MaxBackendId; i++) { - segP->procState[i].limit = -1; /* no backend active !!*/ - segP->procState[i].resetState = false; - segP->procState[i].tag = InvalidBackendTag; - } - /* construct a chain of free entries */ - for (i = 1; i < MAXNUMMESSAGES; i++) { - eP = (SISegEntry *) ((Pointer) segP + - SIGetStartEntrySection(segP) + - (i - 1) * sizeof(SISegEntry)); - eP->isfree = true; - eP->next = i * sizeof(SISegEntry); /* relative to B */ - } - /* handle the last free entry separate */ - eP = (SISegEntry *) ((Pointer) segP + - SIGetStartEntrySection(segP) + - (MAXNUMMESSAGES - 1) * sizeof(SISegEntry)); - eP->isfree = true; - eP->next = InvalidOffset; /* it's the end of the chain !! */ - /* - * Be tidy - */ - pfree(oP); - -} - - - -/************************************************************************/ -/* SISegmentKill(key) - kill any segment */ +SISegInit(SISeg * segP) +{ + SISegOffsets *oP; + int segSize, + i; + SISegEntry *eP; + + oP = SIComputeSize(&segSize); + /* set sempahore ids in the segment */ + /* XXX */ + SISetStartEntrySection(segP, oP->offsetToFirstEntry); + SISetEndEntrySection(segP, oP->offsetToEndOfSegemnt); + SISetStartFreeSpace(segP, 0); + SISetStartEntryChain(segP, InvalidOffset); + SISetEndEntryChain(segP, InvalidOffset); + SISetNumEntries(segP, 0); + SISetMaxNumEntries(segP, MAXNUMMESSAGES); + for (i = 0; i < MaxBackendId; i++) + { + segP->procState[i].limit = -1; /* no backend active !! */ + segP->procState[i].resetState = false; + segP->procState[i].tag = InvalidBackendTag; + } + /* construct a chain of free entries */ + for (i = 1; i < MAXNUMMESSAGES; i++) + { + eP = (SISegEntry *) ((Pointer) segP + + SIGetStartEntrySection(segP) + + (i - 1) * sizeof(SISegEntry)); + eP->isfree = true; + eP->next = i * sizeof(SISegEntry); /* relative to B */ + } + /* handle the last free entry separate */ + eP = (SISegEntry *) ((Pointer) segP + + SIGetStartEntrySection(segP) + + (MAXNUMMESSAGES - 1) * sizeof(SISegEntry)); + eP->isfree = true; + eP->next = InvalidOffset; /* it's the end of the chain !! */ + + /* + * Be tidy + */ + pfree(oP); + +} + + + +/************************************************************************/ +/* SISegmentKill(key) - kill any segment */ /************************************************************************/ static void -SISegmentKill(int key) /* the corresponding key for the segment */ -{ - IpcMemoryKill(key); -} +SISegmentKill(int key) /* the corresponding key for the segment */ +{ + IpcMemoryKill(key); +} /************************************************************************/ -/* SISegmentGet(key, size) - get a shared segment of size <size> */ -/* returns a segment id */ +/* SISegmentGet(key, size) - get a shared segment of size <size> */ +/* returns a segment id */ /************************************************************************/ -static IpcMemoryId -SISegmentGet(int key, /* the corresponding key for the segment */ - int size, /* size of segment in bytes */ - bool create) +static IpcMemoryId +SISegmentGet(int key, /* the corresponding key for the segment */ + int size, /* size of segment in bytes */ + bool create) { - IpcMemoryId shmid; - - if (create) { - shmid = IpcMemoryCreate(key, size, IPCProtection); - } else { - shmid = IpcMemoryIdGet(key, size); - } - return(shmid); + IpcMemoryId shmid; + + if (create) + { + shmid = IpcMemoryCreate(key, size, IPCProtection); + } + else + { + shmid = IpcMemoryIdGet(key, size); + } + return (shmid); } /************************************************************************/ -/* SISegmentAttach(shmid) - attach a shared segment with id shmid */ +/* SISegmentAttach(shmid) - attach a shared segment with id shmid */ /************************************************************************/ static void SISegmentAttach(IpcMemoryId shmid) { - shmInvalBuffer = (struct SISeg *) IpcMemoryAttach(shmid); - if (shmInvalBuffer == IpcMemAttachFailed) { - /* XXX use validity function */ - elog(NOTICE, "SISegmentAttach: Could not attach segment"); - elog(FATAL, "SISegmentAttach: %m"); - } + shmInvalBuffer = (struct SISeg *) IpcMemoryAttach(shmid); + if (shmInvalBuffer == IpcMemAttachFailed) + { + /* XXX use validity function */ + elog(NOTICE, "SISegmentAttach: Could not attach segment"); + elog(FATAL, "SISegmentAttach: %m"); + } } /************************************************************************/ -/* SISegmentInit(killExistingSegment, key) initialize segment */ +/* SISegmentInit(killExistingSegment, key) initialize segment */ /************************************************************************/ int SISegmentInit(bool killExistingSegment, IPCKey key) -{ - SISegOffsets *oP; - int segSize; - IpcMemoryId shmId; - bool create; - - if (killExistingSegment) { - /* Kill existing segment */ - /* set semaphore */ - SISegmentKill(key); - - /* Get a shared segment */ - - oP = SIComputeSize(&segSize); - /* - * Be tidy - */ - pfree(oP); - - create = true; - shmId = SISegmentGet(key,segSize, create); - if (shmId < 0) { - perror("SISegmentGet: failed"); - return(-1); /* an error */ - } - - /* Attach the shared cache invalidation segment */ - /* sets the global variable shmInvalBuffer */ - SISegmentAttach(shmId); - - /* Init shared memory table */ - SISegInit(shmInvalBuffer); - } else { - /* use an existing segment */ - create = false; - shmId = SISegmentGet(key, 0, create); - if (shmId < 0) { - perror("SISegmentGet: getting an existent segment failed"); - return(-1); /* an error */ - } - /* Attach the shared cache invalidation segment */ - SISegmentAttach(shmId); - } - return(1); -} +{ + SISegOffsets *oP; + int segSize; + IpcMemoryId shmId; + bool create; + + if (killExistingSegment) + { + /* Kill existing segment */ + /* set semaphore */ + SISegmentKill(key); + + /* Get a shared segment */ + + oP = SIComputeSize(&segSize); + + /* + * Be tidy + */ + pfree(oP); + create = true; + shmId = SISegmentGet(key, segSize, create); + if (shmId < 0) + { + perror("SISegmentGet: failed"); + return (-1); /* an error */ + } + + /* Attach the shared cache invalidation segment */ + /* sets the global variable shmInvalBuffer */ + SISegmentAttach(shmId); + + /* Init shared memory table */ + SISegInit(shmInvalBuffer); + } + else + { + /* use an existing segment */ + create = false; + shmId = SISegmentGet(key, 0, create); + if (shmId < 0) + { + perror("SISegmentGet: getting an existent segment failed"); + return (-1); /* an error */ + } + /* Attach the shared cache invalidation segment */ + SISegmentAttach(shmId); + } + return (1); +} diff --git a/src/backend/storage/ipc/spin.c b/src/backend/storage/ipc/spin.c index b50d5d9500f..e93d5894a58 100644 --- a/src/backend/storage/ipc/spin.c +++ b/src/backend/storage/ipc/spin.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * spin.c-- - * routines for managing spin locks + * routines for managing spin locks * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.6 1997/08/21 13:43:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.7 1997/09/07 04:48:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,8 +21,8 @@ * term semaphores separately anyway. * * NOTE: These routines are not supposed to be widely used in Postgres. - * They are preserved solely for the purpose of porting Mark Sullivan's - * buffer manager to Postgres. + * They are preserved solely for the purpose of porting Mark Sullivan's + * buffer manager to Postgres. */ #include <errno.h> #include "postgres.h" @@ -43,61 +43,62 @@ IpcSemaphoreId SpinLockId; bool CreateSpinlocks(IPCKey key) -{ - /* the spin lock shared memory must have been created by now */ - return(TRUE); +{ + /* the spin lock shared memory must have been created by now */ + return (TRUE); } bool InitSpinLocks(int init, IPCKey key) { - extern SPINLOCK ShmemLock; - extern SPINLOCK BindingLock; - extern SPINLOCK BufMgrLock; - extern SPINLOCK LockMgrLock; - extern SPINLOCK ProcStructLock; - extern SPINLOCK SInvalLock; - extern SPINLOCK OidGenLockId; - + extern SPINLOCK ShmemLock; + extern SPINLOCK BindingLock; + extern SPINLOCK BufMgrLock; + extern SPINLOCK LockMgrLock; + extern SPINLOCK ProcStructLock; + extern SPINLOCK SInvalLock; + extern SPINLOCK OidGenLockId; + #ifdef MAIN_MEMORY - extern SPINLOCK MMCacheLock; -#endif /* SONY_JUKEBOX */ - - /* These six spinlocks have fixed location is shmem */ - ShmemLock = (SPINLOCK) SHMEMLOCKID; - BindingLock = (SPINLOCK) BINDINGLOCKID; - BufMgrLock = (SPINLOCK) BUFMGRLOCKID; - LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; - ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; - SInvalLock = (SPINLOCK) SINVALLOCKID; - OidGenLockId = (SPINLOCK) OIDGENLOCKID; - + extern SPINLOCK MMCacheLock; + +#endif /* SONY_JUKEBOX */ + + /* These six spinlocks have fixed location is shmem */ + ShmemLock = (SPINLOCK) SHMEMLOCKID; + BindingLock = (SPINLOCK) BINDINGLOCKID; + BufMgrLock = (SPINLOCK) BUFMGRLOCKID; + LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; + ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; + SInvalLock = (SPINLOCK) SINVALLOCKID; + OidGenLockId = (SPINLOCK) OIDGENLOCKID; + #ifdef MAIN_MEMORY - MMCacheLock = (SPINLOCK) MMCACHELOCKID; -#endif /* MAIN_MEMORY */ - - return(TRUE); + MMCacheLock = (SPINLOCK) MMCACHELOCKID; +#endif /* MAIN_MEMORY */ + + return (TRUE); } void SpinAcquire(SPINLOCK lock) { - ExclusiveLock(lock); - PROC_INCR_SLOCK(lock); + ExclusiveLock(lock); + PROC_INCR_SLOCK(lock); } void SpinRelease(SPINLOCK lock) { - PROC_DECR_SLOCK(lock); - ExclusiveUnlock(lock); + PROC_DECR_SLOCK(lock); + ExclusiveUnlock(lock); } -#else /* HAS_TEST_AND_SET */ +#else /* HAS_TEST_AND_SET */ /* Spinlocks are implemented using SysV semaphores */ -static bool AttachSpinLocks(IPCKey key); -static bool SpinIsLocked(SPINLOCK lock); +static bool AttachSpinLocks(IPCKey key); +static bool SpinIsLocked(SPINLOCK lock); /* * SpinAcquire -- try to grab a spinlock @@ -107,86 +108,91 @@ static bool SpinIsLocked(SPINLOCK lock); void SpinAcquire(SPINLOCK lock) { - IpcSemaphoreLock(SpinLockId, lock, IpcExclusiveLock); - PROC_INCR_SLOCK(lock); + IpcSemaphoreLock(SpinLockId, lock, IpcExclusiveLock); + PROC_INCR_SLOCK(lock); } /* * SpinRelease -- release a spin lock - * + * * FAILS if the semaphore is corrupted */ void SpinRelease(SPINLOCK lock) { - Assert(SpinIsLocked(lock)) + Assert(SpinIsLocked(lock)) PROC_DECR_SLOCK(lock); - IpcSemaphoreUnlock(SpinLockId, lock, IpcExclusiveLock); + IpcSemaphoreUnlock(SpinLockId, lock, IpcExclusiveLock); } -static bool +static bool SpinIsLocked(SPINLOCK lock) { - int semval; - - semval = IpcSemaphoreGetValue(SpinLockId, lock); - return(semval < IpcSemaphoreDefaultStartValue); + int semval; + + semval = IpcSemaphoreGetValue(SpinLockId, lock); + return (semval < IpcSemaphoreDefaultStartValue); } /* * CreateSpinlocks -- Create a sysV semaphore array for - * the spinlocks + * the spinlocks * */ bool CreateSpinlocks(IPCKey key) { - - int status; - IpcSemaphoreId semid; - semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, - IpcSemaphoreDefaultStartValue, 1, &status); - if (status == IpcSemIdExist) { - IpcSemaphoreKill(key); - elog(NOTICE,"Destroying old spinlock semaphore"); - semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, - IpcSemaphoreDefaultStartValue, 1, &status); - } - - if (semid >= 0) { - SpinLockId = semid; - return(TRUE); - } - /* cannot create spinlocks */ - elog(FATAL,"CreateSpinlocks: cannot create spin locks"); - return(FALSE); + + int status; + IpcSemaphoreId semid; + + semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, + IpcSemaphoreDefaultStartValue, 1, &status); + if (status == IpcSemIdExist) + { + IpcSemaphoreKill(key); + elog(NOTICE, "Destroying old spinlock semaphore"); + semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, + IpcSemaphoreDefaultStartValue, 1, &status); + } + + if (semid >= 0) + { + SpinLockId = semid; + return (TRUE); + } + /* cannot create spinlocks */ + elog(FATAL, "CreateSpinlocks: cannot create spin locks"); + return (FALSE); } /* * Attach to existing spinlock set */ -static bool +static bool AttachSpinLocks(IPCKey key) { - IpcSemaphoreId id; - - id = semget (key, MAX_SPINS, 0); - if (id < 0) { - if (errno == EEXIST) { - /* key is the name of someone else's semaphore */ - elog (FATAL,"AttachSpinlocks: SPIN_KEY belongs to someone else"); + IpcSemaphoreId id; + + id = semget(key, MAX_SPINS, 0); + if (id < 0) + { + if (errno == EEXIST) + { + /* key is the name of someone else's semaphore */ + elog(FATAL, "AttachSpinlocks: SPIN_KEY belongs to someone else"); + } + /* cannot create spinlocks */ + elog(FATAL, "AttachSpinlocks: cannot create spin locks"); + return (FALSE); } - /* cannot create spinlocks */ - elog(FATAL,"AttachSpinlocks: cannot create spin locks"); - return(FALSE); - } - SpinLockId = id; - return(TRUE); + SpinLockId = id; + return (TRUE); } /* * InitSpinLocks -- Spinlock bootstrapping - * + * * We need several spinlocks for bootstrapping: * BindingLock (for the shmem binding table) and * ShmemLock (for the shmem allocator), BufMgrLock (for buffer @@ -199,41 +205,47 @@ AttachSpinLocks(IPCKey key) bool InitSpinLocks(int init, IPCKey key) { - extern SPINLOCK ShmemLock; - extern SPINLOCK BindingLock; - extern SPINLOCK BufMgrLock; - extern SPINLOCK LockMgrLock; - extern SPINLOCK ProcStructLock; - extern SPINLOCK SInvalLock; - extern SPINLOCK OidGenLockId; - + extern SPINLOCK ShmemLock; + extern SPINLOCK BindingLock; + extern SPINLOCK BufMgrLock; + extern SPINLOCK LockMgrLock; + extern SPINLOCK ProcStructLock; + extern SPINLOCK SInvalLock; + extern SPINLOCK OidGenLockId; + #ifdef MAIN_MEMORY - extern SPINLOCK MMCacheLock; -#endif /* MAIN_MEMORY */ - - if (!init || key != IPC_PRIVATE) { - /* if bootstrap and key is IPC_PRIVATE, it means that we are running - * backend by itself. no need to attach spinlocks - */ - if (! AttachSpinLocks(key)) { - elog(FATAL,"InitSpinLocks: couldnt attach spin locks"); - return(FALSE); + extern SPINLOCK MMCacheLock; + +#endif /* MAIN_MEMORY */ + + if (!init || key != IPC_PRIVATE) + { + + /* + * if bootstrap and key is IPC_PRIVATE, it means that we are + * running backend by itself. no need to attach spinlocks + */ + if (!AttachSpinLocks(key)) + { + elog(FATAL, "InitSpinLocks: couldnt attach spin locks"); + return (FALSE); + } } - } - - /* These five (or six) spinlocks have fixed location is shmem */ - ShmemLock = (SPINLOCK) SHMEMLOCKID; - BindingLock = (SPINLOCK) BINDINGLOCKID; - BufMgrLock = (SPINLOCK) BUFMGRLOCKID; - LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; - ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; - SInvalLock = (SPINLOCK) SINVALLOCKID; - OidGenLockId = (SPINLOCK) OIDGENLOCKID; - + + /* These five (or six) spinlocks have fixed location is shmem */ + ShmemLock = (SPINLOCK) SHMEMLOCKID; + BindingLock = (SPINLOCK) BINDINGLOCKID; + BufMgrLock = (SPINLOCK) BUFMGRLOCKID; + LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; + ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; + SInvalLock = (SPINLOCK) SINVALLOCKID; + OidGenLockId = (SPINLOCK) OIDGENLOCKID; + #ifdef MAIN_MEMORY - MMCacheLock = (SPINLOCK) MMCACHELOCKID; -#endif /* MAIN_MEMORY */ - - return(TRUE); + MMCacheLock = (SPINLOCK) MMCACHELOCKID; +#endif /* MAIN_MEMORY */ + + return (TRUE); } -#endif /* HAS_TEST_AND_SET */ + +#endif /* HAS_TEST_AND_SET */ |