condition.c revision af1e34f918791cf8dc1ed649e306358c71934ddc
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * Copyright (C) 1998-2001 Internet Software Consortium.
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * Permission to use, copy, modify, and distribute this software for any
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * purpose with or without fee is hereby granted, provided that the above
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * copyright notice and this permission notice appear in all copies.
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * PERFORMANCE OF THIS SOFTWARE.
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff/* $Id: condition.c,v 1.22 2007/05/10 23:46:54 tbox Exp $ */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * This handle is shared across all threads
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * The threadlist will hold the actual events needed
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * for the wait condition
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * Add the thread to the threadlist along with the required events
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graffregister_thread(unsigned long thrd, isc_condition_t *gblcond,
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff REQUIRE(localcond != NULL && *localcond == NULL);
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff newthread = malloc(sizeof(isc_condition_thread_t));
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * Create the thread-specific handle
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * Add the thread ID and handles to list of threads for broadcast
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff newthread->handle[LSIGNAL] = gblcond->events[LSIGNAL];
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * The thread is holding the manager lock so this is safe
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff ISC_LIST_APPEND(gblcond->threadlist, newthread, link);
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Grafffind_thread_condition(unsigned long thrd, isc_condition_t *cond,
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff REQUIRE(threadcondp != NULL && *threadcondp == NULL);
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff * Look for the thread ID.
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff for (threadcond = ISC_LIST_HEAD(cond->threadlist);
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff threadcond = ISC_LIST_NEXT(threadcond, link)) {
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Not found, so add it.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff return (register_thread(thrd, cond, threadcondp));
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Unlike pthreads, the caller MUST hold the lock associated with
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * the condition variable when calling us.
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graffisc_condition_broadcast(isc_condition_t *cond) {
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Unlike pthreads, the caller MUST hold the lock associated with
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * the condition variable when calling us.
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff * Notify every thread registered for this
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff for (threadcond = ISC_LIST_HEAD(cond->threadlist);
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff threadcond = ISC_LIST_NEXT(threadcond, link)) {
291b0d910d115e41a4b69d0603c3376aebf0c630Michael Graff if (!SetEvent(threadcond->handle[LBROADCAST]))
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff * Delete the threadlist
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff (void) CloseHandle(threadcond->handle[LBROADCAST]);
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * This is always called when the mutex (lock) is held, but because
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * we are waiting we need to release it and reacquire it as soon as the wait
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * is over. This allows other threads to make use of the object guarded
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * by the mutex but it should never try to delete it as long as the
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * number of waiters > 0. Always reacquire the mutex regardless of the
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * result of the wait. Note that EnterCriticalSection will wait to acquire
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graffwait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) {
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * Get the thread events needed for the wait
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff tresult = find_thread_condition(isc_thread_self(), cond, &threadcond);
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff result = WaitForMultipleObjects(2, threadcond->handle, FALSE,
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graffisc_condition_wait(isc_condition_t *cond, isc_mutex_t *mutex) {