1*820c1a8dSHiroo HAYASHI /* Once-only control (native Windows implementation). 2*820c1a8dSHiroo HAYASHI Copyright (C) 2005-2021 Free Software Foundation, Inc. 3*820c1a8dSHiroo HAYASHI 4*820c1a8dSHiroo HAYASHI This file is free software: you can redistribute it and/or modify 5*820c1a8dSHiroo HAYASHI it under the terms of the GNU Lesser General Public License as 6*820c1a8dSHiroo HAYASHI published by the Free Software Foundation; either version 2.1 of the 7*820c1a8dSHiroo HAYASHI License, or (at your option) any later version. 8*820c1a8dSHiroo HAYASHI 9*820c1a8dSHiroo HAYASHI This file is distributed in the hope that it will be useful, 10*820c1a8dSHiroo HAYASHI but WITHOUT ANY WARRANTY; without even the implied warranty of 11*820c1a8dSHiroo HAYASHI MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*820c1a8dSHiroo HAYASHI GNU Lesser General Public License for more details. 13*820c1a8dSHiroo HAYASHI 14*820c1a8dSHiroo HAYASHI You should have received a copy of the GNU Lesser General Public License 15*820c1a8dSHiroo HAYASHI along with this program. If not, see <https://www.gnu.org/licenses/>. */ 16*820c1a8dSHiroo HAYASHI 17*820c1a8dSHiroo HAYASHI /* Written by Bruno Haible <bruno@clisp.org>, 2005. 18*820c1a8dSHiroo HAYASHI Based on GCC's gthr-win32.h. */ 19*820c1a8dSHiroo HAYASHI 20*820c1a8dSHiroo HAYASHI #include <config.h> 21*820c1a8dSHiroo HAYASHI 22*820c1a8dSHiroo HAYASHI /* Specification. */ 23*820c1a8dSHiroo HAYASHI #include "windows-once.h" 24*820c1a8dSHiroo HAYASHI 25*820c1a8dSHiroo HAYASHI #include <stdlib.h> 26*820c1a8dSHiroo HAYASHI 27*820c1a8dSHiroo HAYASHI void glwthread_once(glwthread_once_t * once_control,void (* initfunction)(void))28*820c1a8dSHiroo HAYASHIglwthread_once (glwthread_once_t *once_control, void (*initfunction) (void)) 29*820c1a8dSHiroo HAYASHI { 30*820c1a8dSHiroo HAYASHI if (once_control->inited <= 0) 31*820c1a8dSHiroo HAYASHI { 32*820c1a8dSHiroo HAYASHI if (InterlockedIncrement (&once_control->started) == 0) 33*820c1a8dSHiroo HAYASHI { 34*820c1a8dSHiroo HAYASHI /* This thread is the first one to come to this once_control. */ 35*820c1a8dSHiroo HAYASHI InitializeCriticalSection (&once_control->lock); 36*820c1a8dSHiroo HAYASHI EnterCriticalSection (&once_control->lock); 37*820c1a8dSHiroo HAYASHI once_control->inited = 0; 38*820c1a8dSHiroo HAYASHI initfunction (); 39*820c1a8dSHiroo HAYASHI once_control->inited = 1; 40*820c1a8dSHiroo HAYASHI LeaveCriticalSection (&once_control->lock); 41*820c1a8dSHiroo HAYASHI } 42*820c1a8dSHiroo HAYASHI else 43*820c1a8dSHiroo HAYASHI { 44*820c1a8dSHiroo HAYASHI /* Don't let once_control->started grow and wrap around. */ 45*820c1a8dSHiroo HAYASHI InterlockedDecrement (&once_control->started); 46*820c1a8dSHiroo HAYASHI /* Some other thread has already started the initialization. 47*820c1a8dSHiroo HAYASHI Yield the CPU while waiting for the other thread to finish 48*820c1a8dSHiroo HAYASHI initializing and taking the lock. */ 49*820c1a8dSHiroo HAYASHI while (once_control->inited < 0) 50*820c1a8dSHiroo HAYASHI Sleep (0); 51*820c1a8dSHiroo HAYASHI if (once_control->inited <= 0) 52*820c1a8dSHiroo HAYASHI { 53*820c1a8dSHiroo HAYASHI /* Take the lock. This blocks until the other thread has 54*820c1a8dSHiroo HAYASHI finished calling the initfunction. */ 55*820c1a8dSHiroo HAYASHI EnterCriticalSection (&once_control->lock); 56*820c1a8dSHiroo HAYASHI LeaveCriticalSection (&once_control->lock); 57*820c1a8dSHiroo HAYASHI if (!(once_control->inited > 0)) 58*820c1a8dSHiroo HAYASHI abort (); 59*820c1a8dSHiroo HAYASHI } 60*820c1a8dSHiroo HAYASHI } 61*820c1a8dSHiroo HAYASHI } 62*820c1a8dSHiroo HAYASHI } 63