3 * $Header: /cvsroot/pgpool/pgpool-II/pool_shmem.c,v 1.3.2.2 2009/08/22 04:19:49 t-ishii Exp $
5 * pgpool: a language independent connection pool server for PostgreSQL
6 * written by Tatsuo Ishii
8 * Portions Copyright (c) 2003-2009, PgPool Global Development Group
9 * Portions Copyright (c) 2003-2004, PostgreSQL Global Development Group
11 * Permission to use, copy, modify, and distribute this software and
12 * its documentation for any purpose and without fee is hereby
13 * granted, provided that the above copyright notice appear in all
14 * copies and that both that copyright notice and this permission
15 * notice appear in supporting documentation, and that the name of the
16 * author not be used in advertising or publicity pertaining to
17 * distribution of the software without specific, written prior
18 * permission. The author makes no representations about the
19 * suitability of this software for any purpose. It is provided "as
20 * is" without express or implied warranty.
32 #ifdef SHM_SHARE_MMU /* use intimate shared memory on Solaris */
33 #define PG_SHMAT_FLAGS SHM_SHARE_MMU
35 #define PG_SHMAT_FLAGS 0
39 #define MAX_ON_EXITS 20
43 void (*function) (int code, Datum arg);
45 } on_shmem_exit_list[MAX_ON_EXITS];
47 static int on_shmem_exit_index;
50 static void IpcMemoryDetach(int status, Datum shmaddr);
51 static void IpcMemoryDelete(int status, Datum shmId);
55 * Create a shared memory segment of the given size and initialize. Also,
56 * register an on_shmem_exit callback to release the storage.
59 pool_shared_memory_create(size_t size)
64 /* Try to create new segment */
65 shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | IPCProtection);
69 pool_error("could not create shared memory segment: %s",
74 /* Register on-exit routine to delete the new segment */
75 on_shmem_exit(IpcMemoryDelete, shmid);
77 /* OK, should be able to attach to the segment */
78 memAddress = shmat(shmid, NULL, PG_SHMAT_FLAGS);
80 if (memAddress == (void *) -1)
82 pool_error("shmat(id=%d) failed: %s", shmid, strerror(errno));
86 /* Register on-exit routine to detach new segment before deleting */
87 on_shmem_exit(IpcMemoryDetach, (Datum) memAddress);
93 * Removes a shared memory segment from process' address spaceq (called as
94 * an on_shmem_exit callback, hence funny argument list)
97 IpcMemoryDetach(int status, Datum shmaddr)
99 if (shmdt((void *) shmaddr) < 0)
100 pool_log("shmdt(%p) failed: %s", (void *) shmaddr, strerror(errno));
104 * Deletes a shared memory segment (called as an on_shmem_exit callback,
105 * hence funny argument list)
108 IpcMemoryDelete(int status, Datum shmId)
110 struct shmid_ds shmStat;
113 * Is a previously-existing shmem segment still existing and in use?
115 if (shmctl(shmId, IPC_STAT, &shmStat) < 0
116 && (errno == EINVAL || errno == EACCES))
118 else if (shmStat.shm_nattch != 0)
121 if (shmctl(shmId, IPC_RMID, NULL) < 0)
122 pool_log("shmctl(%lu, %d, 0) failed: %s",
123 shmId, IPC_RMID, strerror(errno));
127 pool_shmem_exit(int code)
133 * Run all of the on_shmem_exit routines --- but don't actually exit. This
134 * is used by the postmaster to re-initialize shared memory and semaphores
135 * after a backend dies horribly.
140 pool_debug("shmem_exit(%d)", code);
143 * Call all the registered callbacks.
145 * As with proc_exit(), we remove each callback from the list before
146 * calling it, to avoid infinite loop in case of error.
148 while (--on_shmem_exit_index >= 0)
149 (*on_shmem_exit_list[on_shmem_exit_index].function) (code,
150 on_shmem_exit_list[on_shmem_exit_index].arg);
152 on_shmem_exit_index = 0;
156 * This function adds a callback function to the list of functions invoked
160 on_shmem_exit(void (*function) (int code, Datum arg), Datum arg)
162 if (on_shmem_exit_index >= MAX_ON_EXITS)
163 pool_error("out of on_shmem_exit slots");
165 on_shmem_exit_list[on_shmem_exit_index].function = function;
166 on_shmem_exit_list[on_shmem_exit_index].arg = arg;
168 ++on_shmem_exit_index;
172 * This function clears all on_proc_exit() and on_shmem_exit() registered
173 * functions. This is used just after forking a backend, so that the
174 * backend doesn't believe it should call the postmaster's on-exit routines
180 on_shmem_exit_index = 0;