summaryrefslogtreecommitdiff
path: root/src/backend/port/win32/shm.c
blob: 20aaf1f6a4dd436055469c7aa0d7599803fae55a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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;
}