qemu-lock.h revision 4af48bf7c72ef1e201c64bd475377b5af9d8e8a1
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Copyright (c) 2003 Fabrice Bellard
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * This library is free software; you can redistribute it and/or
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * modify it under the terms of the GNU Lesser General Public
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * License as published by the Free Software Foundation; either
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * version 2 of the License, or (at your option) any later version.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * This library is distributed in the hope that it will be useful,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Lesser General Public License for more details.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * You should have received a copy of the GNU Lesser General Public
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * License along with this library; if not, write to the Free Software
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * a choice of LGPL license versions is made available with the language indicating
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync * of the LGPL is applied is otherwise unspecified.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* Locking primitives. Most of this code should be redundant -
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync system emulation doesn't need/use locking, NPTL userspace uses
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync pthread mutexes, and non-NPTL userspace isn't threadsafe anyway.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync In either case a spinlock is probably the wrong kind of lock.
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync Spinlocks are only good if you know annother CPU has the lock and is
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync likely to release it soon. In environments where you have more threads
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync than physical CPUs (the extreme case being a single CPU host) a spinlock
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync simply wastes CPU until the OS decides to preempt it. */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync#define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return ASMAtomicCmpXchgU32((volatile uint32_t *)p, 1, 0) ? 0 : 1;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " lwarx %0,0,%1\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " xor. %0,%3,%0\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " bne $+12\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " stwcx. %2,0,%1\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " bne- $-16\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync long int readval = 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync long int readval = 0;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync unsigned long one;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " ldl_l %0,%1\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " stl_c %2,%1\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " beq %2,1f\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ".subsection 2\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync "1: br 0b\n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync ".previous"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync : "m" (*p));
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync : "memory");
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync register unsigned int ret;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync/* Because malloc only guarantees 8-byte alignment for malloc'd data,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync and GCC only guarantees 8-byte alignment for stack locals, we can't
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync be assured of 16-byte alignment for atomic lock data even if we
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync specify "__attribute ((aligned(16)))" in the type declaration. So,
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync we use a struct containing an array of four ints for the atomic lock
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync type and dynamically select the 16-byte aligned int from the array
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync for the semaphore. */
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline void *ldcw_align (void *p) {
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync unsigned long a = (unsigned long)p;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync return (void *)a;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync unsigned int ret;
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync : "memory" );
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsyncstatic inline int testandset (int *p)
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " .set push \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " .set noat \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " .set mips2 \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync "1: li $1, 1 \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " ll %0, %1 \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " sc $1, %1 \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " beqz $1, 1b \n"
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync " .set pop "
3331475701a5b12f98b3cfea07d5dca60072530fvboxsync : "memory");