Back to index

glibc  2.9
pspinlock.c
Go to the documentation of this file.
00001 /* POSIX spinlock implementation.  Alpha version.
00002    Copyright (C) 2000 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 
00024 
00025 /* This implementation is similar to the one used in the Linux kernel.
00026    But the kernel is byte instructions for the memory access.  This is
00027    faster but unusable here.  The problem is that only 128
00028    threads/processes could use the spinlock at the same time.  If (by
00029    a design error in the program) a thread/process would hold the
00030    spinlock for a time long enough to accumulate 128 waiting
00031    processes, the next one will find a positive value in the spinlock
00032    and assume it is unlocked.  We cannot accept that.  */
00033 
00034 int
00035 __pthread_spin_lock (pthread_spinlock_t *lock)
00036 {
00037   unsigned int tmp;
00038   asm volatile
00039     ("1:      ldl_l  %0,%1\n"
00040      "        blbs   %0,2f\n"
00041      "        or     %0,1,%0\n"
00042      "        stl_c  %0,%1\n"
00043      "        beq    %0,2f\n"
00044      "        mb\n"
00045      ".subsection 2\n"
00046      "2:      ldl    %0,%1\n"
00047      "        blbs   %0,2b\n"
00048      "        br     1b\n"
00049      ".previous"
00050      : "=r" (tmp), "=m" (lock)
00051      : "m" (lock));
00052   return 0;
00053 }
00054 weak_alias (__pthread_spin_lock, pthread_spin_lock)
00055 
00056 
00057 int
00058 __pthread_spin_trylock (pthread_spinlock_t *lock)
00059 {
00060   unsigned long int oldval;
00061   unsigned long int temp;
00062 
00063   asm volatile
00064     ("1:      ldl_l  %0,%1\n"
00065      "        and    %0,%3,%2\n"
00066      "        bne    %2,2f\n"
00067      "        xor    %0,%3,%0\n"
00068      "        stl_c  %0,%1\n"
00069      "        beq    %0,3f\n"
00070      "        mb\n"
00071      "2:\n"
00072      ".subsection 2\n"
00073      "3:      br     1b\n"
00074      ".previous"
00075      : "=&r" (temp), "=m" (*lock), "=&r" (oldval)
00076      : "Ir" (1UL), "m" (*lock));
00077 
00078   return oldval == 0 ? 0 : EBUSY;
00079 }
00080 weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
00081 
00082 
00083 int
00084 __pthread_spin_unlock (pthread_spinlock_t *lock)
00085 {
00086   asm volatile ("mb");
00087   return *lock = 0;
00088 }
00089 weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
00090 
00091 
00092 int
00093 __pthread_spin_init (pthread_spinlock_t *lock, int pshared)
00094 {
00095   /* We can ignore the `pshared' parameter.  Since we are busy-waiting
00096      all processes which can access the memory location `lock' points
00097      to can use the spinlock.  */
00098   *lock = 0;
00099   return 0;
00100 }
00101 weak_alias (__pthread_spin_init, pthread_spin_init)
00102 
00103 
00104 int
00105 __pthread_spin_destroy (pthread_spinlock_t *lock)
00106 {
00107   /* Nothing to do.  */
00108   return 0;
00109 }
00110 weak_alias (__pthread_spin_destroy, pthread_spin_destroy)