~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/port/win32_latch.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * win32_latch.c
 
4
 *        Windows implementation of latches.
 
5
 *
 
6
 * See unix_latch.c for information on usage.
 
7
 *
 
8
 * The Windows implementation uses Windows events that are inherited by
 
9
 * all postmaster child processes.
 
10
 *
 
11
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
12
 * Portions Copyright (c) 1994, Regents of the University of California
 
13
 *
 
14
 * IDENTIFICATION
 
15
 *        src/backend/port/win32_latch.c
 
16
 *
 
17
 *-------------------------------------------------------------------------
 
18
 */
 
19
#include "postgres.h"
 
20
 
 
21
#include <fcntl.h>
 
22
#include <signal.h>
 
23
#include <unistd.h>
 
24
 
 
25
#include "miscadmin.h"
 
26
#include "replication/walsender.h"
 
27
#include "storage/latch.h"
 
28
#include "storage/shmem.h"
 
29
 
 
30
 
 
31
void
 
32
InitLatch(volatile Latch *latch)
 
33
{
 
34
        latch->is_set = false;
 
35
        latch->owner_pid = MyProcPid;
 
36
        latch->is_shared = false;
 
37
 
 
38
        latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
 
39
        if (latch->event == NULL)
 
40
                elog(ERROR, "CreateEvent failed: error code %d", (int) GetLastError());
 
41
}
 
42
 
 
43
void
 
44
InitSharedLatch(volatile Latch *latch)
 
45
{
 
46
        SECURITY_ATTRIBUTES sa;
 
47
 
 
48
        latch->is_set = false;
 
49
        latch->owner_pid = 0;
 
50
        latch->is_shared = true;
 
51
 
 
52
        /*
 
53
         * Set up security attributes to specify that the events are inherited.
 
54
         */
 
55
        ZeroMemory(&sa, sizeof(sa));
 
56
        sa.nLength = sizeof(sa);
 
57
        sa.bInheritHandle = TRUE;
 
58
 
 
59
        latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
 
60
        if (latch->event == NULL)
 
61
                elog(ERROR, "CreateEvent failed: error code %d", (int) GetLastError());
 
62
}
 
63
 
 
64
void
 
65
OwnLatch(volatile Latch *latch)
 
66
{
 
67
        /* Sanity checks */
 
68
        Assert(latch->is_shared);
 
69
        if (latch->owner_pid != 0)
 
70
                elog(ERROR, "latch already owned");
 
71
 
 
72
        latch->owner_pid = MyProcPid;
 
73
}
 
74
 
 
75
void
 
76
DisownLatch(volatile Latch *latch)
 
77
{
 
78
        Assert(latch->is_shared);
 
79
        Assert(latch->owner_pid == MyProcPid);
 
80
 
 
81
        latch->owner_pid = 0;
 
82
}
 
83
 
 
84
bool
 
85
WaitLatch(volatile Latch *latch, long timeout)
 
86
{
 
87
        return WaitLatchOrSocket(latch, PGINVALID_SOCKET, false, false, timeout) > 0;
 
88
}
 
89
 
 
90
int
 
91
WaitLatchOrSocket(volatile Latch *latch, SOCKET sock, bool forRead,
 
92
                                  bool forWrite, long timeout)
 
93
{
 
94
        DWORD           rc;
 
95
        HANDLE          events[3];
 
96
        HANDLE          latchevent;
 
97
        HANDLE          sockevent = WSA_INVALID_EVENT; /* silence compiler */
 
98
        int                     numevents;
 
99
        int                     result = 0;
 
100
 
 
101
        latchevent = latch->event;
 
102
 
 
103
        events[0] = latchevent;
 
104
        events[1] = pgwin32_signal_event;
 
105
        numevents = 2;
 
106
        if (sock != PGINVALID_SOCKET && (forRead || forWrite))
 
107
        {
 
108
                int                     flags = 0;
 
109
 
 
110
                if (forRead)
 
111
                        flags |= FD_READ;
 
112
                if (forWrite)
 
113
                        flags |= FD_WRITE;
 
114
 
 
115
                sockevent = WSACreateEvent();
 
116
                WSAEventSelect(sock, sockevent, flags);
 
117
                events[numevents++] = sockevent;
 
118
        }
 
119
 
 
120
        for (;;)
 
121
        {
 
122
                /*
 
123
                 * Reset the event, and check if the latch is set already. If someone
 
124
                 * sets the latch between this and the WaitForMultipleObjects() call
 
125
                 * below, the setter will set the event and WaitForMultipleObjects()
 
126
                 * will return immediately.
 
127
                 */
 
128
                if (!ResetEvent(latchevent))
 
129
                        elog(ERROR, "ResetEvent failed: error code %d", (int) GetLastError());
 
130
                if (latch->is_set)
 
131
                {
 
132
                        result = 1;
 
133
                        break;
 
134
                }
 
135
 
 
136
                rc = WaitForMultipleObjects(numevents, events, FALSE,
 
137
                                                           (timeout >= 0) ? (timeout / 1000) : INFINITE);
 
138
                if (rc == WAIT_FAILED)
 
139
                        elog(ERROR, "WaitForMultipleObjects() failed: error code %d", (int) GetLastError());
 
140
                else if (rc == WAIT_TIMEOUT)
 
141
                {
 
142
                        result = 0;
 
143
                        break;
 
144
                }
 
145
                else if (rc == WAIT_OBJECT_0 + 1)
 
146
                        pgwin32_dispatch_queued_signals();
 
147
                else if (rc == WAIT_OBJECT_0 + 2)
 
148
                {
 
149
                        WSANETWORKEVENTS resEvents;
 
150
 
 
151
                        Assert(sock != PGINVALID_SOCKET);
 
152
 
 
153
                        ZeroMemory(&resEvents, sizeof(resEvents));
 
154
                        if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR)
 
155
                                ereport(FATAL,
 
156
                                                (errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
 
157
 
 
158
                        if ((forRead && resEvents.lNetworkEvents & FD_READ) ||
 
159
                                (forWrite && resEvents.lNetworkEvents & FD_WRITE))
 
160
                                result = 2;
 
161
                        break;
 
162
                }
 
163
                else if (rc != WAIT_OBJECT_0)
 
164
                        elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", (int) rc);
 
165
        }
 
166
 
 
167
        /* Clean up the handle we created for the socket */
 
168
        if (sock != PGINVALID_SOCKET && (forRead || forWrite))
 
169
        {
 
170
                WSAEventSelect(sock, sockevent, 0);
 
171
                WSACloseEvent(sockevent);
 
172
        }
 
173
 
 
174
        return result;
 
175
}
 
176
 
 
177
void
 
178
SetLatch(volatile Latch *latch)
 
179
{
 
180
        HANDLE          handle;
 
181
 
 
182
        /* Quick exit if already set */
 
183
        if (latch->is_set)
 
184
                return;
 
185
 
 
186
        latch->is_set = true;
 
187
 
 
188
        /*
 
189
         * See if anyone's waiting for the latch. It can be the current process if
 
190
         * we're in a signal handler. Use a local variable here in case the latch
 
191
         * is just disowned between the test and the SetEvent call, and event
 
192
         * field set to NULL.
 
193
         *
 
194
         * Fetch handle field only once, in case the owner simultaneously disowns
 
195
         * the latch and clears handle. This assumes that HANDLE is atomic, which
 
196
         * isn't guaranteed to be true! In practice, it should be, and in the
 
197
         * worst case we end up calling SetEvent with a bogus handle, and SetEvent
 
198
         * will return an error with no harm done.
 
199
         */
 
200
        handle = latch->event;
 
201
        if (handle)
 
202
        {
 
203
                SetEvent(handle);
 
204
 
 
205
                /*
 
206
                 * Note that we silently ignore any errors. We might be in a signal
 
207
                 * handler or other critical path where it's not safe to call elog().
 
208
                 */
 
209
        }
 
210
}
 
211
 
 
212
void
 
213
ResetLatch(volatile Latch *latch)
 
214
{
 
215
        latch->is_set = false;
 
216
}