mirror of https://github.com/postgres/postgres
parent
f0df096785
commit
366682fb66
@ -1,270 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* sema.c |
||||
* Microsoft Windows Win32 Semaphores Emulation |
||||
* |
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group |
||||
* |
||||
* IDENTIFICATION |
||||
* $PostgreSQL: pgsql/src/backend/port/win32/sema.c,v 1.13 2006/04/09 19:21:34 tgl Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
#include "storage/shmem.h" |
||||
|
||||
#include <errno.h> |
||||
|
||||
typedef struct |
||||
{ |
||||
int m_numSems; |
||||
off_t m_semaphoreHandles; |
||||
/* offset from beginning of header */ |
||||
off_t m_semaphoreCounts; |
||||
/* offset from beginning of header */ |
||||
} win32_sem_set_hdr; |
||||
|
||||
/* Control of a semaphore pool. The pool is an area in which we stored all
|
||||
** the semIds of the pool. The first long is the number of semaphore |
||||
** allocated in the pool followed by semaphore handles |
||||
*/ |
||||
|
||||
int |
||||
semctl(int semId, int semNum, int flag, union semun semun) |
||||
{ |
||||
win32_sem_set_hdr *the_set = (win32_sem_set_hdr *) MAKE_PTR(semId); |
||||
|
||||
/* semNum might be 0 */ |
||||
/* semun.array contains the sem initial values */ |
||||
int *sem_counts = (int *) ((off_t) the_set + the_set->m_semaphoreCounts); |
||||
|
||||
/* Fix the count of all sem of the pool to semun.array */ |
||||
if (flag == SETALL) |
||||
{ |
||||
int i; |
||||
struct sembuf sops; |
||||
|
||||
sops.sem_flg = IPC_NOWAIT; |
||||
|
||||
for (i = 0; i < the_set->m_numSems; ++i) |
||||
{ |
||||
if (semun.array[i] == sem_counts[i]) |
||||
continue; /* Nothing to do */ |
||||
|
||||
if (semun.array[i] < sem_counts[i]) |
||||
sops.sem_op = -1; |
||||
else |
||||
sops.sem_op = 1; |
||||
|
||||
sops.sem_num = i; |
||||
|
||||
/* Quickly lock/unlock the semaphore (if we can) */ |
||||
if (semop(semId, &sops, 1) < 0) |
||||
return -1; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
/* Fix the count of one semaphore to semun.val */ |
||||
else if (flag == SETVAL) |
||||
{ |
||||
if (semun.val != sem_counts[semNum]) |
||||
{ |
||||
struct sembuf sops; |
||||
|
||||
sops.sem_flg = IPC_NOWAIT; |
||||
sops.sem_num = semNum; |
||||
|
||||
if (semun.val < sem_counts[semNum]) |
||||
sops.sem_op = -1; |
||||
else |
||||
sops.sem_op = 1; |
||||
|
||||
/* Quickly lock/unlock the semaphore (if we can) */ |
||||
if (semop(semId, &sops, 1) < 0) |
||||
return -1; |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/* Delete the pool */ |
||||
else if (flag == IPC_RMID) |
||||
{ |
||||
int i; |
||||
HANDLE *sem_handles = (HANDLE *) ((off_t) the_set + the_set->m_semaphoreHandles); |
||||
|
||||
/* Loop over all semaphore to delete them */ |
||||
for (i = 0; i < the_set->m_numSems; ++i) |
||||
CloseHandle(sem_handles[i]); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/* Get the current semaphore count */ |
||||
else if (flag == GETNCNT) |
||||
return the_set->m_numSems; |
||||
|
||||
/* Get the current semaphore count of the first semaphore in the pool */ |
||||
else if (flag == GETVAL) |
||||
return sem_counts[semNum]; |
||||
|
||||
/* Other commands not yet supported */ |
||||
else |
||||
{ |
||||
errno = EINVAL; |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
/* Find a pool id based on IPC key */ |
||||
int |
||||
semget(int semKey, int semNum, int flags) |
||||
{ |
||||
char semname[32]; |
||||
char cur_num[20]; |
||||
DWORD last_error; |
||||
char *num_part; |
||||
bool ans = true; |
||||
SECURITY_ATTRIBUTES sec_attrs; |
||||
HANDLE cur_handle; |
||||
bool found = false; |
||||
Size sem_set_size = sizeof(win32_sem_set_hdr) + semNum * (sizeof(HANDLE) + sizeof(int)); |
||||
HANDLE *sem_handles = NULL; |
||||
int *sem_counts = NULL; |
||||
int i; |
||||
win32_sem_set_hdr *new_set; |
||||
|
||||
sec_attrs.nLength = sizeof(sec_attrs); |
||||
sec_attrs.lpSecurityDescriptor = NULL; |
||||
sec_attrs.bInheritHandle = TRUE; |
||||
|
||||
sprintf(semname, "PG_SEMSET.%d.", semKey); |
||||
num_part = semname + strlen(semname); |
||||
|
||||
strcpy(num_part, _itoa(_getpid() * -1, cur_num, 10)); /* For shared memory,
|
||||
* include the pid */ |
||||
new_set = (win32_sem_set_hdr *) ShmemInitStruct(semname, sem_set_size, &found); |
||||
|
||||
if (found) |
||||
{ |
||||
/* This should *never* happen */ |
||||
errno = EEXIST; |
||||
return -1; |
||||
} |
||||
|
||||
new_set->m_numSems = semNum; |
||||
new_set->m_semaphoreHandles = sizeof(win32_sem_set_hdr); |
||||
/* array starts after header */ |
||||
new_set->m_semaphoreCounts = new_set->m_semaphoreHandles + (sizeof(HANDLE) * semNum); |
||||
|
||||
sem_handles = (HANDLE *) ((off_t) new_set + new_set->m_semaphoreHandles); |
||||
sem_counts = (int *) ((off_t) new_set + new_set->m_semaphoreCounts); |
||||
|
||||
for (i = 0; i < semNum && ans; ++i) |
||||
{ |
||||
strcpy(num_part, _itoa(i, cur_num, 10)); |
||||
|
||||
if (flags & IPC_CREAT) |
||||
cur_handle = CreateSemaphore(&sec_attrs, 0, 1, semname); |
||||
else |
||||
cur_handle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, TRUE, semname); |
||||
|
||||
sem_handles[i] = cur_handle; |
||||
|
||||
last_error = GetLastError(); |
||||
if (!cur_handle) |
||||
{ |
||||
errno = EACCES; |
||||
ans = false; |
||||
} |
||||
else if (last_error == ERROR_ALREADY_EXISTS && (flags & (IPC_CREAT | IPC_EXCL))) |
||||
{ |
||||
errno = EEXIST; |
||||
ans = false; |
||||
} |
||||
} |
||||
|
||||
if (ans) |
||||
return MAKE_OFFSET(new_set); |
||||
else |
||||
{ |
||||
int i; |
||||
|
||||
/* Blow away what we've got right now... */ |
||||
for (i = 0; i < semNum; ++i) |
||||
{ |
||||
if (sem_handles[i]) |
||||
CloseHandle(sem_handles[i]); |
||||
else |
||||
break; |
||||
} |
||||
|
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
/* Acquire or release in the semaphore pool */ |
||||
int |
||||
semop(int semId, struct sembuf * sops, int nsops) |
||||
{ |
||||
win32_sem_set_hdr *the_set = (win32_sem_set_hdr *) MAKE_PTR(semId); |
||||
HANDLE *sem_handles = (HANDLE *) ((off_t) the_set + the_set->m_semaphoreHandles); |
||||
int *sem_counts = (int *) ((off_t) the_set + the_set->m_semaphoreCounts); |
||||
HANDLE cur_handle; |
||||
|
||||
if (nsops != 1) |
||||
{ |
||||
/*
|
||||
* Not supported (we return on 1st success, and don't cancel earlier |
||||
* ops) |
||||
*/ |
||||
errno = E2BIG; |
||||
return -1; |
||||
} |
||||
|
||||
cur_handle = sem_handles[sops[0].sem_num]; |
||||
|
||||
if (sops[0].sem_op == -1) |
||||
{ |
||||
DWORD ret; |
||||
HANDLE wh[2]; |
||||
|
||||
wh[0] = cur_handle; |
||||
wh[1] = pgwin32_signal_event; |
||||
|
||||
ret = WaitForMultipleObjectsEx(2, wh, FALSE, (sops[0].sem_flg & IPC_NOWAIT) ? 0 : INFINITE, TRUE); |
||||
|
||||
if (ret == WAIT_OBJECT_0) |
||||
{ |
||||
/* We got it! */ |
||||
sem_counts[sops[0].sem_num]--; |
||||
return 0; |
||||
} |
||||
else if (ret == WAIT_OBJECT_0 + 1 || ret == WAIT_IO_COMPLETION) |
||||
{ |
||||
/* Signal event is set - we have a signal to deliver */ |
||||
pgwin32_dispatch_queued_signals(); |
||||
errno = EINTR; |
||||
} |
||||
else if (ret == WAIT_TIMEOUT) |
||||
/* Couldn't get it */ |
||||
errno = EAGAIN; |
||||
else |
||||
errno = EIDRM; |
||||
} |
||||
else if (sops[0].sem_op > 0) |
||||
{ |
||||
/* Don't want the lock anymore */ |
||||
sem_counts[sops[0].sem_num]++; |
||||
ReleaseSemaphore(cur_handle, sops[0].sem_op, NULL); |
||||
return 0; |
||||
} |
||||
else |
||||
/* Not supported */ |
||||
errno = ERANGE; |
||||
|
||||
/* If we get down here, then something is wrong */ |
||||
return -1; |
||||
} |
Loading…
Reference in new issue