18dffb485Schristos /* Once-only control (native Windows implementation). 2*4b169a6bSchristos Copyright (C) 2005-2022 Free Software Foundation, Inc. 38dffb485Schristos 4*4b169a6bSchristos This file is free software: you can redistribute it and/or modify 5*4b169a6bSchristos it under the terms of the GNU Lesser General Public License as 6*4b169a6bSchristos published by the Free Software Foundation; either version 2.1 of the 7*4b169a6bSchristos License, or (at your option) any later version. 88dffb485Schristos 9*4b169a6bSchristos This file is distributed in the hope that it will be useful, 108dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 118dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*4b169a6bSchristos GNU Lesser General Public License for more details. 138dffb485Schristos 14*4b169a6bSchristos You should have received a copy of the GNU Lesser General Public License 15*4b169a6bSchristos along with this program. If not, see <https://www.gnu.org/licenses/>. */ 168dffb485Schristos 178dffb485Schristos /* Written by Bruno Haible <bruno@clisp.org>, 2005. 188dffb485Schristos Based on GCC's gthr-win32.h. */ 198dffb485Schristos 208dffb485Schristos #include <config.h> 218dffb485Schristos 228dffb485Schristos /* Specification. */ 238dffb485Schristos #include "windows-once.h" 248dffb485Schristos 258dffb485Schristos #include <stdlib.h> 268dffb485Schristos 278dffb485Schristos void glwthread_once(glwthread_once_t * once_control,void (* initfunction)(void))288dffb485Schristosglwthread_once (glwthread_once_t *once_control, void (*initfunction) (void)) 298dffb485Schristos { 308dffb485Schristos if (once_control->inited <= 0) 318dffb485Schristos { 328dffb485Schristos if (InterlockedIncrement (&once_control->started) == 0) 338dffb485Schristos { 348dffb485Schristos /* This thread is the first one to come to this once_control. */ 358dffb485Schristos InitializeCriticalSection (&once_control->lock); 368dffb485Schristos EnterCriticalSection (&once_control->lock); 378dffb485Schristos once_control->inited = 0; 388dffb485Schristos initfunction (); 398dffb485Schristos once_control->inited = 1; 408dffb485Schristos LeaveCriticalSection (&once_control->lock); 418dffb485Schristos } 428dffb485Schristos else 438dffb485Schristos { 448dffb485Schristos /* Don't let once_control->started grow and wrap around. */ 458dffb485Schristos InterlockedDecrement (&once_control->started); 468dffb485Schristos /* Some other thread has already started the initialization. 478dffb485Schristos Yield the CPU while waiting for the other thread to finish 488dffb485Schristos initializing and taking the lock. */ 498dffb485Schristos while (once_control->inited < 0) 508dffb485Schristos Sleep (0); 518dffb485Schristos if (once_control->inited <= 0) 528dffb485Schristos { 538dffb485Schristos /* Take the lock. This blocks until the other thread has 548dffb485Schristos finished calling the initfunction. */ 558dffb485Schristos EnterCriticalSection (&once_control->lock); 568dffb485Schristos LeaveCriticalSection (&once_control->lock); 578dffb485Schristos if (!(once_control->inited > 0)) 588dffb485Schristos abort (); 598dffb485Schristos } 608dffb485Schristos } 618dffb485Schristos } 628dffb485Schristos } 63