From 20ead395c74906acfd95f61aaa1583bfaff02364 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 24 Apr 2003 21:23:01 +0000 Subject: Add Win32 shmem/sema prototypes. --- src/backend/port/sysv_shmem.c | 6 +- src/backend/port/win32/sem.c | 256 ---------------------------------------- src/backend/port/win32/sema.c | 257 +++++++++++++++++++++++++++++++++++++++++ src/backend/port/win32/shm.c | 128 -------------------- src/backend/port/win32/shmem.c | 127 ++++++++++++++++++++ src/include/port/win32.h | 52 ++++++++- 6 files changed, 440 insertions(+), 386 deletions(-) delete mode 100644 src/backend/port/win32/sem.c create mode 100644 src/backend/port/win32/sema.c delete mode 100644 src/backend/port/win32/shm.c create mode 100644 src/backend/port/win32/shmem.c diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index fc5c6e83c19..9e5f8f9457a 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -10,7 +10,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.5 2003/03/25 16:15:44 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.6 2003/04/24 21:23:01 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -30,6 +30,10 @@ #include #endif +#ifdef WIN32 +#include "win32/shmem.h" +#endif + #include "miscadmin.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" diff --git a/src/backend/port/win32/sem.c b/src/backend/port/win32/sem.c deleted file mode 100644 index 90296bd7ebd..00000000000 --- a/src/backend/port/win32/sem.c +++ /dev/null @@ -1,256 +0,0 @@ -/*------------------------------------------------------------------------- - * - * sem.c - * Microsoft Windows Win32 Semaphores Emulation - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" -#include "storage/shmem.h" - -#include - -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; -} diff --git a/src/backend/port/win32/sema.c b/src/backend/port/win32/sema.c new file mode 100644 index 00000000000..489918fa97a --- /dev/null +++ b/src/backend/port/win32/sema.c @@ -0,0 +1,257 @@ +/*------------------------------------------------------------------------- + * + * sema.c + * Microsoft Windows Win32 Semaphores Emulation + * + * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "storage/shmem.h" +#include "sema.h" + +#include + +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; +} diff --git a/src/backend/port/win32/shm.c b/src/backend/port/win32/shm.c deleted file mode 100644 index 833f13c4cf0..00000000000 --- a/src/backend/port/win32/shm.c +++ /dev/null @@ -1,128 +0,0 @@ -/*------------------------------------------------------------------------- - * - * shm.c - * Microsoft Windows Win32 Shared Memory Emulation - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" -#include "windows.h" - -#include -#include - -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) -{ - /* 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; -} diff --git a/src/backend/port/win32/shmem.c b/src/backend/port/win32/shmem.c new file mode 100644 index 00000000000..8e560118506 --- /dev/null +++ b/src/backend/port/win32/shmem.c @@ -0,0 +1,127 @@ +/*------------------------------------------------------------------------- + * + * shmem.c + * Microsoft Windows Win32 Shared Memory Emulation + * + * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include +#include + +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) +{ + /* 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; +} diff --git a/src/include/port/win32.h b/src/include/port/win32.h index a117be863af..ecd79368fb9 100644 --- a/src/include/port/win32.h +++ b/src/include/port/win32.h @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/include/port/win32.h,v 1.7 2003/04/18 01:03:42 momjian Exp $ */ +/* $Header: /cvsroot/pgsql/src/include/port/win32.h,v 1.8 2003/04/24 21:23:01 momjian Exp $ */ #include @@ -32,6 +32,56 @@ #endif +/* + * IPC defines + */ +#define IPC_RMID 256 +#define IPC_CREAT 512 +#define IPC_EXCL 1024 +#define IPC_PRIVATE 234564 +#define IPC_NOWAIT 2048 +#define IPC_STAT 4096 + + +/* + * Shared memory + */ +struct shmid_ds +{ + int dummy; + int shm_nattch; +}; + +int shmdt(const void *shmaddr); +void* shmat(int memId, void* shmaddr, int flag); +int shmctl(int shmid, int flag, struct shmid_ds * dummy); +int shmget(int memKey, int size, int flag); + + +/* + * Semaphores + */ +union semun +{ + int val; + struct semid_ds *buf; + unsigned short *array; +}; + +struct sembuf +{ + int sem_flg; + int sem_op; + int sem_num; +}; + +int semctl(int semId, int semNum, int flag, union semun); +int semget(int semKey, int semNum, int flags); +int semop(int semId, struct sembuf * sops, int flag); + + +/* FROM SRA */ + /* * Supplement to . */ -- cgit v1.2.3