head 1.17; access; symbols release_4_2:1.17 aix_ok:1.16 Version_2_1:1.6; locks; strict; comment @ * @; 1.17 date 94.02.07.11.44.36; author aoki; state Exp; branches; next 1.16; 1.16 date 91.11.21.13.18.07; author hong; state Exp; branches; next 1.15; 1.15 date 91.11.09.09.52.00; author hong; state Exp; branches; next 1.14; 1.14 date 91.09.27.19.05.15; author hong; state Exp; branches; next 1.13; 1.13 date 91.08.29.23.54.07; author mer; state Exp; branches; next 1.12; 1.12 date 91.08.27.14.18.48; author hong; state Exp; branches; next 1.11; 1.11 date 91.08.25.13.34.35; author hong; state Exp; branches; next 1.10; 1.10 date 91.07.24.16.12.58; author hong; state Exp; branches; next 1.9; 1.9 date 91.07.19.15.11.59; author hong; state Exp; branches; next 1.8; 1.8 date 91.07.17.23.46.34; author hong; state Exp; branches; next 1.7; 1.7 date 91.06.25.18.33.05; author hong; state Exp; branches; next 1.6; 1.6 date 90.11.28.20.56.26; author hong; state Exp; branches; next 1.5; 1.5 date 90.11.12.08.14.42; author hong; state Exp; branches; next 1.4; 1.4 date 90.09.25.16.44.21; author kemnitz; state Exp; branches; next 1.3; 1.3 date 90.03.31.19.00.25; author cimarron; state Exp; branches; next 1.2; 1.2 date 90.03.12.16.26.33; author cimarron; state Exp; branches; next 1.1; 1.1 date 90.03.01.15.40.17; author cimarron; state Exp; branches; next ; desc @general changes to add parallelism support, in-memory relations, and various code cleanups. @ 1.17 log @ipc.h protos require ipci.h but someone included them backwards all over the storage directory.. @ text @/* ---------------------------------------------------------------- * FILE * execipc.c * * DESCRIPTION * executor shared memory / semaphore stuff * * This code was swiped from the buffer manager and * somewhat simplified. The whole shared memory / semaphore mess * should probably be thought out better because as it is, * each module that needs shared memory or semaphores has to have * its own functions to create, attach and initialize them. * * In my opinion, several modules should register initialization * routines to be called by a single create/attach mechanism at * the appropriate times. -cim 2/27/90 * * The create/initialize functions are currently called from * {Attach,Create}SharedMemoryAndSemaphores in storage/ipc/ipci.c * which is called from InitCommunication(). * * INTERFACE ROUTINES * the following are used by the executor proper: * * ParallelExecutorEnabled() - has become a macro defined in slaves.h * SetParallelExecutorEnabled() - assign parallel status * GetNumberSlaveBackends() - has become a macro defined in slaves.h * SetNumberSlaveBackends() - assign parallel information * * I_xxx() - initialize the specified semaphore * P_xxx() - P on the specified semaphore * V_xxx() - V on the specified semaphore * * the rest of the functions are used by the ipci.c code during * initialization. * * NOTES * This file exists here and not in the executor directory * because these functions are called by the initialization * code which is compiled into cinterface.a. The executor * directory contains code which is not compiled into cinterface.a * and so this file is here because it should not be there. * It's that simple. * * This is once case where its important to know what code * ends up being compiled where. If this code is moved, this * problem should be kept in mind... * * IDENTIFICATION * $Header: /faerie/aoki/postgres/src/backend/storage/ipc/RCS/execipc.c,v 1.16 1991/11/21 13:18:07 hong Exp aoki $ * ---------------------------------------------------------------- */ /* ---------------- * this group of #includes stolen from ipci.c -- these should * be condensed. * ---------------- */ #include "tmp/c.h" #include "storage/ipci.h" #include "storage/ipc.h" #include "storage/sinval.h" #include "tcop/slaves.h" #include "utils/mcxt.h" #include "utils/log.h" RcsId("$Header: /faerie/aoki/postgres/src/backend/storage/ipc/RCS/execipc.c,v 1.16 1991/11/21 13:18:07 hong Exp aoki $"); /* ---------------- * local defines and stuff * ---------------- */ #define EXEC_SHM_SIZE 1024*1024 #define EXEC_SHM_PERMISSION 0700 IpcMemoryId ExecutorMemoryId = -1; IpcSemaphoreId ExecutorSemaphoreId = -1; IpcSemaphoreId ExecutorSemaphoreId1 = -1; uint16 ExecNumSem = 0; char *ExecutorSharedMemory = NULL; int ExecutorSharedMemorySize = 0; int ParallelExecutorEnableState = 0; int NumberSlaveBackends = 0; int *ExecutorSemaphoreLockCount = NULL; int ExecutorSemaphoreArraySize; int ExecutorSMSemaphore; int ExecutorAbortSemaphore; int ExecutorMasterSemaphore; int ExecutorSlaveSemStart; ProcGroupInfo ProcGroupInfoP; /* have to define it here for postmaster to be happy to link, dumb! */ SlaveInfo SlaveInfoP; int MyPid = -1; SlaveLocalInfoData SlaveLocalInfoD = {1, 0, false, -1, 0, false, NULL, NULL}; /* ---------------------------------------------------------------- * accessor functions * * these are here to provide access to variables kept * hidden to other parts of the system. In particular * * SetParallelExecutorEnabled() and * SetNumberSlaveBackends() * * Are used to specify parallel information obtained * from the command line, * * ParallelExecutorEnabled() * * Is used during initialization to decide whether or * not to allocate shared memory and semaphores and also * at runtime to decide how to plan/execute the query. * * ---------------------------------------------------------------- */ void SetParallelExecutorEnabled(state) bool state; { ParallelExecutorEnableState = (state == true); } void SetNumberSlaveBackends(numslaves) int numslaves; { NumberSlaveBackends = numslaves; } /* ---------------------------------------------------------------- * semaphore operations * * The IpcSemaphoreXXX routines allow operations on named * arrays of semaphores. The executor semaphores are all * kept in a single array and thus managable via a single * IPCKey. That way they are easy to clean up from the outside * world. * * Exec_I, Exec_P and Exec_V are the "internal" semaphore * interface routines to the Ipc code. These routines provide * access to the entire array of executor semaphores. In * addition, these keep track of the number of locks made by * each backend so that when a backend dies, the semaphore locks * can be released. * * I_Start, etc. are routines which access specific-purposed * semaphores in the array. These I_, P_ and V_ routines * are the only ones expected to call the Exec_I, etc routines. * Hence if the code changed or new semaphores are needed, * then this interface guideline should be kept in mind. * * Note: in the following code, we always pass negative * arguments to IpcSemaphore{Lock,Unlock}. Positive * values do the opposite of what the name of the * routine would suggest. * ---------------------------------------------------------------- */ /* -------------------------------- * ExecImmediateReleaseSemaphore releases all the semaphore * locks placed by this backend. This is called by exitpg(). * -------------------------------- */ void ExecImmediateReleaseSemaphore() { int i; int cnt; int semno; IpcSemaphoreId semid; for (i=0; i 0) IpcSemaphoreSilentUnlock(semid, semno, -cnt); } } /* -------------------------------- * Exec_I sets the value of the specified executor semaphore * We set the lock count to 1-value because a semaphore value * of 1 indicates no processes hold locks on that semaphore. * -------------------------------- */ void Exec_I(semno, value) int semno; int value; { int i; IpcSemaphoreId semid; if (semno < IPC_NMAXSEM) { i = semno; semid = ExecutorSemaphoreId; } else { i = semno - IPC_NMAXSEM; semid = ExecutorSemaphoreId1; } IpcSemaphoreSet(semid, i, value); ExecutorSemaphoreLockCount[semno] = 1-value; } /* -------------------------------- * Exec_P requests a P (plaatsen) operation on the specified * executor semaphore. It places "nlocks" locks at once. * -------------------------------- */ void Exec_P(semno, nlocks) int semno; int nlocks; { int i; IpcSemaphoreId semid; if (semno < IPC_NMAXSEM) { i = semno; semid = ExecutorSemaphoreId; } else { i = semno - IPC_NMAXSEM; semid = ExecutorSemaphoreId1; } IpcSemaphoreLock(semid, i, -nlocks); ExecutorSemaphoreLockCount[semno] += nlocks; } /* -------------------------------- * Exec_V requests a V (vrijlaten) operation on the specified * executor semaphore. It removes "nlocks" locks at once. * -------------------------------- */ void Exec_V(semno, nlocks) int semno; int nlocks; { int i; IpcSemaphoreId semid; if (semno < IPC_NMAXSEM) { i = semno; semid = ExecutorSemaphoreId; } else { i = semno - IPC_NMAXSEM; semid = ExecutorSemaphoreId1; } IpcSemaphoreUnlock(semid, i, -nlocks); ExecutorSemaphoreLockCount[semno] -= nlocks; } /* -------------------------------- * external interface to semaphore operations * -------------------------------- */ /* ---------------- * the Start(n) semaphores are used to signal the slave backends * to start processing. * * Since I_Start sets the semaphore to 0, a process doing P_Start * will wait until after some other process executes a V_Start. * * Note: we use local variables because we can tweak them in * dbx easier... * ---------------- */ void I_Start(x) int x; { int value = 0; Exec_I(x + ExecutorSlaveSemStart, value); } void P_Start(x) int x; { int value = 1; Exec_P(x + ExecutorSlaveSemStart, value); } void V_Start(x) int x; { int value = 1; Exec_V(x + ExecutorSlaveSemStart, value); } /* ---------------- * the Finished() semaphore is used for the slaves to signal * the master backend that processing is complete. * * Note: P_Finished() places nslaves locks at once so that * after nslaves execute V_Finished(), the P will be granted. * * Since I_Finished sets the semaphore to 0, a process doing P_Finished * will wait until after some other process executes a V_Finished. * ---------------- */ void I_Finished() { int value = 0; Exec_I(ExecutorMasterSemaphore, value); } void P_Finished() { int value = 1; Exec_P(ExecutorMasterSemaphore, value); } void V_Finished(groupid, scounter, status) int groupid; SharedCounter *scounter; ProcGroupStatus status; { bool is_lastone; if (scounter->count <= 0) { elog(WARN, "V_Finished counter negative.\n"); } #ifdef sequent S_LOCK(&(scounter->exlock)); #else Assert(0); /* you are not supposed to call this routine if you are not running on sequent */ #endif scounter->count--; is_lastone = (bool)(scounter->count == 0); #ifdef sequent S_UNLOCK(&(scounter->exlock)); #endif if (is_lastone) { /* ---------------- * the last slave wakes up the master * ---------------- */ int value = 1; ProcGroupInfoP[groupid].status = status;; Exec_V(ExecutorMasterSemaphore, value); } } void P_FinishedAbort() { int value = GetNumberSlaveBackends(); Exec_P(ExecutorMasterSemaphore, value); } void V_FinishedAbort() { int value = 1; Exec_V(ExecutorMasterSemaphore, value); } /* -------------------------------- * InitMWaitOneLock * * initialize a one producer multiple consumer lock * --------------------------------- */ void InitMWaitOneLock(m1lock) M1Lock *m1lock; { m1lock->count = 0; #ifdef HAS_TEST_AND_SET S_INIT_LOCK(&(m1lock->waitlock)); S_LOCK(&(m1lock->waitlock)); #endif } /* -------------------------------- * MWaitOne * * consumer waits on the producer * --------------------------------- */ void MWaitOne(m1lock) M1Lock *m1lock; { #ifdef HAS_TEST_AND_SET S_LOCK(&(m1lock->waitlock)); m1lock->count--; if (m1lock->count > 0) S_UNLOCK(&(m1lock->waitlock)); #endif } /* -------------------------------- * OneSignalM * * producer wakes up all consumers * --------------------------------- */ void OneSignalM(m1lock, m) M1Lock *m1lock; int m; { m1lock->count = m; #ifdef HAS_TEST_AND_SET S_UNLOCK(&(m1lock->waitlock)); #endif } /* ---------------- * the SharedMemoryMutex semaphore is used to restrict concurrent * updates to the executor shared memory allocator meta-data. * * Since I_SharedMemoryMutex sets the semaphore to 1, a process * doing P_SharedMemoryMutex will be immediately granted the semaphore. * ---------------- */ void I_SharedMemoryMutex() { #ifndef sequent int value = 1; Exec_I(ExecutorSMSemaphore, value); #endif } void P_SharedMemoryMutex() { #ifdef sequent ExclusiveLock(ExecutorSMSemaphore); #else int value = 1; Exec_P(ExecutorSMSemaphore, value); #endif } void V_SharedMemoryMutex() { #ifdef sequent ExclusiveUnlock(ExecutorSMSemaphore); #else int value = 1; Exec_V(ExecutorSMSemaphore, value); #endif } /* ---------------- * the Abort semaphore is used to synchronize abort transaction * processing in the master and slave backends. * * Since I_Abort sets the semaphore to 0, a process doing P_Abort * will wait until after some other process executes a V_Abort. * ---------------- */ void I_Abort() { int value = 0; Exec_I(ExecutorAbortSemaphore, value); } void P_Abort() { int value = 1; Exec_P(ExecutorAbortSemaphore, value); } void V_Abort() { int value = 1; Exec_V(ExecutorAbortSemaphore, value); } /* -------------------------------- * ExecInitExecutorSemaphore * * Note: if the semaphore already exists, IpcSemaphoreCreate() * will return the existing semaphore id. * -------------------------------- */ void ExecInitExecutorSemaphore(key) IPCKey key; { MemoryContext oldContext; int status; /* ---------------- * make certain we are in the top memory context * or else allocated stuff will go away after the * first transaction. * ---------------- */ oldContext = MemoryContextSwitchTo(TopMemoryContext); /* ---------------- * calculate size of semaphore array * ---------------- */ ExecutorSemaphoreArraySize = #ifndef sequent 1 + /* 1 for shared memory meta-data access */ #endif 1 + /* 1 for abort synchronization */ 1 + /* 1 for master backend synchronization */ NumberSlaveBackends; /* n for slave backend synchronization */ /* ---------------- * calculate semaphore numbers (indexes into semaphore array) * ---------------- */ ExecutorAbortSemaphore = 0; ExecutorMasterSemaphore = ExecutorAbortSemaphore + 1; ExecutorSlaveSemStart = ExecutorMasterSemaphore + 1; #ifdef sequent ExecutorSMSemaphore = CreateLock(); #else ExecutorSMSemaphore = ExecutorSlaveSemStart + 1; #endif /* ---------------- * create the executor semaphore array. Note, we don't * want register an on_exit procedure here to kill the semaphores * because this code is executed before we fork(). We have to * register our on_exit progedure after we fork() because only * the master backend should register the on_exit procedure. * ---------------- */ if (ExecutorSemaphoreArraySize <= IPC_NMAXSEM) { ExecutorSemaphoreId = IpcSemaphoreCreateWithoutOnExit(key, ExecutorSemaphoreArraySize, IPCProtection, 0, &status); } else { ExecutorSemaphoreId = IpcSemaphoreCreateWithoutOnExit(key, IPC_NMAXSEM, IPCProtection, 0, &status); ExecutorSemaphoreId1 = IpcSemaphoreCreateWithoutOnExit(key, ExecutorSemaphoreArraySize - IPC_NMAXSEM, IPCProtection, 0, &status); } /* ---------------- * create the semaphore lock count array. This array keeps * track of the number of locks placed by a backend on the * executor semaphores. This is needed for releasing locks * on the semaphores when a backend dies. * ---------------- */ ExecutorSemaphoreLockCount = (int *) palloc(ExecutorSemaphoreArraySize * sizeof(int)); /* ---------------- * register a function to cleanup when we leave. This function * only releases semaphore locks so it should be called by all * backends when they exit. In fact, we have to register this * on_exit procedure here, because later we register the semaphore * kill procedure. If we registered the kill procedure BEFORE * the release procedure, then the unlock code will try to unlock * non-existant semaphores. But this isn't a big problem because * we're about to die anyway... -cim 3/15/90 * ---------------- */ on_exitpg(ExecImmediateReleaseSemaphore, (caddr_t) 0); /* ---------------- * return to old memory context * ---------------- */ (void) MemoryContextSwitchTo(oldContext); } /* ---------------- * ExecSemaphoreOnExit * * this function registers the proper on_exit procedure * for the executor semaphores. This is called in the master * backend AFTER the slaves are fork()'ed so the cleanup * procedure will only fire in the master backend. * ---------------- */ void ExecSemaphoreOnExit(procedure) void (*procedure)(); { on_exitpg(procedure, ExecutorSemaphoreId); if (ExecutorSemaphoreArraySize > IPC_NMAXSEM) on_exitpg(procedure, ExecutorSemaphoreId1); } /* ---------------------------------------------------------------- * shared memory ops * ---------------------------------------------------------------- */ /* -------------------------------- * ExecCreateExecutorSharedMemory * -------------------------------- */ void ExecCreateExecutorSharedMemory(key) IPCKey key; { /* ---------------- * calculate the size of the shared memory segment we need. * XXX make this a function of NumberSlaveBackends. * ---------------- */ ExecutorSharedMemorySize = EXEC_SHM_SIZE; /* ---------------- * create the shared memory segment. As with the creation * of the semaphores, we don't want to register a cleanup procedure * until after we have fork()'ed, and then we should only register * it in the Master backend. * ---------------- */ ExecutorMemoryId = IpcMemoryCreateWithoutOnExit(key, ExecutorSharedMemorySize, EXEC_SHM_PERMISSION); if (ExecutorMemoryId < 0) elog(FATAL, "ExecCreateExecutorSharedMemory: IpcMemoryCreate failed"); } /* -------------------------------- * ExecSharedMemoryOnExit * * this function registers the proper on_exit procedure * for the executor shared memory. * -------------------------------- */ void ExecSharedMemoryOnExit(procedure) void (*procedure)(); { on_exitpg(procedure, ExecutorMemoryId); } /* -------------------------------- * ExecLocateExecutorSharedMemory * -------------------------------- */ void ExecLocateExecutorSharedMemory(key) IPCKey key; { /* ---------------- * find the shared memory segment * ---------------- */ ExecutorMemoryId = IpcMemoryIdGet(key, 0); if (ExecutorMemoryId < 0) elog(FATAL, "ExecLocateExecutorSharedMemory: IpcMemoryIdGet failed"); } /* -------------------------------- * ExecAttachExecutorSharedMemory * -------------------------------- */ void ExecAttachExecutorSharedMemory() { /* ---------------- * attach to the shared segment * ---------------- */ ExecutorSharedMemory = IpcMemoryAttach(ExecutorMemoryId); if (ExecutorSharedMemory == IpcMemAttachFailed) elog(FATAL, "ExecAttachExecutorSharedMemory: IpcMemoryAttach failed"); } @ 1.16 log @fixed a bug that causes hashjoin to hang @ text @d50 1 a50 1 * $Header: RCS/execipc.c,v 1.15 91/11/09 09:52:00 hong Exp $ d61 1 a62 1 #include "storage/ipci.h" d69 1 a69 1 RcsId("$Header: RCS/execipc.c,v 1.15 91/11/09 09:52:00 hong Exp $"); @ 1.15 log @changes in data structure for adjusment of parallelism @ text @d50 1 a50 1 * $Header: storage/ipc/RCS/execipc.c,v 1.14 91/09/27 19:05:15 hong Exp Locker: hong $ d69 1 a69 1 RcsId("$Header: storage/ipc/RCS/execipc.c,v 1.14 91/09/27 19:05:15 hong Exp Locker: hong $"); d99 1 a99 1 SlaveLocalInfoData SlaveLocalInfoD; @ 1.14 log @fixed a bug in V_Finished. @ text @d50 1 a50 1 * $Header: RCS/execipc.c,v 1.13 91/08/29 23:54:07 mer Exp Locker: hong $ d69 1 a69 1 RcsId("$Header: RCS/execipc.c,v 1.13 91/08/29 23:54:07 mer Exp Locker: hong $"); d339 1 a339 1 V_Finished(groupid) d341 2 d346 2 a347 2 if (ProcGroupInfoP[groupid].countdown <= 0) { elog(WARN, "Process group countdown to negative. \n"); d350 1 a350 1 S_LOCK(&(ProcGroupInfoP[groupid].lock)); d355 2 a356 2 ProcGroupInfoP[groupid].countdown--; is_lastone = (bool)(ProcGroupInfoP[groupid].countdown == 0); d358 1 a358 1 S_UNLOCK(&(ProcGroupInfoP[groupid].lock)); d366 1 a366 1 ProcGroupInfoP[groupid].status = FINISHED; @ 1.13 log @purge old lmgr code @ text @d50 1 a50 1 * $Header: /users/mer/postgres/src/storage/ipc/RCS/execipc.c,v 1.12 1991/08/27 14:18:48 hong Exp $ d69 1 a69 1 RcsId("$Header: /users/mer/postgres/src/storage/ipc/RCS/execipc.c,v 1.12 1991/08/27 14:18:48 hong Exp $"); d342 2 d354 1 d358 1 a358 1 if (ProcGroupInfoP[groupid].countdown == 0) { @ 1.12 log @fix to make postmaster link @ text @d50 1 a50 1 * $Header: RCS/execipc.c,v 1.11 91/08/25 13:34:35 hong Exp Locker: hong $ a62 1 #include "storage/pladt.h" a63 1 #include "storage/plparam.h" d69 1 a69 1 RcsId("$Header: RCS/execipc.c,v 1.11 91/08/25 13:34:35 hong Exp Locker: hong $"); d181 1 a181 1 if (i < NMAXSEM) { d186 1 a186 1 semno = i - NMAXSEM; d210 1 a210 1 if (semno < NMAXSEM) { d215 1 a215 1 i = semno - NMAXSEM; d236 1 a236 1 if (semno < NMAXSEM) { d241 1 a241 1 i = semno - NMAXSEM; d262 1 a262 1 if (semno < NMAXSEM) { d267 1 a267 1 i = semno - NMAXSEM; d557 1 a557 1 if (ExecutorSemaphoreArraySize <= NMAXSEM) { d568 1 a568 1 NMAXSEM, d574 1 a574 1 ExecutorSemaphoreArraySize - NMAXSEM, d625 1 a625 1 if (ExecutorSemaphoreArraySize > NMAXSEM) @ 1.11 log @introduced a new kind of lock of master slave sync. @ text @d50 1 a50 1 * $Header: RCS/execipc.c,v 1.10 91/07/24 16:12:58 hong Exp Locker: hong $ d71 1 a71 1 RcsId("$Header: RCS/execipc.c,v 1.10 91/07/24 16:12:58 hong Exp Locker: hong $"); d97 6 a338 3 ProcGroupInfo ProcGroupInfoP; /* have to define it here for postmaster to be happy to link, dumb! */ @ 1.10 log @turned some small functions into macros @ text @d50 1 a50 1 * $Header: RCS/execipc.c,v 1.9 91/07/19 15:11:59 hong Exp Locker: hong $ d71 1 a71 1 RcsId("$Header: RCS/execipc.c,v 1.9 91/07/19 15:11:59 hong Exp Locker: hong $"); a333 14 void P_FinishedAbort() { int value = GetNumberSlaveBackends(); Exec_P(ExecutorMasterSemaphore, value); } void V_FinishedAbort() { int value = 1; Exec_V(ExecutorMasterSemaphore, value); } d364 68 @ 1.9 log @to make postgres happy to link @ text @a24 2 * ExecGetExecutorSharedMemory() - get the start of shared mem * ExecGetExecutorSharedMemorySize()- get the size of shared segment d27 1 a27 1 * GetNumberSlaveBackends() - return parallel information d50 1 a50 1 * $Header: RCS/execipc.c,v 1.8 91/07/17 23:46:34 hong Exp $ d71 1 a71 1 RcsId("$Header: RCS/execipc.c,v 1.8 91/07/17 23:46:34 hong Exp $"); a117 5 char * ExecGetExecutorSharedMemory() { return ExecutorSharedMemory; } a118 6 int ExecGetExecutorSharedMemorySize() { return ExecutorSharedMemorySize; } a130 6 } int GetNumberSlaveBackends() { return NumberSlaveBackends; @ 1.8 log @changes to support inter-fragment and inter-query parallelism @ text @d52 1 a52 1 * $Header: RCS/execipc.c,v 1.7 91/06/25 18:33:05 hong Exp Locker: hong $ d73 1 a73 1 RcsId("$Header: RCS/execipc.c,v 1.7 91/06/25 18:33:05 hong Exp Locker: hong $"); d367 3 d377 1 d379 4 d384 1 d386 1 @ 1.7 log @changed parallel executor shared memory semaphore to spin lock to speedup up the plan copying to shared memory @ text @d27 1 a27 1 * ParallelExecutorEnabled() - return parallel status d52 1 a52 1 * $Header: RCS/execipc.c,v 1.6 90/11/28 20:56:26 hong Exp Locker: hong $ d69 1 d73 1 a73 1 RcsId("$Header: RCS/execipc.c,v 1.6 90/11/28 20:56:26 hong Exp Locker: hong $"); a131 6 int ParallelExecutorEnabled() { return ParallelExecutorEnableState; } d347 1 a347 2 P_Finished(nprocs) int nprocs; d349 2 a350 1 Exec_P(ExecutorMasterSemaphore, nprocs); d354 1 a354 1 V_Finished() d356 7 d365 21 @ 1.6 log @temporarily increased the maximum number of parallel backend to 50 @ text @d52 1 a52 1 * $Header: RCS/execipc.c,v 1.5 90/11/12 08:14:42 hong Exp Locker: hong $ d72 1 a72 1 RcsId("$Header: RCS/execipc.c,v 1.5 90/11/12 08:14:42 hong Exp Locker: hong $"); d376 1 d379 1 d385 3 d390 1 d396 3 d401 1 d460 1 d462 1 d471 1 a471 2 ExecutorSMSemaphore = 0; ExecutorAbortSemaphore = ExecutorSMSemaphore + 1; d474 5 @ 1.5 log @increased parallel executor shared memory @ text @d52 1 a52 1 * $Header: RCS/execipc.c,v 1.4 90/09/25 16:44:21 kemnitz Exp $ d67 1 d72 1 a72 1 RcsId("$Header: RCS/execipc.c,v 1.4 90/09/25 16:44:21 kemnitz Exp $"); d83 1 d197 2 d201 8 d211 1 a211 1 IpcSemaphoreSilentUnlock(ExecutorSemaphoreId, i, -cnt); d227 12 a238 1 IpcSemaphoreSet(ExecutorSemaphoreId, semno, value); d253 12 a264 1 IpcSemaphoreLock(ExecutorSemaphoreId, semno, -nlocks); d279 12 a290 1 IpcSemaphoreUnlock(ExecutorSemaphoreId, semno, -nlocks); d472 1 d479 16 d540 2 @ 1.4 log @Updating from revision 1.3 to revision 1.5 @ text @d52 1 a52 1 * $Header: RCS/execipc.c,v 1.5 90/09/06 14:40:27 hong Exp $ d71 1 a71 1 RcsId("$Header: RCS/execipc.c,v 1.5 90/09/06 14:40:27 hong Exp $"); d77 1 a77 1 #define EXEC_SHM_SIZE 65535 @ 1.3 log @*** empty log message *** @ text @d52 1 a52 1 * $Header: RCS/execipc.c,v 1.2 90/03/12 16:26:33 cimarron Exp $ d61 1 a61 1 #include "c.h" d63 4 a66 4 #include "ipc.h" #include "log.h" #include "pladt.h" #include "sinval.h" d68 2 a69 2 #include "ipci.h" #include "mcxt.h" d71 1 a71 1 RcsId("$Header: RCS/execipc.c,v 1.2 90/03/12 16:26:33 cimarron Exp $"); d307 2 a308 1 P_Finished() d310 1 a310 3 int nslaves; nslaves = GetNumberSlaveBackends(); Exec_P(ExecutorMasterSemaphore, nslaves); @ 1.2 log @Integration Checkin @ text @d34 1 a34 1 * V_xxxV() - V on the specified semaphore d52 1 a52 1 * $Header: RCS/execipc.c,v 1.1 90/03/01 15:40:17 cimarron Exp $ d71 1 a71 1 RcsId("$Header: RCS/execipc.c,v 1.1 90/03/01 15:40:17 cimarron Exp $"); d92 1 d176 5 d195 1 a195 1 d199 1 a199 1 IpcSemaphoreUnlock(ExecutorSemaphoreId, i, cnt); d205 2 d216 1 a216 1 ExecutorSemaphoreLockCount[semno] = -value; d221 1 a221 1 * executor semaphore. It places nlocks-locks at once. d236 1 a236 1 * executor semaphore. It removes nlocks-locks at once. a250 3 * * Note: P_Finished() places nslaves-1 locks at once so that * after nslaves execute V_Finished(), the P will be granted. d256 6 d268 2 a269 1 Exec_I(x + ExecutorSlaveSemStart, 0); d276 2 a277 1 Exec_P(x + ExecutorSlaveSemStart, 1); d284 2 a285 1 Exec_V(x + ExecutorSlaveSemStart, 1); d291 6 d302 2 a303 1 Exec_I(ExecutorMasterSemaphore, 0); d311 1 a311 1 Exec_P(ExecutorMasterSemaphore, nslaves-1); d317 2 a318 1 Exec_V(ExecutorMasterSemaphore, 1); d324 3 d332 2 a333 1 Exec_I(ExecutorSMSemaphore, 0); d339 2 a340 1 Exec_P(ExecutorSMSemaphore, 1); d346 2 a347 1 Exec_V(ExecutorSMSemaphore, 1); d350 30 a379 1 /* -------------------------------- d386 1 a386 1 d392 1 a392 1 d400 1 a400 1 d407 1 d410 1 a410 1 d416 2 a417 1 ExecutorMasterSemaphore = ExecutorSMSemaphore + 1; d419 1 a419 1 d421 5 a425 2 * create the executor semaphore array and initialize all * semaphores to 0. d428 7 a434 6 ExecutorSemaphoreId = IpcSemaphoreCreate(key, ExecutorSemaphoreArraySize, IPCProtection, 0, /* initial value */ &status); d444 1 a444 1 d446 8 a453 1 * register a function to cleanup when we leave d465 17 a481 1 /* ---------------------------------------------------------------- d503 4 a506 1 * create the shared memory segment d509 4 a512 3 ExecutorMemoryId = IpcMemoryCreate(key, ExecutorSharedMemorySize, EXEC_SHM_PERMISSION); d516 1 d518 12 @ 1.1 log @Initial revision @ text @a0 1 d26 5 a30 2 * ExecGetAndHoldSemaphore() - grab the semaphore * ExecReleaseSemaphore() - release the semaphore d32 4 d52 1 a52 1 * $Header$ d69 1 d71 1 a71 1 RcsId("$Header$"); a76 3 #define EXEC_SEM_INIT 255 #define EXEC_SEM_LOCK (-255) d85 1 d88 1 d90 5 d99 14 a112 1 * hidden to other parts of the system. d123 6 d148 6 d156 19 d177 1 d179 2 a180 1 * ExecImmediateReleaseSemaphore d187 7 a193 3 if (ExecNumSem != 0) { IpcSemaphoreUnlock(ExecutorSemaphoreId, 0, EXEC_SEM_LOCK); ExecNumSem = 0; d198 1 a198 1 * ExecGetAndHoldSemaphore d203 3 a205 1 ExecGetAndHoldSemaphore() d207 2 a208 5 if (ExecNumSem == 0) { IpcSemaphoreLock(ExecutorSemaphoreId, 0, EXEC_SEM_LOCK); } ExecNumSem += 1; d212 2 a213 1 * ExecReleaseSemaphore d218 3 a220 1 ExecReleaseSemaphore() d222 2 a223 4 if (ExecNumSem >= 1) { IpcSemaphoreUnlock(ExecutorSemaphoreId, 0, EXEC_SEM_LOCK); ExecNumSem = 0; } d227 96 a329 1 void d333 1 d337 3 a339 1 * create the executor semaphore d342 24 d367 1 a367 1 1, d369 1 a369 1 EXEC_SEM_INIT, d373 10 d387 6 a396 4 * * Note: the shared memory stuff relies on the semaphore * stuff so the semaphore stuff should be initialized * first. d410 7 d421 1 a421 1 EXEC_SHM_SIZE, @