Implement new NPTL POSIX Threads ABI for HPPA.

This version of the NPTL POSIX thread ABI for hppa does
not break backwards compatibility with the the old
Linuxthreads ABI, and is therefore suitable for release
by distributions.

	sysdeps/unix/sysv/linux/hppa/
	* internaltypes.h: New file.

	sysdeps/unix/sysv/linux/hppa/nptl/
	* pthreadP.h: New file.
	* pthread.h: New file.
	* pthread_cond_broadcast.c: New file.
	* pthread_cond_destroy.c: New file.
	* pthread_cond_init.c: New file.
	* pthread_cond_signal.c: New file.
	* pthread_cond_timedwait.c: New file.
	* pthread_cond_wait.c: New file.
	* bits/pthreadtypes.h: Make pthread_mutex_t,
	pthread_rwlock_t, and pthread_cond_t backwards
	compatible.
This commit is contained in:
Carlos O'Donell 2009-09-08 14:32:53 -04:00
parent f0e6944906
commit be0f2008ac
11 changed files with 1601 additions and 4 deletions

View File

@ -1,3 +1,21 @@
2009-09-08 Carlos O'Donell <carlos@codesourcery.com>
sysdeps/unix/sysv/linux/hppa/
* internaltypes.h: New file.
sysdeps/unix/sysv/linux/hppa/nptl/
* pthreadP.h: New file.
* pthread.h: New file.
* pthread_cond_broadcast.c: New file.
* pthread_cond_destroy.c: New file.
* pthread_cond_init.c: New file.
* pthread_cond_signal.c: New file.
* pthread_cond_timedwait.c: New file.
* pthread_cond_wait.c: New file.
* bits/pthreadtypes.h: Make pthread_mutex_t,
pthread_rwlock_t, and pthread_cond_t backwards
compatible.
2009-04-24 Carlos O'Donell <carlos@codesourcery.com>
* sysdeps/hppa/hppa1.1/s_signbit.c: New file.

View File

@ -0,0 +1,79 @@
#include_next <internaltypes.h>
#ifndef _INTERNAL_TYPES_H_HPPA_
#define _INTERNAL_TYPES_H_HPPA_ 1
#include <atomic.h>
/* In GLIBC 2.10 HPPA switched from Linuxthreads to NPTL, and in order
to maintain ABI compatibility with pthread_cond_t, some care had to be
taken.
The NPTL pthread_cond_t grew in size. When HPPA switched to NPTL, we
dropped the use of ldcw, and switched to the kernel helper routine for
compare-and-swap. This allowed HPPA to use the 4-word 16-byte aligned
lock words, and alignment words to store the additional pthread_cond_t
data. Once organized properly the new NPTL pthread_cond_t was 1 word
smaller than the Linuxthreads version.
However, we were faced with the case that users may have initialized the
pthread_cond_t with PTHREAD_COND_INITIALIZER. In this case, the first
four words were set to one, and must be cleared before any NPTL code
used these words.
We didn't want to use LDCW, because it continues to be a source of bugs
when applications memset pthread_cond_t to all zeroes by accident. This
works on all other architectures where lock words are unlocked at zero.
Remember that because of the semantics of LDCW, a locked word is set to
zero, and an unlocked word is set to 1.
Instead we used atomic_compare_and_exchange_val_acq, but we couldn't use
this on any of the pthread_cond_t words, otherwise it might interfere
with the current operation of the structure. To solve this problem we
used the left over word.
If the stucture was initialized by a legacy Linuxthread
PTHREAD_COND_INITIALIZER it contained a 1, and this indicates that the
structure requires zeroing for NPTL. The first thread to come upon a
pthread_cond_t with a 1 in the __initializer field, will
compare-and-swap the value, placing a 2 there which will cause all other
threads using the same pthread_cond_t to wait for the completion of the
initialization. Lastly, we use a store (with memory barrier) to change
__initializer from 2 to 0. Note that the store is strongly ordered, but
we use the PA 1.1 compatible form which is ",ma" with zero offset.
In the future, when the application is recompiled with NPTL
PTHREAD_COND_INITIALIZER it will be a quick compare-and-swap, which
fails because __initializer is zero, and the structure will be used as
is correctly. */
#define cond_compat_clear(var) \
({ \
int tmp = 0; \
var->__data.__lock = 0; \
var->__data.__futex = 0; \
var->__data.__mutex = NULL; \
/* Clear __initializer last, to indicate initialization is done. */ \
__asm__ __volatile__ ("stw,ma %1,0(%0)" \
: : "r" (&var->__data.__initializer), "r" (tmp) : "memory"); \
})
#define cond_compat_check_and_clear(var) \
({ \
int ret; \
volatile int *value = &var->__data.__initializer; \
if ((ret = atomic_compare_and_exchange_val_acq(value, 2, 1))) \
{ \
if (ret == 1) \
{ \
/* Initialize structure. */ \
cond_compat_clear (var); \
} \
else \
{ \
/* Yield until structure is initialized. */ \
while (*value == 2) sched_yield (); \
} \
} \
})
#endif

View File

@ -34,7 +34,7 @@
#define __SIZEOF_PTHREAD_ATTR_T 36
#define __SIZEOF_PTHREAD_BARRIER_T 48
#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
#define __SIZEOF_PTHREAD_COND_T 64
#define __SIZEOF_PTHREAD_COND_T 48
#define __SIZEOF_PTHREAD_CONDATTR_T 4
#define __SIZEOF_PTHREAD_MUTEX_T 48
#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
@ -70,12 +70,22 @@ typedef union
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
/* The old 4-word 16-byte aligned lock. This is initalized
to all ones by the Linuxthreads PTHREAD_MUTEX_INITIALIZER.
Unused in NPTL. */
int __compat_padding[4];
/* In the old structure there are 4 words left due to alignment.
In NPTL two words are used. */
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
/* Two more words are left before the NPTL
pthread_mutex_t is larger than Linuxthreads. */
int __reserved1;
int __reserved2;
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
@ -89,19 +99,37 @@ typedef union
/* Data structure for conditional variable handling. The structure of
the attribute type is not exposed on purpose. */
the attribute type is not exposed on purpose. However, this structure
is exposed via PTHREAD_COND_INITIALIZER, and because of this, the
Linuxthreads version sets the first four ints to one. In the NPTL
version we must check, in every function using pthread_cond_t,
for the static Linuxthreads initializer and clear the appropriate
words. */
typedef union
{
struct
{
/* In the old Linuxthreads pthread_cond_t, this is the
start of the 4-word lock structure, the next four words
are set all to 1 by the Linuxthreads
PTHREAD_COND_INITIALIZER. */
int __lock;
/* Tracks the initialization of this structure:
0 initialized with NPTL PTHREAD_COND_INITIALIZER.
1 initialized with Linuxthreads PTHREAD_COND_INITIALIZER.
2 initialization in progress. */
int __initializer;
unsigned int __futex;
void *__mutex;
/* In the old Linuxthreads this would have been the start
of the pthread_fastlock status word. */
__extension__ unsigned long long int __total_seq;
__extension__ unsigned long long int __wakeup_seq;
__extension__ unsigned long long int __woken_seq;
void *__mutex;
unsigned int __nwaiters;
unsigned int __broadcast_seq;
/* The NPTL pthread_cond_t is exactly the same size as
the Linuxthreads version, there are no words to spare. */
} __data;
char __size[__SIZEOF_PTHREAD_COND_T];
__extension__ long long int __align;
@ -129,19 +157,34 @@ typedef union
{
struct
{
/* In the old Linuxthreads pthread_rwlock_t, this is the
start of the 4-word 16-byte aligned lock structure. The
next four words are all set to 1 by the Linuxthreads
PTHREAD_RWLOCK_INITIALIZER. We ignore them in NPTL. */
int __compat_padding[4];
int __lock;
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
int __writer;
/* An unused word, reserved for future use. It was added
to maintain the location of the flags from the Linuxthreads
layout of this structure. */
int __reserved1;
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
unsigned char __pad2;
unsigned char __pad1;
unsigned char __shared;
unsigned char __flags;
int __writer;
/* The NPTL pthread_rwlock_t is 4 words smaller than the
Linuxthreads version. One word is in the middle of the
structure, the other three are at the end. */
int __reserved2;
int __reserved3;
int __reserved4;
} __data;
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
long int __align;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
#include_next <pthreadP.h>
#ifndef _PTHREADP_H_HPPA_
#define _PTHREADP_H_HPPA_ 1
/* Internal cond functions. */
extern int __pthread_cond_broadcast_internal (pthread_cond_t *cond);
extern int __pthread_cond_destroy_internal (pthread_cond_t *cond);
extern int __pthread_cond_init_internal (pthread_cond_t *cond,
const pthread_condattr_t *cond_attr);
extern int __pthread_cond_signal_internal (pthread_cond_t *cond);
extern int __pthread_cond_timedwait_internal (pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime);
extern int __pthread_cond_wait_internal (pthread_cond_t *cond,
pthread_mutex_t *mutex);
#endif

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <pthread_cond_broadcast.c>
#else
# include <pthread.h>
# include <pthreadP.h>
# include <internaltypes.h>
# include <shlib-compat.h>
int
__pthread_cond_broadcast (cond)
pthread_cond_t *cond;
{
cond_compat_check_and_clear (cond);
return __pthread_cond_broadcast_internal (cond);
}
versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
GLIBC_2_3_2);
# undef versioned_symbol
# define versioned_symbol(lib, local, symbol, version)
# undef __pthread_cond_broadcast
# define __pthread_cond_broadcast __pthread_cond_broadcast_internal
# include_next <pthread_cond_broadcast.c>
#endif

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <pthread_cond_destroy.c>
#else
# include <pthread.h>
# include <pthreadP.h>
# include <internaltypes.h>
# include <shlib-compat.h>
int
__pthread_cond_destroy (cond)
pthread_cond_t *cond;
{
cond_compat_check_and_clear (cond);
return __pthread_cond_destroy_internal (cond);
}
versioned_symbol (libpthread, __pthread_cond_destroy, pthread_cond_destroy,
GLIBC_2_3_2);
# undef versioned_symbol
# define versioned_symbol(lib, local, symbol, version)
# undef __pthread_cond_destroy
# define __pthread_cond_destroy __pthread_cond_destroy_internal
# include_next <pthread_cond_destroy.c>
#endif

View File

@ -0,0 +1,44 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <pthread_cond_init.c>
#else
# include <pthread.h>
# include <pthreadP.h>
# include <internaltypes.h>
# include <shlib-compat.h>
int
__pthread_cond_init (cond, cond_attr)
pthread_cond_t *cond;
const pthread_condattr_t *cond_attr;
{
cond_compat_clear (cond);
return __pthread_cond_init_internal (cond, cond_attr);
}
versioned_symbol (libpthread, __pthread_cond_init, pthread_cond_init,
GLIBC_2_3_2);
# undef versioned_symbol
# define versioned_symbol(lib, local, symbol, version)
# undef __pthread_cond_init
# define __pthread_cond_init __pthread_cond_init_internal
# include_next <pthread_cond_init.c>
#endif

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <pthread_cond_signal.c>
#else
# include <pthread.h>
# include <pthreadP.h>
# include <internaltypes.h>
# include <shlib-compat.h>
int
__pthread_cond_signal (cond)
pthread_cond_t *cond;
{
cond_compat_check_and_clear (cond);
return __pthread_cond_signal_internal (cond);
}
versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
GLIBC_2_3_2);
# undef versioned_symbol
# define versioned_symbol(lib, local, symbol, version)
# undef __pthread_cond_signal
# define __pthread_cond_signal __pthread_cond_signal_internal
# include_next <pthread_cond_signal.c>
#endif

View File

@ -0,0 +1,45 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <pthread_cond_timedwait.c>
#else
# include <pthread.h>
# include <pthreadP.h>
# include <internaltypes.h>
# include <shlib-compat.h>
int
__pthread_cond_timedwait (cond, mutex, abstime)
pthread_cond_t *cond;
pthread_mutex_t *mutex;
const struct timespec *abstime;
{
cond_compat_check_and_clear (cond);
return __pthread_cond_timedwait_internal (cond, mutex, abstime);
}
versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
GLIBC_2_3_2);
# undef versioned_symbol
# define versioned_symbol(lib, local, symbol, version)
# undef __pthread_cond_timedwait
# define __pthread_cond_timedwait __pthread_cond_timedwait_internal
# include_next <pthread_cond_timedwait.c>
#endif

View File

@ -0,0 +1,44 @@
/* Copyright (C) 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@codesourcery.com>, 2009.
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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <pthread_cond_wait.c>
#else
# include <pthread.h>
# include <pthreadP.h>
# include <internaltypes.h>
# include <shlib-compat.h>
int
__pthread_cond_wait (cond, mutex)
pthread_cond_t *cond;
pthread_mutex_t *mutex;
{
cond_compat_check_and_clear (cond);
return __pthread_cond_wait_internal (cond, mutex);
}
versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
GLIBC_2_3_2);
# undef versioned_symbol
# define versioned_symbol(lib, local, symbol, version)
# undef __pthread_cond_wait
# define __pthread_cond_wait __pthread_cond_wait_internal
# include_next <pthread_cond_wait.c>
#endif