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