Back to index

glibc  2.9
pspinlock.c
Go to the documentation of this file.
00001 /* POSIX spinlock implementation.  S/390 version.
00002    Copyright (C) 2000, 2004 Free Software Foundation, Inc.
00003    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public License as
00008    published by the Free Software Foundation; either version 2.1 of the
00009    License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00018    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.  */
00020 
00021 #include <errno.h>
00022 #include <pthread.h>
00023 #include "internals.h"
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   asm volatile("    basr  1,0\n"
00038               "0:  slr   0,0\n"
00039               "    cs    0,1,%1\n"
00040               "    jl    0b\n"
00041               : "=m" (*lock)
00042               : "m" (*lock) : "0", "1", "cc" );
00043   return 0;
00044 }
00045 weak_alias (__pthread_spin_lock, pthread_spin_lock)
00046 
00047 int
00048 __pthread_spin_trylock (pthread_spinlock_t *lock)
00049 {
00050   int oldval;
00051 
00052   asm volatile("    slr   %1,%1\n"
00053               "    basr  1,0\n"
00054               "0:  cs    %1,1,%0"
00055               : "=m" (*lock), "=&d" (oldval)
00056               : "m" (*lock) : "1", "cc" );
00057   return oldval == 0 ? 0 : EBUSY;
00058 }
00059 weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
00060 
00061 
00062 int
00063 __pthread_spin_unlock (pthread_spinlock_t *lock)
00064 {
00065   asm volatile("    xc 0(4,%0),0(%0)\n"
00066               "    bcr 15,0"
00067               : : "a" (lock) : "memory" );
00068   return 0;
00069 }
00070 weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
00071 
00072 
00073 int
00074 __pthread_spin_init (pthread_spinlock_t *lock, int pshared)
00075 {
00076   /* We can ignore the `pshared' parameter.  Since we are busy-waiting
00077      all processes which can access the memory location `lock' points
00078      to can use the spinlock.  */
00079   *lock = 0;
00080   return 0;
00081 }
00082 weak_alias (__pthread_spin_init, pthread_spin_init)
00083 
00084 
00085 int
00086 __pthread_spin_destroy (pthread_spinlock_t *lock)
00087 {
00088   /* Nothing to do.  */
00089   return 0;
00090 }
00091 weak_alias (__pthread_spin_destroy, pthread_spin_destroy)