Back to index

glibc  2.9
pspinlock.c
Go to the documentation of this file.
00001 /* POSIX spinlock implementation.  x86-64 version.
00002    Copyright (C) 2001 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
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the 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; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <pthread.h>
00022 #include "internals.h"
00023 
00024 /* This implementation is similar to the one used in the Linux kernel.
00025    But the kernel is byte instructions for the memory access.  This is
00026    faster but unusable here.  The problem is that only 128
00027    threads/processes could use the spinlock at the same time.  If (by
00028    a design error in the program) a thread/process would hold the
00029    spinlock for a time long enough to accumulate 128 waiting
00030    processes, the next one will find a positive value in the spinlock
00031    and assume it is unlocked.  We cannot accept that.  */
00032 
00033 int
00034 __pthread_spin_lock (pthread_spinlock_t *lock)
00035 {
00036   asm volatile
00037     ("\n"
00038      "1:\n\t"
00039      "lock; decl %0\n\t"
00040      "js 2f\n\t"
00041      ".section .text.spinlock,\"ax\"\n"
00042      "2:\n\t"
00043      "cmpl $0,%0\n\t"
00044      "rep; nop\n\t"
00045      "jle 2b\n\t"
00046      "jmp 1b\n\t"
00047      ".previous"
00048      : "=m" (*lock));
00049   return 0;
00050 }
00051 weak_alias (__pthread_spin_lock, pthread_spin_lock)
00052 
00053 
00054 int
00055 __pthread_spin_trylock (pthread_spinlock_t *lock)
00056 {
00057   int oldval;
00058 
00059   asm volatile
00060     ("xchgl %0,%1"
00061      : "=r" (oldval), "=m" (*lock)
00062      : "0" (0));
00063   return oldval > 0 ? 0 : EBUSY;
00064 }
00065 weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
00066 
00067 
00068 int
00069 __pthread_spin_unlock (pthread_spinlock_t *lock)
00070 {
00071   asm volatile
00072     ("movl $1,%0"
00073      : "=m" (*lock));
00074   return 0;
00075 }
00076 weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
00077 
00078 
00079 int
00080 __pthread_spin_init (pthread_spinlock_t *lock, int pshared)
00081 {
00082   /* We can ignore the `pshared' parameter.  Since we are busy-waiting
00083      all processes which can access the memory location `lock' points
00084      to can use the spinlock.  */
00085   *lock = 1;
00086   return 0;
00087 }
00088 weak_alias (__pthread_spin_init, pthread_spin_init)
00089 
00090 
00091 int
00092 __pthread_spin_destroy (pthread_spinlock_t *lock)
00093 {
00094   /* Nothing to do.  */
00095   return 0;
00096 }
00097 weak_alias (__pthread_spin_destroy, pthread_spin_destroy)