mirror of https://github.com/postgres/postgres
Also update copyright to be ours, with approval from Jan.WIN32_DEV
parent
d670bf378c
commit
1a67e4869c
@ -0,0 +1,239 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* sem.c |
||||
* Microsoft Windows Win32 Semaphores Emulation |
||||
* |
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#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; |
||||
|
||||
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 */ |
||||
win32_sem_set_hdr* 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 (int 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 { |
||||
// Blow away what we've got right now...
|
||||
for (int 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; |
||||
if (sops[0].sem_flg & IPC_NOWAIT) |
||||
ret = WaitForSingleObject(cur_handle, 0); |
||||
else |
||||
ret = WaitForSingleObject(cur_handle, INFINITE); |
||||
|
||||
if (ret == WAIT_OBJECT_0) { |
||||
/* We got it! */ |
||||
sem_counts[sops[0].sem_num]--; |
||||
return 0; |
||||
} 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; |
||||
} |
@ -0,0 +1,120 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* shm.c |
||||
* Microsoft Windows Win32 Shared Memory Emulation |
||||
* |
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
#include "windows.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <errno.h> |
||||
|
||||
static DWORD s_segsize = 0; |
||||
|
||||
/* Detach from a shared mem area based on its address */ |
||||
int |
||||
shmdt(const void *shmaddr) |
||||
{ |
||||
if (UnmapViewOfFile(shmaddr)) |
||||
return 0; |
||||
else |
||||
return -1; |
||||
} |
||||
|
||||
/* Attach to an existing area */ |
||||
void * |
||||
shmat(int memId, void* shmaddr, int flag) |
||||
{ |
||||
/* KEW_TODO -- shmat needs to count # attached to shared mem */ |
||||
void *lpmem = MapViewOfFileEx((HANDLE)memId, |
||||
FILE_MAP_WRITE | FILE_MAP_READ, |
||||
0, 0, /* (DWORD)pshmdsc->segsize */ s_segsize, shmaddr); |
||||
|
||||
if (lpmem == NULL) { |
||||
lpmem = (void *)-1; |
||||
errno = GetLastError(); |
||||
} |
||||
|
||||
return lpmem; |
||||
} |
||||
|
||||
/* Control a shared mem area */ |
||||
int |
||||
shmctl(int shmid, int flag, struct shmid_ds * dummy) |
||||
{ |
||||
if (flag == IPC_RMID) |
||||
{ |
||||
/* Delete the area */ |
||||
CloseHandle((HANDLE)shmid); |
||||
return 0; |
||||
} |
||||
if (flag == IPC_STAT) |
||||
{ |
||||
/* Can only test for if exists */ |
||||
int hmap = shmget(shmid, 0, 0); |
||||
if (hmap < 0) { |
||||
/* Shared memory does not exist */ |
||||
errno = EINVAL; |
||||
return -1; |
||||
} |
||||
else { |
||||
/* Shared memory does exist and must be in use */ |
||||
shmctl(hmap, IPC_RMID, NULL); /* Release our hold on it */ |
||||
errno = 0; |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
errno = EINVAL; |
||||
return -1; |
||||
} |
||||
|
||||
/* Get an area based on the IPC key */ |
||||
int |
||||
shmget(int memKey, int size, int flag) |
||||
{ |
||||
HANDLE hmap; |
||||
char szShareMem[32]; |
||||
DWORD dwRet; |
||||
|
||||
s_segsize = size; |
||||
sprintf(szShareMem, "sharemem.%d", memKey); |
||||
|
||||
if (flag & IPC_CREAT) { |
||||
hmap = CreateFileMapping((HANDLE)0xFFFFFFFF, /* Use the swap file */ |
||||
NULL, |
||||
PAGE_READWRITE, /* Memory is Read/Write */ |
||||
0L, /* Size Upper 32 Bits */ |
||||
(DWORD)s_segsize, /* Size Lower 32 bits*/ |
||||
szShareMem); |
||||
} |
||||
else { |
||||
hmap = OpenFileMapping(FILE_MAP_ALL_ACCESS, |
||||
FALSE, |
||||
szShareMem); |
||||
if (!hmap) { |
||||
errno = ENOENT; |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
dwRet = GetLastError(); |
||||
if (dwRet == ERROR_ALREADY_EXISTS && hmap && (flag & (IPC_CREAT | IPC_EXCL))) { |
||||
/* Caller wanted to create the segment -- error if already exists */ |
||||
CloseHandle(hmap); |
||||
errno = EEXIST; |
||||
return -1; |
||||
} |
||||
else if (!hmap) |
||||
{ |
||||
/* Unable to get shared memory */ |
||||
return -1; |
||||
} |
||||
|
||||
return (int)hmap; |
||||
} |
Loading…
Reference in new issue