From fb4cc8a0c2cc7ca710a2e1b21d33fcf7c5e3e8ba Mon Sep 17 00:00:00 2001 From: Agustina Arzille Date: Sun, 18 Mar 2018 18:22:55 +0100 Subject: hurd: Reimplement libc locks using mach's gsync * hurd/Makefile (routines): Add hurdlock. * hurd/Versions (GLIBC_PRIVATE): Added new entry to export the above interface. (HURD_CTHREADS_0.3): Remove __libc_getspecific. * hurd/hurdpid.c: Include (_S_msg_proc_newids): Use lll_wait to synchronize. * hurd/hurdsig.c: (reauth_proc): Use __mutex_lock and __mutex_unlock. * hurd/setauth.c: Include , use integer for synchronization. * mach/Makefile (lock-headers): Remove machine-lock.h. * mach/lock-intern.h: Include instead of . (__spin_lock_t): New type. (__SPIN_LOCK_INITIALIZER): New macro. (__spin_lock, __spin_unlock, __spin_try_lock, __spin_lock_locked, __mutex_init, __mutex_lock_solid, __mutex_unlock_solid, __mutex_lock, __mutex_unlock, __mutex_trylock): Use lll to implement locks. * mach/mutex-init.c: Include instead of . (__mutex_init): Initialize with lll. * manual/errno.texi (EOWNERDEAD, ENOTRECOVERABLE): New errno values. * sysdeps/mach/Makefile: Add libmachuser as dependencies for libs needing lll. * sysdeps/mach/hurd/bits/errno.h: Regenerate. * sysdeps/mach/hurd/cthreads.c (__libc_getspecific): Remove function. * sysdeps/mach/hurd/bits/libc-lock.h: Remove file. * sysdeps/mach/hurd/setpgid.c: Include . (__setpgid): Use lll for synchronization. * sysdeps/mach/hurd/setsid.c: Likewise with __setsid. * sysdeps/mach/bits/libc-lock.h: Include and instead of . (_IO_lock_inexpensive): New macro (__libc_lock_recursive_t, __rtld_lock_recursive_t): New structures. (__libc_lock_self0): New declaration. (__libc_lock_owner_self): New macro. (__libc_key_t): Remove type. (_LIBC_LOCK_INITIALIZER): New macro. (__libc_lock_define_initialized, __libc_lock_init, __libc_lock_fini, __libc_lock_fini_recursive, __rtld_lock_fini_recursive, __libc_lock_lock, __libc_lock_trylock, __libc_lock_unlock, __libc_lock_define_initialized_recursive, __rtld_lock_define_initialized_recursive, __libc_lock_init_recursive, __libc_lock_trylock_recursive, __libc_lock_lock_recursive, __libc_lock_unlock_recursive, __rtld_lock_initialize, __rtld_lock_trylock_recursive, __rtld_lock_lock_recursive, __rtld_lock_unlock_recursive __libc_once_define, __libc_mutex_unlock): Reimplement with lll. (__libc_lock_define_recursive, __rtld_lock_define_recursive, _LIBC_LOCK_RECURSIVE_INITIALIZER, _RTLD_LOCK_RECURSIVE_INITIALIZER): New macros. Include to reimplement libc_key* with pthread_key*. * hurd/hurdlock.c: New file. * hurd/hurdlock.h: New file. * mach/lowlevellock.h: New file --- mach/Makefile | 2 +- mach/lock-intern.h | 69 +++++++++++++++++++++++++++++---------------- mach/lowlevellock.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mach/mutex-init.c | 7 ++--- 4 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 mach/lowlevellock.h (limited to 'mach') diff --git a/mach/Makefile b/mach/Makefile index e0d1ffb1fa..2683587b2d 100644 --- a/mach/Makefile +++ b/mach/Makefile @@ -23,7 +23,7 @@ headers = mach_init.h mach.h mach_error.h mach-shortcuts.h mach/mach_traps.h \ $(interface-headers) mach/mach.h mach/mig_support.h mach/error.h \ $(lock-headers) machine-sp.h bits/mach/param.h lock = spin-solid spin-lock mutex-init mutex-solid -lock-headers = lock-intern.h machine-lock.h spin-lock.h +lock-headers = lock-intern.h spin-lock.h routines = $(mach-syscalls) $(mach-shortcuts) \ mach_init mig_strncpy msg \ mig-alloc mig-dealloc mig-reply \ diff --git a/mach/lock-intern.h b/mach/lock-intern.h index f8874c7561..ed8acb6aec 100644 --- a/mach/lock-intern.h +++ b/mach/lock-intern.h @@ -19,12 +19,19 @@ #define _LOCK_INTERN_H #include -#include +#if defined __USE_EXTERN_INLINES && defined _LIBC +# include +#endif #ifndef _EXTERN_INLINE #define _EXTERN_INLINE __extern_inline #endif +/* The type of a spin lock variable. */ +typedef unsigned int __spin_lock_t; + +/* Static initializer for spinlocks. */ +#define __SPIN_LOCK_INITIALIZER LLL_INITIALIZER /* Initialize LOCK. */ @@ -50,31 +57,47 @@ extern void __spin_lock (__spin_lock_t *__lock); _EXTERN_INLINE void __spin_lock (__spin_lock_t *__lock) { - if (! __spin_try_lock (__lock)) - __spin_lock_solid (__lock); + lll_lock (__lock, 0); } #endif - -/* Name space-clean internal interface to mutex locks. - Code internal to the C library uses these functions to lock and unlock - mutex locks. These locks are of type `struct mutex', defined in - . The functions here are name space-clean. If the program - is linked with the cthreads library, `__mutex_lock_solid' and - `__mutex_unlock_solid' will invoke the corresponding cthreads functions - to implement real mutex locks. If not, simple stub versions just use - spin locks. */ +/* Unlock LOCK. */ +extern void __spin_unlock (__spin_lock_t *__lock); +#if defined __USE_EXTERN_INLINES && defined _LIBC +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + lll_unlock (__lock, 0); +} +#endif -/* Initialize the newly allocated mutex lock LOCK for further use. */ -extern void __mutex_init (void *__lock); +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ +extern int __spin_try_lock (__spin_lock_t *__lock); -/* Lock LOCK, blocking if we can't get it. */ -extern void __mutex_lock_solid (void *__lock); +#if defined __USE_EXTERN_INLINES && defined _LIBC +_EXTERN_INLINE int +__spin_try_lock (__spin_lock_t *__lock) +{ + return (lll_trylock (__lock) == 0); +} +#endif + +/* Return nonzero if LOCK is locked. */ +extern int __spin_lock_locked (__spin_lock_t *__lock); -/* Finish unlocking LOCK, after the spin lock LOCK->held has already been - unlocked. This function will wake up any thread waiting on LOCK. */ -extern void __mutex_unlock_solid (void *__lock); +#if defined __USE_EXTERN_INLINES && defined _LIBC +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return (*(volatile __spin_lock_t *)__lock != 0); +} +#endif + +/* Name space-clean internal interface to mutex locks. */ + +/* Initialize the newly allocated mutex lock LOCK for further use. */ +extern void __mutex_init (void *__lock); /* Lock the mutex lock LOCK. */ @@ -84,8 +107,7 @@ extern void __mutex_lock (void *__lock); _EXTERN_INLINE void __mutex_lock (void *__lock) { - if (! __spin_try_lock ((__spin_lock_t *) __lock)) - __mutex_lock_solid (__lock); + __spin_lock ((__spin_lock_t *)__lock); } #endif @@ -97,8 +119,7 @@ extern void __mutex_unlock (void *__lock); _EXTERN_INLINE void __mutex_unlock (void *__lock) { - __spin_unlock ((__spin_lock_t *) __lock); - __mutex_unlock_solid (__lock); + __spin_unlock ((__spin_lock_t *)__lock); } #endif @@ -109,7 +130,7 @@ extern int __mutex_trylock (void *__lock); _EXTERN_INLINE int __mutex_trylock (void *__lock) { - return __spin_try_lock ((__spin_lock_t *) __lock); + return (__spin_try_lock ((__spin_lock_t *)__lock)); } #endif diff --git a/mach/lowlevellock.h b/mach/lowlevellock.h new file mode 100644 index 0000000000..20c66ca979 --- /dev/null +++ b/mach/lowlevellock.h @@ -0,0 +1,81 @@ +/* Low-level lock implementation. Mach gsync-based version. + Copyright (C) 1994-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _MACH_LOWLEVELLOCK_H +#define _MACH_LOWLEVELLOCK_H 1 + +#include +#include + +/* Gsync flags. */ +#ifndef GSYNC_SHARED + #define GSYNC_SHARED 0x01 + #define GSYNC_QUAD 0x02 + #define GSYNC_TIMED 0x04 + #define GSYNC_BROADCAST 0x08 + #define GSYNC_MUTATE 0x10 +#endif + +/* Static initializer for low-level locks. */ +#define LLL_INITIALIZER 0 + +/* Wait on address PTR, without blocking if its contents + * are different from VAL. */ +#define lll_wait(ptr, val, flags) \ + __gsync_wait (__mach_task_self (), \ + (vm_offset_t)(ptr), (val), 0, 0, (flags)) + +/* Wake one or more threads waiting on address PTR. */ +#define lll_wake(ptr, flags) \ + __gsync_wake (__mach_task_self (), (vm_offset_t)(ptr), 0, (flags)) + +/* Acquire the lock at PTR. */ +#define lll_lock(ptr, flags) \ + ({ \ + int *__iptr = (int *)(ptr); \ + int __flags = (flags); \ + if (*__iptr != 0 || \ + atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) != 0) \ + while (1) \ + { \ + if (atomic_exchange_acq (__iptr, 2) == 0) \ + break; \ + lll_wait (__iptr, 2, __flags); \ + } \ + (void)0; \ + }) + +/* Try to acquire the lock at PTR, without blocking. + Evaluates to zero on success. */ +#define lll_trylock(ptr) \ + ({ \ + int *__iptr = (int *)(ptr); \ + *__iptr == 0 && \ + atomic_compare_and_exchange_bool_acq (__iptr, 1, 0) == 0 ? 0 : -1; \ + }) + +/* Release the lock at PTR. */ +#define lll_unlock(ptr, flags) \ + ({ \ + int *__iptr = (int *)(ptr); \ + if (atomic_exchange_rel (__iptr, 0) == 2) \ + lll_wake (__iptr, (flags)); \ + (void)0; \ + }) + +#endif diff --git a/mach/mutex-init.c b/mach/mutex-init.c index cab0a86fec..776fec5506 100644 --- a/mach/mutex-init.c +++ b/mach/mutex-init.c @@ -17,13 +17,10 @@ . */ #include -#include +#include void __mutex_init (void *lock) { - /* This happens to be name space-safe because it is a macro. - It invokes only spin_lock_init, which is a macro for __spin_lock_init; - and cthread_queue_init, which is a macro for some simple code. */ - mutex_init ((struct mutex *) lock); + *(int *)lock = LLL_INITIALIZER; } -- cgit 1.4.1