1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Semaphores Emulation
6 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
9 * $PostgreSQL: pgsql/src/backend/port/win32/sema.c,v 1.5 2004/02/12 20:37:34 momjian Exp $
11 *-------------------------------------------------------------------------
15 #include "storage/shmem.h"
22 off_t m_semaphoreHandles;
23 /* offset from beginning of header */
24 off_t m_semaphoreCounts;
25 /* offset from beginning of header */
28 /* Control of a semaphore pool. The pool is an area in which we stored all
29 ** the semIds of the pool. The first long is the number of semaphore
30 ** allocated in the pool followed by semaphore handles
34 semctl(int semId, int semNum, int flag, union semun semun)
36 win32_sem_set_hdr *the_set = (win32_sem_set_hdr *) MAKE_PTR(semId);
38 /* semNum might be 0 */
39 /* semun.array contains the sem initial values */
40 int *sem_counts = (int *) ((off_t) the_set + the_set->m_semaphoreCounts);
42 /* Fix the count of all sem of the pool to semun.array */
48 sops.sem_flg = IPC_NOWAIT;
50 for (i = 0; i < the_set->m_numSems; ++i)
52 if (semun.array[i] == sem_counts[i])
53 continue; /* Nothing to do */
55 if (semun.array[i] < sem_counts[i])
62 /* Quickly lock/unlock the semaphore (if we can) */
63 if (semop(semId, &sops, 1) < 0)
69 /* Fix the count of one semaphore to semun.val */
70 else if (flag == SETVAL)
72 if (semun.val != sem_counts[semNum])
76 sops.sem_flg = IPC_NOWAIT;
77 sops.sem_num = semNum;
79 if (semun.val < sem_counts[semNum])
84 /* Quickly lock/unlock the semaphore (if we can) */
85 if (semop(semId, &sops, 1) < 0)
93 else if (flag == IPC_RMID)
96 HANDLE *sem_handles = (HANDLE *) ((off_t) the_set + the_set->m_semaphoreHandles);
98 /* Loop over all semaphore to delete them */
99 for (i = 0; i < the_set->m_numSems; ++i)
100 CloseHandle(sem_handles[i]);
105 /* Get the current semaphore count */
106 else if (flag == GETNCNT)
107 return the_set->m_numSems;
109 /* Get the current semaphore count of the first semaphore in the pool */
110 else if (flag == GETVAL)
111 return sem_counts[semNum];
113 /* Other commands not yet supported */
121 /* Find a pool id based on IPC key */
123 semget(int semKey, int semNum, int flags)
130 SECURITY_ATTRIBUTES sec_attrs;
133 Size sem_set_size = sizeof(win32_sem_set_hdr) + semNum * (sizeof(HANDLE) + sizeof(int));
134 HANDLE *sem_handles = NULL;
135 int *sem_counts = NULL;
138 sec_attrs.nLength = sizeof(sec_attrs);
139 sec_attrs.lpSecurityDescriptor = NULL;
140 sec_attrs.bInheritHandle = TRUE;
142 sprintf(semname, "PG_SEMSET.%d.", semKey);
143 num_part = semname + strlen(semname);
145 strcpy(num_part, _itoa(_getpid() * -1, cur_num, 10)); /* For shared memory,
147 win32_sem_set_hdr *new_set = (win32_sem_set_hdr *) ShmemInitStruct(semname, sem_set_size, &found);
151 /* This should *never* happen */
156 new_set->m_numSems = semNum;
157 new_set->m_semaphoreHandles = sizeof(win32_sem_set_hdr);
158 /* array starts after header */
159 new_set->m_semaphoreCounts = new_set->m_semaphoreHandles + (sizeof(HANDLE) * semNum);
161 sem_handles = (HANDLE *) ((off_t) new_set + new_set->m_semaphoreHandles);
162 sem_counts = (int *) ((off_t) new_set + new_set->m_semaphoreCounts);
164 for (i = 0; i < semNum && ans; ++i)
166 strcpy(num_part, _itoa(i, cur_num, 10));
168 if (flags & IPC_CREAT)
169 cur_handle = CreateSemaphore(&sec_attrs, 0, 1, semname);
171 cur_handle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, TRUE, semname);
173 sem_handles[i] = cur_handle;
175 last_error = GetLastError();
181 else if (last_error == ERROR_ALREADY_EXISTS && (flags & (IPC_CREAT | IPC_EXCL)))
189 return MAKE_OFFSET(new_set);
194 /* Blow away what we've got right now... */
195 for (i = 0; i < semNum; ++i)
198 CloseHandle(sem_handles[i]);
207 /* Acquire or release in the semaphore pool */
209 semop(int semId, struct sembuf * sops, int nsops)
211 win32_sem_set_hdr *the_set = (win32_sem_set_hdr *) MAKE_PTR(semId);
212 HANDLE *sem_handles = (HANDLE *) ((off_t) the_set + the_set->m_semaphoreHandles);
213 int *sem_counts = (int *) ((off_t) the_set + the_set->m_semaphoreCounts);
219 * Not supported (we return on 1st success, and don't cancel
226 cur_handle = sem_handles[sops[0].sem_num];
228 if (sops[0].sem_op == -1)
232 if (sops[0].sem_flg & IPC_NOWAIT)
233 ret = WaitForSingleObject(cur_handle, 0);
235 ret = WaitForSingleObject(cur_handle, INFINITE);
237 if (ret == WAIT_OBJECT_0)
240 sem_counts[sops[0].sem_num]--;
243 else if (ret == WAIT_TIMEOUT)
244 /* Couldn't get it */
249 else if (sops[0].sem_op > 0)
251 /* Don't want the lock anymore */
252 sem_counts[sops[0].sem_num]++;
253 ReleaseSemaphore(cur_handle, sops[0].sem_op, NULL);
260 /* If we get down here, then something is wrong */