diff --git a/lib/isc/win32/include/isc/once.h b/lib/isc/win32/include/isc/once.h new file mode 100644 index 0000000000..f0ec235806 --- /dev/null +++ b/lib/isc/win32/include/isc/once.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: once.h,v 1.1 1999/09/23 18:14:16 tale Exp $ */ + +#ifndef ISC_ONCE_H +#define ISC_ONCE_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +typedef struct { + int status; +#ifndef ISC_ONCE_USE_MUTEX + int counter; +#endif +} isc_once_t; + +#define ISC_ONCE_INIT_NEEDED 0 +#define ISC_ONCE_INIT_DONE 1 + +#ifdef ISC_ONCE_USE_MUTEX +#define ISC_ONCE_INIT { ISC_ONCE_INIT_NEEDED } +#else +#define ISC_ONCE_INIT { ISC_ONCE_INIT_NEEDED, 1 } +#endif + +isc_result_t +isc_once_do(isc_once_t *controller, void(*function)(void)); + +ISC_LANG_ENDDECLS + +#endif /* ISC_ONCE_H */ diff --git a/lib/isc/win32/once.c b/lib/isc/win32/once.c new file mode 100644 index 0000000000..a5ff365d44 --- /dev/null +++ b/lib/isc/win32/once.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $Id: once.c,v 1.1 1999/09/23 18:14:16 tale Exp $ */ + +/* Principal Authors: DCL */ + +#ifdef ISC_ONCE_USE_MUTEX +#include +#include +#endif + +#include + +#include +#include + +#ifdef ISC_ONCE_USE_MUTEX + +/* + * XXXDCL someone (me? bob?) should decide which method to use, + * the mutex method or the InterlockedDecrement method. + */ + +isc_result_t +isc_once_do(isc_once_t *controller, void(*function)(void)) + +{ + char mutex_name[64]; + HANDLE mutex; + + REQUIRE(controller != NULL && function != NULL); + + if (controller->status == ISC_ONCE_INIT_NEEDED) { + + /* + * Create a name that is associated only with this process + * and controller. + */ + sprintf(mutex_name, "__isc_once_do_%ld:%p", + getpid(), controller); + + /* + * Create the mutex (or attach to the existing mutex) + * and lock it. + */ + mutex = CreateMutex(NULL, FALSE, mutex_name); + if (mutex == NULL) + return (ISC_R_UNEXPECTED); + if (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) + return (ISC_R_UNEXPECTED); + + /* + * Recheck need for initialization now that + * the controller is locked. + */ + if (controller->status == ISC_ONCE_INIT_NEEDED) { + function(); + controller->status = ISC_ONCE_INIT_DONE; + } + + ReleaseMutex(mutex); + CloseHandle(mutex); + } + + return (ISC_R_SUCCESS); +} + +#else /* not ISC_ONCE_USE_MUTEX, use InterlockedDecrement instead */ + +isc_result_t +isc_once_do(isc_once_t *controller, void(*function)(void)) + +{ + REQUIRE(controller != NULL && function != NULL); + + if (controller->status == ISC_ONCE_INIT_NEEDED) { + + if (InterlockedDecrement(&controller->counter) == 0) { + if (controller->status == ISC_ONCE_INIT_NEEDED) { + function(); + controller->status = ISC_ONCE_INIT_DONE; + } + } else { + while (controller->status == ISC_ONCE_INIT_NEEDED) { + /* + * Spin wait. + */ + } + } + } + + return (ISC_R_SUCCESS); +} + +#endif /* ISC_ONCE_USE_MUTEX */