1/* Copyright (C) 2002-2015 Free Software Foundation, Inc. 2 Contributed by Zack Weinberg <zack@codesourcery.com> 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 3, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25/* Threads compatibility routines for libgcc2 for VxWorks. 26 These are out-of-line routines called from gthr-vxworks.h. */ 27 28#include "tconfig.h" 29#include "tsystem.h" 30#include "gthr.h" 31 32#if defined(__GTHREADS) 33#include <vxWorks.h> 34#ifndef __RTP__ 35#include <vxLib.h> 36#endif 37#include <taskLib.h> 38#ifndef __RTP__ 39#include <taskHookLib.h> 40#else 41# include <errno.h> 42#endif 43 44/* Init-once operation. 45 46 This would be a clone of the implementation from gthr-solaris.h, 47 except that we have a bootstrap problem - the whole point of this 48 exercise is to prevent double initialization, but if two threads 49 are racing with each other, once->mutex is liable to be initialized 50 by both. Then each thread will lock its own mutex, and proceed to 51 call the initialization routine. 52 53 So instead we use a bare atomic primitive (vxTas()) to handle 54 mutual exclusion. Threads losing the race then busy-wait, calling 55 taskDelay() to yield the processor, until the initialization is 56 completed. Inefficient, but reliable. */ 57 58int 59__gthread_once (__gthread_once_t *guard, void (*func)(void)) 60{ 61 if (guard->done) 62 return 0; 63 64#ifdef __RTP__ 65 __gthread_lock_library (); 66#else 67 while (!vxTas ((void *)&guard->busy)) 68 { 69#ifdef __PPC__ 70 /* This can happen on powerpc, which is using all 32 bits 71 of the gthread_once_t structure. */ 72 if (guard->done) 73 return; 74#endif 75 taskDelay (1); 76 } 77#endif 78 79 /* Only one thread at a time gets here. Check ->done again, then 80 go ahead and call func() if no one has done it yet. */ 81 if (!guard->done) 82 { 83 func (); 84 guard->done = 1; 85 } 86 87#ifdef __RTP__ 88 __gthread_unlock_library (); 89#else 90 guard->busy = 0; 91#endif 92 return 0; 93} 94 95#endif /* __GTHREADS */ 96