Commit a5d7c242 authored by Mark Andrews's avatar Mark Andrews
Browse files

2175. [bug] win32: window broadcast condition variable support

                        was broken. [RT #16592]
parent f6da30bb
2175. [bug] win32: window broadcast condition variable support
was broken. [RT #16592]
2174. [bug] I/O errors should always be fatal when reading
master files. [RT #16825]
......
/*
* Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
......@@ -15,13 +15,14 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: condition.c,v 1.20 2006/02/13 23:50:54 marka Exp $ */
/* $Id: condition.c,v 1.21 2007/05/09 23:49:37 marka Exp $ */
#include <config.h>
#include <isc/condition.h>
#include <isc/assertions.h>
#include <isc/util.h>
#include <isc/thread.h>
#include <isc/time.h>
#define LSIGNAL 0
......@@ -34,23 +35,92 @@ isc_condition_init(isc_condition_t *cond) {
REQUIRE(cond != NULL);
cond->waiters = 0;
/*
* This handle is shared across all threads
*/
h = CreateEvent(NULL, FALSE, FALSE, NULL);
if (h == NULL) {
/* XXX */
return (ISC_R_UNEXPECTED);
}
cond->events[LSIGNAL] = h;
h = CreateEvent(NULL, TRUE, FALSE, NULL);
if (h == NULL) {
(void)CloseHandle(cond->events[LSIGNAL]);
/* XXX */
/*
* The threadlist will hold the actual events needed
* for the wait condition
*/
ISC_LIST_INIT(cond->threadlist);
return (ISC_R_SUCCESS);
}
/*
* Add the thread to the threadlist along with the required events
*/
static isc_result_t
register_thread(unsigned long thrd, isc_condition_t *gblcond,
isc_condition_thread_t **localcond)
{
HANDLE hc;
isc_condition_thread_t *newthread;
REQUIRE(localcond != NULL && *localcond == NULL);
newthread = malloc(sizeof(isc_condition_thread_t));
if (newthread == NULL)
return (ISC_R_NOMEMORY);
/*
* Create the thread-specific handle
*/
hc = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hc == NULL) {
free(newthread);
return (ISC_R_UNEXPECTED);
}
cond->events[LBROADCAST] = h;
/*
* Add the thread ID and handles to list of threads for broadcast
*/
newthread->handle[LSIGNAL] = gblcond->events[LSIGNAL];
newthread->handle[LBROADCAST] = hc;
newthread->th = thrd;
/*
* The thread is holding the manager lock so this is safe
*/
ISC_LIST_APPEND(gblcond->threadlist, newthread, link);
*localcond = newthread;
return (ISC_R_SUCCESS);
}
static isc_result_t
find_thread_condition(unsigned long thrd, isc_condition_t *cond,
isc_condition_thread_t **threadcondp)
{
isc_condition_thread_t *threadcond;
REQUIRE(threadcondp != NULL && *threadcondp == NULL);
/*
* Look for the thread ID.
*/
for (threadcond = ISC_LIST_HEAD(cond->threadlist);
threadcond != NULL;
threadcond = ISC_LIST_NEXT(threadcond, link)) {
if (threadcond->th == thrd) {
*threadcondp = threadcond;
return (ISC_R_SUCCESS);
}
}
/*
* Not found, so add it.
*/
return (register_thread(thrd, cond, threadcondp));
}
isc_result_t
isc_condition_signal(isc_condition_t *cond) {
......@@ -60,8 +130,7 @@ isc_condition_signal(isc_condition_t *cond) {
*/
REQUIRE(cond != NULL);
if (cond->waiters > 0 &&
!SetEvent(cond->events[LSIGNAL])) {
if (!SetEvent(cond->events[LSIGNAL])) {
/* XXX */
return (ISC_R_UNEXPECTED);
}
......@@ -72,29 +141,54 @@ isc_condition_signal(isc_condition_t *cond) {
isc_result_t
isc_condition_broadcast(isc_condition_t *cond) {
isc_condition_thread_t *threadcond;
isc_boolean_t failed = ISC_FALSE;
/*
* Unlike pthreads, the caller MUST hold the lock associated with
* the condition variable when calling us.
*/
REQUIRE(cond != NULL);
if (cond->waiters > 0 &&
!SetEvent(cond->events[LBROADCAST])) {
/* XXX */
return (ISC_R_UNEXPECTED);
/*
* Notify every thread registered for this
*/
for (threadcond = ISC_LIST_HEAD(cond->threadlist);
threadcond != NULL;
threadcond = ISC_LIST_NEXT(threadcond, link)) {
if (!SetEvent(threadcond->handle[LBROADCAST]))
failed = ISC_TRUE;
}
if (failed)
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
}
isc_result_t
isc_condition_destroy(isc_condition_t *cond) {
isc_condition_thread_t *next, *threadcond;
REQUIRE(cond != NULL);
REQUIRE(cond->waiters == 0);
(void)CloseHandle(cond->events[LSIGNAL]);
(void)CloseHandle(cond->events[LBROADCAST]);
/*
* Delete the threadlist
*/
threadcond = ISC_LIST_HEAD(cond->threadlist);
while (threadcond != NULL) {
next = ISC_LIST_NEXT(threadcond, link);
DEQUEUE(cond->threadlist, threadcond, link);
(void) CloseHandle(threadcond->handle[LBROADCAST]);
free(threadcond);
threadcond = next;
}
return (ISC_R_SUCCESS);
}
......@@ -111,22 +205,26 @@ isc_condition_destroy(isc_condition_t *cond) {
static isc_result_t
wait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) {
DWORD result;
isc_result_t tresult;
isc_condition_thread_t *threadcond = NULL;
/*
* Get the thread events needed for the wait
*/
tresult = find_thread_condition(isc_thread_self(), cond, &threadcond);
if (tresult != ISC_R_SUCCESS)
return (tresult);
cond->waiters++;
LeaveCriticalSection(mutex);
result = WaitForMultipleObjects(2, cond->events, FALSE, milliseconds);
result = WaitForMultipleObjects(2, threadcond->handle, FALSE,
milliseconds);
EnterCriticalSection(mutex);
cond->waiters--;
if (result == WAIT_FAILED) {
/* XXX */
return (ISC_R_UNEXPECTED);
}
if (cond->waiters == 0 &&
!ResetEvent(cond->events[LBROADCAST])) {
/* XXX */
return (ISC_R_UNEXPECTED);
}
if (result == WAIT_TIMEOUT)
return (ISC_R_TIMEDOUT);
......
/*
* Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: condition.h,v 1.14 2004/03/05 05:12:05 marka Exp $ */
/* $Id: condition.h,v 1.15 2007/05/09 23:49:37 marka Exp $ */
#ifndef ISC_CONDITION_H
#define ISC_CONDITION_H 1
......@@ -24,11 +24,22 @@
#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/thread.h>
#include <isc/types.h>
typedef struct isc_condition_thread isc_condition_thread_t;
struct isc_condition_thread {
unsigned long th;
HANDLE handle[2];
ISC_LINK(isc_condition_thread_t) link;
};
typedef struct isc_condition {
HANDLE events[2];
unsigned int waiters;
ISC_LIST(isc_condition_thread_t) threadlist;
} isc_condition_t;
ISC_LANG_BEGINDECLS
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment