Back to index

glibc  2.9
pspinlock.c
Go to the documentation of this file.
00001 /* POSIX spinlock implementation.  x86 version.
00002    Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public License as
00007    published by the Free Software Foundation; either version 2.1 of the
00008    License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00017    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.  */
00019 
00020 #include <errno.h>
00021 #include <pthread.h>
00022 #include "internals.h"
00023 #include <kernel-features.h>
00024 
00025 
00026 /* This implementation is similar to the one used in the Linux kernel.
00027    But the kernel is byte instructions for the memory access.  This is
00028    faster but unusable here.  The problem is that only 128
00029    threads/processes could use the spinlock at the same time.  If (by
00030    a design error in the program) a thread/process would hold the
00031    spinlock for a time long enough to accumulate 128 waiting
00032    processes, the next one will find a positive value in the spinlock
00033    and assume it is unlocked.  We cannot accept that.  */
00034 
00035 int
00036 __pthread_spin_lock (pthread_spinlock_t *lock)
00037 {
00038   asm volatile
00039     ("\n"
00040      "1:\n\t"
00041      "lock; decl %0\n\t"
00042      "js 2f\n\t"
00043      ".section .text.spinlock,\"ax\"\n"
00044      "2:\n\t"
00045      "cmpl $0,%0\n\t"
00046      "rep; nop\n\t"
00047      "jle 2b\n\t"
00048      "jmp 1b\n\t"
00049      ".previous"
00050      : "=m" (*lock));
00051   return 0;
00052 }
00053 weak_alias (__pthread_spin_lock, pthread_spin_lock)
00054 
00055 
00056 int
00057 __pthread_spin_trylock (pthread_spinlock_t *lock)
00058 {
00059   int oldval;
00060 
00061   asm volatile
00062     ("xchgl %0,%1"
00063      : "=r" (oldval), "=m" (*lock)
00064      : "0" (0));
00065   return oldval > 0 ? 0 : EBUSY;
00066 }
00067 weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
00068 
00069 
00070 int
00071 __pthread_spin_unlock (pthread_spinlock_t *lock)
00072 {
00073   asm volatile
00074     ("movl $1,%0"
00075      : "=m" (*lock));
00076   return 0;
00077 }
00078 weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
00079 
00080 
00081 int
00082 __pthread_spin_init (pthread_spinlock_t *lock, int pshared)
00083 {
00084   /* We can ignore the `pshared' parameter.  Since we are busy-waiting
00085      all processes which can access the memory location `lock' points
00086      to can use the spinlock.  */
00087   *lock = 1;
00088   return 0;
00089 }
00090 weak_alias (__pthread_spin_init, pthread_spin_init)
00091 
00092 
00093 int
00094 __pthread_spin_destroy (pthread_spinlock_t *lock)
00095 {
00096   /* Nothing to do.  */
00097   return 0;
00098 }
00099 weak_alias (__pthread_spin_destroy, pthread_spin_destroy)
00100 
00101 #ifndef __ASSUME_SET_THREAD_AREA_SYSCALL
00102 int __have_no_set_thread_area;
00103 #endif