mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Added missing files.
Changed direntry in gnupg.texi from gpg to gpg2.
This commit is contained in:
parent
71b6a940a3
commit
02a2e26489
6
TODO
6
TODO
@ -112,3 +112,9 @@
|
|||||||
* Extend selinux support to other modules
|
* Extend selinux support to other modules
|
||||||
|
|
||||||
* Remove -sat PGP2 compatibility hack
|
* Remove -sat PGP2 compatibility hack
|
||||||
|
|
||||||
|
* gnupg14/mpi: rsa_verify
|
||||||
|
Is this is optimized for a 160 bit hash?
|
||||||
|
|
||||||
|
* Cleanup m4/ on next gettext update
|
||||||
|
There is at least one couple of duplicate files: inttype[_-]h.m4.
|
||||||
|
@ -48,7 +48,7 @@ section entitled ``Copying''.
|
|||||||
|
|
||||||
@dircategory GNU Utilities
|
@dircategory GNU Utilities
|
||||||
@direntry
|
@direntry
|
||||||
* gpg: (gnupg). OpenPGP encryption and signing tool.
|
* gpg2: (gnupg). OpenPGP encryption and signing tool.
|
||||||
* gpgsm: (gnupg). S/MIME encryption and signing tool.
|
* gpgsm: (gnupg). S/MIME encryption and signing tool.
|
||||||
@end direntry
|
@end direntry
|
||||||
|
|
||||||
|
162
doc/gpgv.texi
Normal file
162
doc/gpgv.texi
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
@c Copyright (C) 2004 Free Software Foundation, Inc.
|
||||||
|
@c This is part of the GnuPG manual.
|
||||||
|
@c For copying conditions, see the file GnuPG.texi.
|
||||||
|
|
||||||
|
@c
|
||||||
|
@c This is included by tools.texi.
|
||||||
|
@c
|
||||||
|
|
||||||
|
@c Begin GnuPG 1.x specific stuff
|
||||||
|
@ifset gpgone
|
||||||
|
@macro gpgvname
|
||||||
|
gpgv
|
||||||
|
@end macro
|
||||||
|
@manpage gpgv.1
|
||||||
|
@node gpgv
|
||||||
|
@section Verify OpenPGP signatures
|
||||||
|
@ifset manverb
|
||||||
|
.B gpgv
|
||||||
|
\- Verify OpenPGP signatures
|
||||||
|
@end ifset
|
||||||
|
|
||||||
|
@mansect synopsis
|
||||||
|
@ifset manverb
|
||||||
|
.B gpgv
|
||||||
|
.RI [ options ]
|
||||||
|
.I signed_files
|
||||||
|
@end ifset
|
||||||
|
@end ifset
|
||||||
|
@c End GnuPG 1.x specific stuff
|
||||||
|
|
||||||
|
@c Begin GnuPG 2 specific stuff
|
||||||
|
@ifclear gpgone
|
||||||
|
@macro gpgvname
|
||||||
|
gpgv2
|
||||||
|
@end macro
|
||||||
|
@manpage gpgv2.1
|
||||||
|
@node gpgv
|
||||||
|
@section Verify OpenPGP signatures
|
||||||
|
@ifset manverb
|
||||||
|
.B gpgv2
|
||||||
|
\- Verify OpenPGP signatures
|
||||||
|
@end ifset
|
||||||
|
|
||||||
|
@mansect synopsis
|
||||||
|
@ifset manverb
|
||||||
|
.B gpgv2
|
||||||
|
.RI [ options ]
|
||||||
|
.I signed_files
|
||||||
|
@end ifset
|
||||||
|
@end ifclear
|
||||||
|
@c End GnuPG 2 specific stuff
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@mansect description
|
||||||
|
@code{@gpgvname} is an OpenPGP signature verification tool.
|
||||||
|
|
||||||
|
This program is actually a stripped down version of @code{gpg} which is
|
||||||
|
only able to check signatures. It is somewhat smaller than the fully blown
|
||||||
|
@code{gpg} and uses a different (and simpler) way to check that
|
||||||
|
the public keys used to make the signature are valid. There are
|
||||||
|
no configuration files and only a few options are implemented.
|
||||||
|
|
||||||
|
@code{@gpgvname} assumes that all keys in the keyring are trustworthy.
|
||||||
|
By default it uses a keyring named @file{trustedkeys.gpg} which is
|
||||||
|
assumed to be in the home directory as defined by GnuPG or set by an
|
||||||
|
option or an environment variable. An option may be used to specify
|
||||||
|
another keyring or even multiple keyrings.
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
@mansect options
|
||||||
|
@code{@gpgvname} recognizes these options:
|
||||||
|
|
||||||
|
@table @gnupgtabopt
|
||||||
|
|
||||||
|
@item --verbose
|
||||||
|
@itemx -v
|
||||||
|
@opindex verbose
|
||||||
|
Gives more information during processing. If used
|
||||||
|
twice, the input data is listed in detail.
|
||||||
|
|
||||||
|
@item --quiet
|
||||||
|
@itemx -q
|
||||||
|
@opindex quiet
|
||||||
|
Try to be as quiet as possible.
|
||||||
|
|
||||||
|
@item --keyring @var{file}
|
||||||
|
@opindex keyring
|
||||||
|
Add @var{file} to the list of keyrings.
|
||||||
|
If @var{file} begins with a tilde and a slash, these
|
||||||
|
are replaced by the HOME directory. If the filename
|
||||||
|
does not contain a slash, it is assumed to be in the
|
||||||
|
home-directory ("~/.gnupg" if --homedir is not used).
|
||||||
|
|
||||||
|
@item --status-fd @var{n}
|
||||||
|
@opindex status-fd
|
||||||
|
Write special status strings to the file descriptor @var{n}. See the
|
||||||
|
file DETAILS in the documentation for a listing of them.
|
||||||
|
|
||||||
|
@item --logger-fd @code{n}
|
||||||
|
@opindex logger-fd
|
||||||
|
Write log output to file descriptor @code{n} and not to stderr.
|
||||||
|
|
||||||
|
@item --ignore-time-conflict
|
||||||
|
@opindex ignore-time-conflict
|
||||||
|
GnuPG normally checks that the timestamps associated with keys and
|
||||||
|
signatures have plausible values. However, sometimes a signature seems to
|
||||||
|
be older than the key due to clock problems. This option turns these
|
||||||
|
checks into warnings.
|
||||||
|
|
||||||
|
@include opt-homedir.texi
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@mansect return value
|
||||||
|
|
||||||
|
The program returns 0 if everything was fine, 1 if at least
|
||||||
|
one signature was bad, and other error codes for fatal errors.
|
||||||
|
|
||||||
|
@mansect examples
|
||||||
|
@subsection Examples
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
|
||||||
|
@item @gpgvname @code{pgpfile}
|
||||||
|
@itemx @gpgvname @code{sigfile}
|
||||||
|
Verify the signature of the file. The second form
|
||||||
|
is used for detached signatures, where @code{sigfile} is the detached
|
||||||
|
signature (either ASCII armored or binary) and are the signed
|
||||||
|
data; if this is not given the name of the file holding the signed data is
|
||||||
|
constructed by cutting off the extension (".asc", ".sig" or ".sign") from
|
||||||
|
@code{sigfile}.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@mansect environment
|
||||||
|
@subsection Environment
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
|
||||||
|
@item HOME
|
||||||
|
Used to locate the default home directory.
|
||||||
|
|
||||||
|
@item GNUPGHOME
|
||||||
|
If set directory used instead of "~/.gnupg".
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@mansect files
|
||||||
|
@subsection FILES
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
|
||||||
|
@item ~/.gnupg/trustedkeys.gpg
|
||||||
|
The default keyring with the allowed keys
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@mansect see also
|
||||||
|
@command{gpg2}(1)
|
||||||
|
@include see-also-note.texi
|
||||||
|
|
6
intl/export.h
Normal file
6
intl/export.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
#if @HAVE_VISIBILITY@ && BUILDING_LIBINTL
|
||||||
|
#define LIBINTL_DLL_EXPORTED __attribute__((__visibility__("default")))
|
||||||
|
#else
|
||||||
|
#define LIBINTL_DLL_EXPORTED
|
||||||
|
#endif
|
51
intl/hash-string.c
Normal file
51
intl/hash-string.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* Implements a string hashing function.
|
||||||
|
Copyright (C) 1995, 1997, 1998, 2000, 2003 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, write to the Free
|
||||||
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Specification. */
|
||||||
|
#include "hash-string.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Defines the so called `hashpjw' function by P.J. Weinberger
|
||||||
|
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
|
||||||
|
1986, 1987 Bell Telephone Laboratories, Inc.] */
|
||||||
|
unsigned long int
|
||||||
|
__hash_string (const char *str_param)
|
||||||
|
{
|
||||||
|
unsigned long int hval, g;
|
||||||
|
const char *str = str_param;
|
||||||
|
|
||||||
|
/* Compute the hash value for the given string. */
|
||||||
|
hval = 0;
|
||||||
|
while (*str != '\0')
|
||||||
|
{
|
||||||
|
hval <<= 4;
|
||||||
|
hval += (unsigned char) *str++;
|
||||||
|
g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
|
||||||
|
if (g != 0)
|
||||||
|
{
|
||||||
|
hval ^= g >> (HASHWORDBITS - 8);
|
||||||
|
hval ^= g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hval;
|
||||||
|
}
|
36
intl/intl-exports.c
Normal file
36
intl/intl-exports.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* List of exported symbols of libintl on Cygwin.
|
||||||
|
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||||
|
Written by Bruno Haible <bruno@clisp.org>, 2006.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
/* IMP(x) is a symbol that contains the address of x. */
|
||||||
|
#define IMP(x) _imp__##x
|
||||||
|
|
||||||
|
/* Ensure that the variable x is exported from the library, and that a
|
||||||
|
pseudo-variable IMP(x) is available. */
|
||||||
|
#define VARIABLE(x) \
|
||||||
|
/* Export x without redefining x. This code was found by compiling a \
|
||||||
|
snippet: \
|
||||||
|
extern __declspec(dllexport) int x; int x = 42; */ \
|
||||||
|
asm (".section .drectve\n"); \
|
||||||
|
asm (".ascii \" -export:" #x ",data\"\n"); \
|
||||||
|
asm (".data\n"); \
|
||||||
|
/* Allocate a pseudo-variable IMP(x). */ \
|
||||||
|
extern int x; \
|
||||||
|
void * IMP(x) = &x;
|
||||||
|
|
||||||
|
VARIABLE(libintl_version)
|
130
intl/langprefs.c
Normal file
130
intl/langprefs.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* Determine the user's language preferences.
|
||||||
|
Copyright (C) 2004-2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
/* Written by Bruno Haible <bruno@clisp.org>. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if HAVE_CFPREFERENCESCOPYAPPVALUE
|
||||||
|
# include <string.h>
|
||||||
|
# include <CoreFoundation/CFPreferences.h>
|
||||||
|
# include <CoreFoundation/CFPropertyList.h>
|
||||||
|
# include <CoreFoundation/CFArray.h>
|
||||||
|
# include <CoreFoundation/CFString.h>
|
||||||
|
extern void _nl_locale_name_canonicalize (char *name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Determine the user's language preferences, as a colon separated list of
|
||||||
|
locale names in XPG syntax
|
||||||
|
language[_territory[.codeset]][@modifier]
|
||||||
|
The result must not be freed; it is statically allocated.
|
||||||
|
The LANGUAGE environment variable does not need to be considered; it is
|
||||||
|
already taken into account by the caller. */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_nl_language_preferences_default (void)
|
||||||
|
{
|
||||||
|
#if HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.2 or newer */
|
||||||
|
{
|
||||||
|
/* Cache the preferences list, since CoreFoundation calls are expensive. */
|
||||||
|
static const char *cached_languages;
|
||||||
|
static int cache_initialized;
|
||||||
|
|
||||||
|
if (!cache_initialized)
|
||||||
|
{
|
||||||
|
CFTypeRef preferences =
|
||||||
|
CFPreferencesCopyAppValue (CFSTR ("AppleLanguages"),
|
||||||
|
kCFPreferencesCurrentApplication);
|
||||||
|
if (preferences != NULL
|
||||||
|
&& CFGetTypeID (preferences) == CFArrayGetTypeID ())
|
||||||
|
{
|
||||||
|
CFArrayRef prefArray = (CFArrayRef)preferences;
|
||||||
|
int n = CFArrayGetCount (prefArray);
|
||||||
|
char buf[256];
|
||||||
|
size_t size = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
CFTypeRef element = CFArrayGetValueAtIndex (prefArray, i);
|
||||||
|
if (element != NULL
|
||||||
|
&& CFGetTypeID (element) == CFStringGetTypeID ()
|
||||||
|
&& CFStringGetCString ((CFStringRef)element,
|
||||||
|
buf, sizeof (buf),
|
||||||
|
kCFStringEncodingASCII))
|
||||||
|
{
|
||||||
|
_nl_locale_name_canonicalize (buf);
|
||||||
|
size += strlen (buf) + 1;
|
||||||
|
/* Most GNU programs use msgids in English and don't ship
|
||||||
|
an en.mo message catalog. Therefore when we see "en"
|
||||||
|
in the preferences list, arrange for gettext() to
|
||||||
|
return the msgid, and ignore all further elements of
|
||||||
|
the preferences list. */
|
||||||
|
if (strcmp (buf, "en") == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
char *languages = (char *) malloc (size);
|
||||||
|
|
||||||
|
if (languages != NULL)
|
||||||
|
{
|
||||||
|
char *p = languages;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
CFTypeRef element =
|
||||||
|
CFArrayGetValueAtIndex (prefArray, i);
|
||||||
|
if (element != NULL
|
||||||
|
&& CFGetTypeID (element) == CFStringGetTypeID ()
|
||||||
|
&& CFStringGetCString ((CFStringRef)element,
|
||||||
|
buf, sizeof (buf),
|
||||||
|
kCFStringEncodingASCII))
|
||||||
|
{
|
||||||
|
_nl_locale_name_canonicalize (buf);
|
||||||
|
strcpy (p, buf);
|
||||||
|
p += strlen (buf);
|
||||||
|
*p++ = ':';
|
||||||
|
if (strcmp (buf, "en") == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*--p = '\0';
|
||||||
|
|
||||||
|
cached_languages = languages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache_initialized = 1;
|
||||||
|
}
|
||||||
|
if (cached_languages != NULL)
|
||||||
|
return cached_languages;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
924
intl/lock.c
Normal file
924
intl/lock.c
Normal file
@ -0,0 +1,924 @@
|
|||||||
|
/* Locking in multithreaded situations.
|
||||||
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
|
||||||
|
Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
|
||||||
|
gthr-win32.h. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "lock.h"
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_POSIX_THREADS
|
||||||
|
|
||||||
|
/* Use the POSIX threads library. */
|
||||||
|
|
||||||
|
# if PTHREAD_IN_USE_DETECTION_HARD
|
||||||
|
|
||||||
|
/* The function to be executed by a dummy thread. */
|
||||||
|
static void *
|
||||||
|
dummy_thread_func (void *arg)
|
||||||
|
{
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
glthread_in_use (void)
|
||||||
|
{
|
||||||
|
static int tested;
|
||||||
|
static int result; /* 1: linked with -lpthread, 0: only with libc */
|
||||||
|
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
pthread_t thread;
|
||||||
|
|
||||||
|
if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0)
|
||||||
|
/* Thread creation failed. */
|
||||||
|
result = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Thread creation works. */
|
||||||
|
void *retval;
|
||||||
|
if (pthread_join (thread, &retval) != 0)
|
||||||
|
abort ();
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
tested = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
# if HAVE_PTHREAD_RWLOCK
|
||||||
|
|
||||||
|
# if !defined PTHREAD_RWLOCK_INITIALIZER
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_init (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_rwlock_init (&lock->rwlock, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_rdlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->guard) != 0)
|
||||||
|
abort ();
|
||||||
|
if (!lock->initialized)
|
||||||
|
glthread_rwlock_init (lock);
|
||||||
|
if (pthread_mutex_unlock (&lock->guard) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
if (pthread_rwlock_rdlock (&lock->rwlock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_wrlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->guard) != 0)
|
||||||
|
abort ();
|
||||||
|
if (!lock->initialized)
|
||||||
|
glthread_rwlock_init (lock);
|
||||||
|
if (pthread_mutex_unlock (&lock->guard) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
if (pthread_rwlock_wrlock (&lock->rwlock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_unlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
abort ();
|
||||||
|
if (pthread_rwlock_unlock (&lock->rwlock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_destroy (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
abort ();
|
||||||
|
if (pthread_rwlock_destroy (&lock->rwlock) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->initialized = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_init (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_init (&lock->lock, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_cond_init (&lock->waiting_readers, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_cond_init (&lock->waiting_writers, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->waiting_writers_count = 0;
|
||||||
|
lock->runcount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_rdlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
/* Test whether only readers are currently running, and whether the runcount
|
||||||
|
field will not overflow. */
|
||||||
|
/* POSIX says: "It is implementation-defined whether the calling thread
|
||||||
|
acquires the lock when a writer does not hold the lock and there are
|
||||||
|
writers blocked on the lock." Let's say, no: give the writers a higher
|
||||||
|
priority. */
|
||||||
|
while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
|
||||||
|
{
|
||||||
|
/* This thread has to wait for a while. Enqueue it among the
|
||||||
|
waiting_readers. */
|
||||||
|
if (pthread_cond_wait (&lock->waiting_readers, &lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
lock->runcount++;
|
||||||
|
if (pthread_mutex_unlock (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_wrlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
/* Test whether no readers or writers are currently running. */
|
||||||
|
while (!(lock->runcount == 0))
|
||||||
|
{
|
||||||
|
/* This thread has to wait for a while. Enqueue it among the
|
||||||
|
waiting_writers. */
|
||||||
|
lock->waiting_writers_count++;
|
||||||
|
if (pthread_cond_wait (&lock->waiting_writers, &lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->waiting_writers_count--;
|
||||||
|
}
|
||||||
|
lock->runcount--; /* runcount becomes -1 */
|
||||||
|
if (pthread_mutex_unlock (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_unlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
if (lock->runcount < 0)
|
||||||
|
{
|
||||||
|
/* Drop a writer lock. */
|
||||||
|
if (!(lock->runcount == -1))
|
||||||
|
abort ();
|
||||||
|
lock->runcount = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Drop a reader lock. */
|
||||||
|
if (!(lock->runcount > 0))
|
||||||
|
abort ();
|
||||||
|
lock->runcount--;
|
||||||
|
}
|
||||||
|
if (lock->runcount == 0)
|
||||||
|
{
|
||||||
|
/* POSIX recommends that "write locks shall take precedence over read
|
||||||
|
locks", to avoid "writer starvation". */
|
||||||
|
if (lock->waiting_writers_count > 0)
|
||||||
|
{
|
||||||
|
/* Wake up one of the waiting writers. */
|
||||||
|
if (pthread_cond_signal (&lock->waiting_writers) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Wake up all waiting readers. */
|
||||||
|
if (pthread_cond_broadcast (&lock->waiting_readers) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pthread_mutex_unlock (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_destroy (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_destroy (&lock->lock) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_cond_destroy (&lock->waiting_readers) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_cond_destroy (&lock->waiting_writers) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
# if HAVE_PTHREAD_MUTEX_RECURSIVE
|
||||||
|
|
||||||
|
# if !(defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t attributes;
|
||||||
|
|
||||||
|
if (pthread_mutexattr_init (&attributes) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_mutex_init (&lock->recmutex, &attributes) != 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_mutexattr_destroy (&attributes) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->guard) != 0)
|
||||||
|
abort ();
|
||||||
|
if (!lock->initialized)
|
||||||
|
glthread_recursive_lock_init (lock);
|
||||||
|
if (pthread_mutex_unlock (&lock->guard) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
if (pthread_mutex_lock (&lock->recmutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
abort ();
|
||||||
|
if (pthread_mutex_unlock (&lock->recmutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->initialized)
|
||||||
|
abort ();
|
||||||
|
if (pthread_mutex_destroy (&lock->recmutex) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->initialized = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_init (&lock->mutex, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->owner = (pthread_t) 0;
|
||||||
|
lock->depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
pthread_t self = pthread_self ();
|
||||||
|
if (lock->owner != self)
|
||||||
|
{
|
||||||
|
if (pthread_mutex_lock (&lock->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->owner = self;
|
||||||
|
}
|
||||||
|
if (++(lock->depth) == 0) /* wraparound? */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (lock->owner != pthread_self ())
|
||||||
|
abort ();
|
||||||
|
if (lock->depth == 0)
|
||||||
|
abort ();
|
||||||
|
if (--(lock->depth) == 0)
|
||||||
|
{
|
||||||
|
lock->owner = (pthread_t) 0;
|
||||||
|
if (pthread_mutex_unlock (&lock->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (lock->owner != (pthread_t) 0)
|
||||||
|
abort ();
|
||||||
|
if (pthread_mutex_destroy (&lock->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
|
int
|
||||||
|
glthread_once_singlethreaded (pthread_once_t *once_control)
|
||||||
|
{
|
||||||
|
/* We don't know whether pthread_once_t is an integer type, a floating-point
|
||||||
|
type, a pointer type, or a structure type. */
|
||||||
|
char *firstbyte = (char *)once_control;
|
||||||
|
if (*firstbyte == *(const char *)&fresh_once)
|
||||||
|
{
|
||||||
|
/* First time use of once_control. Invert the first byte. */
|
||||||
|
*firstbyte = ~ *(const char *)&fresh_once;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_PTH_THREADS
|
||||||
|
|
||||||
|
/* Use the GNU Pth threads library. */
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_once_call (void *arg)
|
||||||
|
{
|
||||||
|
void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;
|
||||||
|
void (*initfunction) (void) = *gl_once_temp_addr;
|
||||||
|
initfunction ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
glthread_once_singlethreaded (pth_once_t *once_control)
|
||||||
|
{
|
||||||
|
/* We know that pth_once_t is an integer type. */
|
||||||
|
if (*once_control == PTH_ONCE_INIT)
|
||||||
|
{
|
||||||
|
/* First time use of once_control. Invert the marker. */
|
||||||
|
*once_control = ~ PTH_ONCE_INIT;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_SOLARIS_THREADS
|
||||||
|
|
||||||
|
/* Use the old Solaris threads library. */
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (mutex_init (&lock->mutex, USYNC_THREAD, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->owner = (thread_t) 0;
|
||||||
|
lock->depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
thread_t self = thr_self ();
|
||||||
|
if (lock->owner != self)
|
||||||
|
{
|
||||||
|
if (mutex_lock (&lock->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
lock->owner = self;
|
||||||
|
}
|
||||||
|
if (++(lock->depth) == 0) /* wraparound? */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (lock->owner != thr_self ())
|
||||||
|
abort ();
|
||||||
|
if (lock->depth == 0)
|
||||||
|
abort ();
|
||||||
|
if (--(lock->depth) == 0)
|
||||||
|
{
|
||||||
|
lock->owner = (thread_t) 0;
|
||||||
|
if (mutex_unlock (&lock->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (lock->owner != (thread_t) 0)
|
||||||
|
abort ();
|
||||||
|
if (mutex_destroy (&lock->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_once (gl_once_t *once_control, void (*initfunction) (void))
|
||||||
|
{
|
||||||
|
if (!once_control->inited)
|
||||||
|
{
|
||||||
|
/* Use the mutex to guarantee that if another thread is already calling
|
||||||
|
the initfunction, this thread waits until it's finished. */
|
||||||
|
if (mutex_lock (&once_control->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
if (!once_control->inited)
|
||||||
|
{
|
||||||
|
once_control->inited = 1;
|
||||||
|
initfunction ();
|
||||||
|
}
|
||||||
|
if (mutex_unlock (&once_control->mutex) != 0)
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
glthread_once_singlethreaded (gl_once_t *once_control)
|
||||||
|
{
|
||||||
|
/* We know that gl_once_t contains an integer type. */
|
||||||
|
if (!once_control->inited)
|
||||||
|
{
|
||||||
|
/* First time use of once_control. Invert the marker. */
|
||||||
|
once_control->inited = ~ 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_WIN32_THREADS
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_lock_init (gl_lock_t *lock)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection (&lock->lock);
|
||||||
|
lock->guard.done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_lock_lock (gl_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
{
|
||||||
|
if (InterlockedIncrement (&lock->guard.started) == 0)
|
||||||
|
/* This thread is the first one to need this lock. Initialize it. */
|
||||||
|
glthread_lock_init (lock);
|
||||||
|
else
|
||||||
|
/* Yield the CPU while waiting for another thread to finish
|
||||||
|
initializing this lock. */
|
||||||
|
while (!lock->guard.done)
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_lock_unlock (gl_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
abort ();
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_lock_destroy (gl_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
abort ();
|
||||||
|
DeleteCriticalSection (&lock->lock);
|
||||||
|
lock->guard.done = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gl_waitqueue_init (gl_waitqueue_t *wq)
|
||||||
|
{
|
||||||
|
wq->array = NULL;
|
||||||
|
wq->count = 0;
|
||||||
|
wq->alloc = 0;
|
||||||
|
wq->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enqueues the current thread, represented by an event, in a wait queue.
|
||||||
|
Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */
|
||||||
|
static HANDLE
|
||||||
|
gl_waitqueue_add (gl_waitqueue_t *wq)
|
||||||
|
{
|
||||||
|
HANDLE event;
|
||||||
|
unsigned int index;
|
||||||
|
|
||||||
|
if (wq->count == wq->alloc)
|
||||||
|
{
|
||||||
|
unsigned int new_alloc = 2 * wq->alloc + 1;
|
||||||
|
HANDLE *new_array =
|
||||||
|
(HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
|
||||||
|
if (new_array == NULL)
|
||||||
|
/* No more memory. */
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
/* Now is a good opportunity to rotate the array so that its contents
|
||||||
|
starts at offset 0. */
|
||||||
|
if (wq->offset > 0)
|
||||||
|
{
|
||||||
|
unsigned int old_count = wq->count;
|
||||||
|
unsigned int old_alloc = wq->alloc;
|
||||||
|
unsigned int old_offset = wq->offset;
|
||||||
|
unsigned int i;
|
||||||
|
if (old_offset + old_count > old_alloc)
|
||||||
|
{
|
||||||
|
unsigned int limit = old_offset + old_count - old_alloc;
|
||||||
|
for (i = 0; i < limit; i++)
|
||||||
|
new_array[old_alloc + i] = new_array[i];
|
||||||
|
}
|
||||||
|
for (i = 0; i < old_count; i++)
|
||||||
|
new_array[i] = new_array[old_offset + i];
|
||||||
|
wq->offset = 0;
|
||||||
|
}
|
||||||
|
wq->array = new_array;
|
||||||
|
wq->alloc = new_alloc;
|
||||||
|
}
|
||||||
|
event = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||||
|
if (event == INVALID_HANDLE_VALUE)
|
||||||
|
/* No way to allocate an event. */
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
index = wq->offset + wq->count;
|
||||||
|
if (index >= wq->alloc)
|
||||||
|
index -= wq->alloc;
|
||||||
|
wq->array[index] = event;
|
||||||
|
wq->count++;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notifies the first thread from a wait queue and dequeues it. */
|
||||||
|
static inline void
|
||||||
|
gl_waitqueue_notify_first (gl_waitqueue_t *wq)
|
||||||
|
{
|
||||||
|
SetEvent (wq->array[wq->offset + 0]);
|
||||||
|
wq->offset++;
|
||||||
|
wq->count--;
|
||||||
|
if (wq->count == 0 || wq->offset == wq->alloc)
|
||||||
|
wq->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notifies all threads from a wait queue and dequeues them all. */
|
||||||
|
static inline void
|
||||||
|
gl_waitqueue_notify_all (gl_waitqueue_t *wq)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < wq->count; i++)
|
||||||
|
{
|
||||||
|
unsigned int index = wq->offset + i;
|
||||||
|
if (index >= wq->alloc)
|
||||||
|
index -= wq->alloc;
|
||||||
|
SetEvent (wq->array[index]);
|
||||||
|
}
|
||||||
|
wq->count = 0;
|
||||||
|
wq->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_init (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection (&lock->lock);
|
||||||
|
gl_waitqueue_init (&lock->waiting_readers);
|
||||||
|
gl_waitqueue_init (&lock->waiting_writers);
|
||||||
|
lock->runcount = 0;
|
||||||
|
lock->guard.done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_rdlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
{
|
||||||
|
if (InterlockedIncrement (&lock->guard.started) == 0)
|
||||||
|
/* This thread is the first one to need this lock. Initialize it. */
|
||||||
|
glthread_rwlock_init (lock);
|
||||||
|
else
|
||||||
|
/* Yield the CPU while waiting for another thread to finish
|
||||||
|
initializing this lock. */
|
||||||
|
while (!lock->guard.done)
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
/* Test whether only readers are currently running, and whether the runcount
|
||||||
|
field will not overflow. */
|
||||||
|
if (!(lock->runcount + 1 > 0))
|
||||||
|
{
|
||||||
|
/* This thread has to wait for a while. Enqueue it among the
|
||||||
|
waiting_readers. */
|
||||||
|
HANDLE event = gl_waitqueue_add (&lock->waiting_readers);
|
||||||
|
if (event != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DWORD result;
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
/* Wait until another thread signals this event. */
|
||||||
|
result = WaitForSingleObject (event, INFINITE);
|
||||||
|
if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
|
||||||
|
abort ();
|
||||||
|
CloseHandle (event);
|
||||||
|
/* The thread which signalled the event already did the bookkeeping:
|
||||||
|
removed us from the waiting_readers, incremented lock->runcount. */
|
||||||
|
if (!(lock->runcount > 0))
|
||||||
|
abort ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Allocation failure. Weird. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
Sleep (1);
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
while (!(lock->runcount + 1 > 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock->runcount++;
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_wrlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
{
|
||||||
|
if (InterlockedIncrement (&lock->guard.started) == 0)
|
||||||
|
/* This thread is the first one to need this lock. Initialize it. */
|
||||||
|
glthread_rwlock_init (lock);
|
||||||
|
else
|
||||||
|
/* Yield the CPU while waiting for another thread to finish
|
||||||
|
initializing this lock. */
|
||||||
|
while (!lock->guard.done)
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
/* Test whether no readers or writers are currently running. */
|
||||||
|
if (!(lock->runcount == 0))
|
||||||
|
{
|
||||||
|
/* This thread has to wait for a while. Enqueue it among the
|
||||||
|
waiting_writers. */
|
||||||
|
HANDLE event = gl_waitqueue_add (&lock->waiting_writers);
|
||||||
|
if (event != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DWORD result;
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
/* Wait until another thread signals this event. */
|
||||||
|
result = WaitForSingleObject (event, INFINITE);
|
||||||
|
if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
|
||||||
|
abort ();
|
||||||
|
CloseHandle (event);
|
||||||
|
/* The thread which signalled the event already did the bookkeeping:
|
||||||
|
removed us from the waiting_writers, set lock->runcount = -1. */
|
||||||
|
if (!(lock->runcount == -1))
|
||||||
|
abort ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Allocation failure. Weird. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
Sleep (1);
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
while (!(lock->runcount == 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock->runcount--; /* runcount becomes -1 */
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_unlock (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
abort ();
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
if (lock->runcount < 0)
|
||||||
|
{
|
||||||
|
/* Drop a writer lock. */
|
||||||
|
if (!(lock->runcount == -1))
|
||||||
|
abort ();
|
||||||
|
lock->runcount = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Drop a reader lock. */
|
||||||
|
if (!(lock->runcount > 0))
|
||||||
|
abort ();
|
||||||
|
lock->runcount--;
|
||||||
|
}
|
||||||
|
if (lock->runcount == 0)
|
||||||
|
{
|
||||||
|
/* POSIX recommends that "write locks shall take precedence over read
|
||||||
|
locks", to avoid "writer starvation". */
|
||||||
|
if (lock->waiting_writers.count > 0)
|
||||||
|
{
|
||||||
|
/* Wake up one of the waiting writers. */
|
||||||
|
lock->runcount--;
|
||||||
|
gl_waitqueue_notify_first (&lock->waiting_writers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Wake up all waiting readers. */
|
||||||
|
lock->runcount += lock->waiting_readers.count;
|
||||||
|
gl_waitqueue_notify_all (&lock->waiting_readers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_rwlock_destroy (gl_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
abort ();
|
||||||
|
if (lock->runcount != 0)
|
||||||
|
abort ();
|
||||||
|
DeleteCriticalSection (&lock->lock);
|
||||||
|
if (lock->waiting_readers.array != NULL)
|
||||||
|
free (lock->waiting_readers.array);
|
||||||
|
if (lock->waiting_writers.array != NULL)
|
||||||
|
free (lock->waiting_writers.array);
|
||||||
|
lock->guard.done = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_init (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
lock->owner = 0;
|
||||||
|
lock->depth = 0;
|
||||||
|
InitializeCriticalSection (&lock->lock);
|
||||||
|
lock->guard.done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (!lock->guard.done)
|
||||||
|
{
|
||||||
|
if (InterlockedIncrement (&lock->guard.started) == 0)
|
||||||
|
/* This thread is the first one to need this lock. Initialize it. */
|
||||||
|
glthread_recursive_lock_init (lock);
|
||||||
|
else
|
||||||
|
/* Yield the CPU while waiting for another thread to finish
|
||||||
|
initializing this lock. */
|
||||||
|
while (!lock->guard.done)
|
||||||
|
Sleep (0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
DWORD self = GetCurrentThreadId ();
|
||||||
|
if (lock->owner != self)
|
||||||
|
{
|
||||||
|
EnterCriticalSection (&lock->lock);
|
||||||
|
lock->owner = self;
|
||||||
|
}
|
||||||
|
if (++(lock->depth) == 0) /* wraparound? */
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (lock->owner != GetCurrentThreadId ())
|
||||||
|
abort ();
|
||||||
|
if (lock->depth == 0)
|
||||||
|
abort ();
|
||||||
|
if (--(lock->depth) == 0)
|
||||||
|
{
|
||||||
|
lock->owner = 0;
|
||||||
|
LeaveCriticalSection (&lock->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
|
||||||
|
{
|
||||||
|
if (lock->owner != 0)
|
||||||
|
abort ();
|
||||||
|
DeleteCriticalSection (&lock->lock);
|
||||||
|
lock->guard.done = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
glthread_once (gl_once_t *once_control, void (*initfunction) (void))
|
||||||
|
{
|
||||||
|
if (once_control->inited <= 0)
|
||||||
|
{
|
||||||
|
if (InterlockedIncrement (&once_control->started) == 0)
|
||||||
|
{
|
||||||
|
/* This thread is the first one to come to this once_control. */
|
||||||
|
InitializeCriticalSection (&once_control->lock);
|
||||||
|
EnterCriticalSection (&once_control->lock);
|
||||||
|
once_control->inited = 0;
|
||||||
|
initfunction ();
|
||||||
|
once_control->inited = 1;
|
||||||
|
LeaveCriticalSection (&once_control->lock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Undo last operation. */
|
||||||
|
InterlockedDecrement (&once_control->started);
|
||||||
|
/* Some other thread has already started the initialization.
|
||||||
|
Yield the CPU while waiting for the other thread to finish
|
||||||
|
initializing and taking the lock. */
|
||||||
|
while (once_control->inited < 0)
|
||||||
|
Sleep (0);
|
||||||
|
if (once_control->inited <= 0)
|
||||||
|
{
|
||||||
|
/* Take the lock. This blocks until the other thread has
|
||||||
|
finished calling the initfunction. */
|
||||||
|
EnterCriticalSection (&once_control->lock);
|
||||||
|
LeaveCriticalSection (&once_control->lock);
|
||||||
|
if (!(once_control->inited > 0))
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
801
intl/lock.h
Normal file
801
intl/lock.h
Normal file
@ -0,0 +1,801 @@
|
|||||||
|
/* Locking in multithreaded situations.
|
||||||
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
|
||||||
|
Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
|
||||||
|
gthr-win32.h. */
|
||||||
|
|
||||||
|
/* This file contains locking primitives for use with a given thread library.
|
||||||
|
It does not contain primitives for creating threads or for other
|
||||||
|
synchronization primitives.
|
||||||
|
|
||||||
|
Normal (non-recursive) locks:
|
||||||
|
Type: gl_lock_t
|
||||||
|
Declaration: gl_lock_define(extern, name)
|
||||||
|
Initializer: gl_lock_define_initialized(, name)
|
||||||
|
Initialization: gl_lock_init (name);
|
||||||
|
Taking the lock: gl_lock_lock (name);
|
||||||
|
Releasing the lock: gl_lock_unlock (name);
|
||||||
|
De-initialization: gl_lock_destroy (name);
|
||||||
|
|
||||||
|
Read-Write (non-recursive) locks:
|
||||||
|
Type: gl_rwlock_t
|
||||||
|
Declaration: gl_rwlock_define(extern, name)
|
||||||
|
Initializer: gl_rwlock_define_initialized(, name)
|
||||||
|
Initialization: gl_rwlock_init (name);
|
||||||
|
Taking the lock: gl_rwlock_rdlock (name);
|
||||||
|
gl_rwlock_wrlock (name);
|
||||||
|
Releasing the lock: gl_rwlock_unlock (name);
|
||||||
|
De-initialization: gl_rwlock_destroy (name);
|
||||||
|
|
||||||
|
Recursive locks:
|
||||||
|
Type: gl_recursive_lock_t
|
||||||
|
Declaration: gl_recursive_lock_define(extern, name)
|
||||||
|
Initializer: gl_recursive_lock_define_initialized(, name)
|
||||||
|
Initialization: gl_recursive_lock_init (name);
|
||||||
|
Taking the lock: gl_recursive_lock_lock (name);
|
||||||
|
Releasing the lock: gl_recursive_lock_unlock (name);
|
||||||
|
De-initialization: gl_recursive_lock_destroy (name);
|
||||||
|
|
||||||
|
Once-only execution:
|
||||||
|
Type: gl_once_t
|
||||||
|
Initializer: gl_once_define(extern, name)
|
||||||
|
Execution: gl_once (name, initfunction);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _LOCK_H
|
||||||
|
#define _LOCK_H
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_POSIX_THREADS
|
||||||
|
|
||||||
|
/* Use the POSIX threads library. */
|
||||||
|
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
# if PTHREAD_IN_USE_DETECTION_HARD
|
||||||
|
|
||||||
|
/* The pthread_in_use() detection needs to be done at runtime. */
|
||||||
|
# define pthread_in_use() \
|
||||||
|
glthread_in_use ()
|
||||||
|
extern int glthread_in_use (void);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if USE_POSIX_THREADS_WEAK
|
||||||
|
|
||||||
|
/* Use weak references to the POSIX threads library. */
|
||||||
|
|
||||||
|
/* Weak references avoid dragging in external libraries if the other parts
|
||||||
|
of the program don't use them. Here we use them, because we don't want
|
||||||
|
every program that uses libintl to depend on libpthread. This assumes
|
||||||
|
that libpthread would not be loaded after libintl; i.e. if libintl is
|
||||||
|
loaded first, by an executable that does not depend on libpthread, and
|
||||||
|
then a module is dynamically loaded that depends on libpthread, libintl
|
||||||
|
will not be multithread-safe. */
|
||||||
|
|
||||||
|
/* The way to test at runtime whether libpthread is present is to test
|
||||||
|
whether a function pointer's value, such as &pthread_mutex_init, is
|
||||||
|
non-NULL. However, some versions of GCC have a bug through which, in
|
||||||
|
PIC mode, &foo != NULL always evaluates to true if there is a direct
|
||||||
|
call to foo(...) in the same function. To avoid this, we test the
|
||||||
|
address of a function in libpthread that we don't use. */
|
||||||
|
|
||||||
|
# pragma weak pthread_mutex_init
|
||||||
|
# pragma weak pthread_mutex_lock
|
||||||
|
# pragma weak pthread_mutex_unlock
|
||||||
|
# pragma weak pthread_mutex_destroy
|
||||||
|
# pragma weak pthread_rwlock_init
|
||||||
|
# pragma weak pthread_rwlock_rdlock
|
||||||
|
# pragma weak pthread_rwlock_wrlock
|
||||||
|
# pragma weak pthread_rwlock_unlock
|
||||||
|
# pragma weak pthread_rwlock_destroy
|
||||||
|
# pragma weak pthread_once
|
||||||
|
# pragma weak pthread_cond_init
|
||||||
|
# pragma weak pthread_cond_wait
|
||||||
|
# pragma weak pthread_cond_signal
|
||||||
|
# pragma weak pthread_cond_broadcast
|
||||||
|
# pragma weak pthread_cond_destroy
|
||||||
|
# pragma weak pthread_mutexattr_init
|
||||||
|
# pragma weak pthread_mutexattr_settype
|
||||||
|
# pragma weak pthread_mutexattr_destroy
|
||||||
|
# ifndef pthread_self
|
||||||
|
# pragma weak pthread_self
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if !PTHREAD_IN_USE_DETECTION_HARD
|
||||||
|
# pragma weak pthread_cancel
|
||||||
|
# define pthread_in_use() (pthread_cancel != NULL)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
# if !PTHREAD_IN_USE_DETECTION_HARD
|
||||||
|
# define pthread_in_use() 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef pthread_mutex_t gl_lock_t;
|
||||||
|
# define gl_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_mutex_t NAME;
|
||||||
|
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
|
||||||
|
# define gl_lock_initializer \
|
||||||
|
PTHREAD_MUTEX_INITIALIZER
|
||||||
|
# define gl_lock_init(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
|
||||||
|
# define gl_lock_lock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
|
||||||
|
# define gl_lock_unlock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_lock_destroy(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
# if HAVE_PTHREAD_RWLOCK
|
||||||
|
|
||||||
|
# ifdef PTHREAD_RWLOCK_INITIALIZER
|
||||||
|
|
||||||
|
typedef pthread_rwlock_t gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_rwlock_t NAME;
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
|
||||||
|
# define gl_rwlock_initializer \
|
||||||
|
PTHREAD_RWLOCK_INITIALIZER
|
||||||
|
# define gl_rwlock_init(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
|
||||||
|
# define gl_rwlock_rdlock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_rwlock_wrlock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_rwlock_unlock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_rwlock_destroy(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int initialized;
|
||||||
|
pthread_mutex_t guard; /* protects the initialization */
|
||||||
|
pthread_rwlock_t rwlock; /* read-write lock */
|
||||||
|
}
|
||||||
|
gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_rwlock_t NAME;
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
|
||||||
|
# define gl_rwlock_initializer \
|
||||||
|
{ 0, PTHREAD_MUTEX_INITIALIZER }
|
||||||
|
# define gl_rwlock_init(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_init (&NAME)
|
||||||
|
# define gl_rwlock_rdlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
|
||||||
|
# define gl_rwlock_wrlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
|
||||||
|
# define gl_rwlock_unlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
|
||||||
|
# define gl_rwlock_destroy(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
|
||||||
|
extern void glthread_rwlock_init (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_mutex_t lock; /* protects the remaining fields */
|
||||||
|
pthread_cond_t waiting_readers; /* waiting readers */
|
||||||
|
pthread_cond_t waiting_writers; /* waiting writers */
|
||||||
|
unsigned int waiting_writers_count; /* number of waiting writers */
|
||||||
|
int runcount; /* number of readers running, or -1 when a writer runs */
|
||||||
|
}
|
||||||
|
gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_rwlock_t NAME;
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
|
||||||
|
# define gl_rwlock_initializer \
|
||||||
|
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
|
||||||
|
# define gl_rwlock_init(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_init (&NAME)
|
||||||
|
# define gl_rwlock_rdlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
|
||||||
|
# define gl_rwlock_wrlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
|
||||||
|
# define gl_rwlock_unlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
|
||||||
|
# define gl_rwlock_destroy(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
|
||||||
|
extern void glthread_rwlock_init (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
# if HAVE_PTHREAD_MUTEX_RECURSIVE
|
||||||
|
|
||||||
|
# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
|
||||||
|
|
||||||
|
typedef pthread_mutex_t gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_mutex_t NAME;
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
|
||||||
|
# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
PTHREAD_RECURSIVE_MUTEX_INITIALIZER
|
||||||
|
# else
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
|
||||||
|
# endif
|
||||||
|
# define gl_recursive_lock_init(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
|
||||||
|
# define gl_recursive_lock_lock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
|
||||||
|
# define gl_recursive_lock_unlock(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_recursive_lock_destroy(NAME) \
|
||||||
|
if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_mutex_t recmutex; /* recursive mutex */
|
||||||
|
pthread_mutex_t guard; /* protects the initialization */
|
||||||
|
int initialized;
|
||||||
|
}
|
||||||
|
gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME;
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
{ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
|
||||||
|
# define gl_recursive_lock_init(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
|
||||||
|
# define gl_recursive_lock_lock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
|
||||||
|
# define gl_recursive_lock_unlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
|
||||||
|
# define gl_recursive_lock_destroy(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
|
||||||
|
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
/* Old versions of POSIX threads on Solaris did not have recursive locks.
|
||||||
|
We have to implement them ourselves. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_t owner;
|
||||||
|
unsigned long depth;
|
||||||
|
}
|
||||||
|
gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME;
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
{ PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
|
||||||
|
# define gl_recursive_lock_init(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
|
||||||
|
# define gl_recursive_lock_lock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
|
||||||
|
# define gl_recursive_lock_unlock(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
|
||||||
|
# define gl_recursive_lock_destroy(NAME) \
|
||||||
|
if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
|
||||||
|
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef pthread_once_t gl_once_t;
|
||||||
|
# define gl_once_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
|
||||||
|
# define gl_once(NAME, INITFUNCTION) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (pthread_in_use ()) \
|
||||||
|
{ \
|
||||||
|
if (pthread_once (&NAME, INITFUNCTION) != 0) \
|
||||||
|
abort (); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
if (glthread_once_singlethreaded (&NAME)) \
|
||||||
|
INITFUNCTION (); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
extern int glthread_once_singlethreaded (pthread_once_t *once_control);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_PTH_THREADS
|
||||||
|
|
||||||
|
/* Use the GNU Pth threads library. */
|
||||||
|
|
||||||
|
# include <pth.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
# if USE_PTH_THREADS_WEAK
|
||||||
|
|
||||||
|
/* Use weak references to the GNU Pth threads library. */
|
||||||
|
|
||||||
|
# pragma weak pth_mutex_init
|
||||||
|
# pragma weak pth_mutex_acquire
|
||||||
|
# pragma weak pth_mutex_release
|
||||||
|
# pragma weak pth_rwlock_init
|
||||||
|
# pragma weak pth_rwlock_acquire
|
||||||
|
# pragma weak pth_rwlock_release
|
||||||
|
# pragma weak pth_once
|
||||||
|
|
||||||
|
# pragma weak pth_cancel
|
||||||
|
# define pth_in_use() (pth_cancel != NULL)
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
# define pth_in_use() 1
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef pth_mutex_t gl_lock_t;
|
||||||
|
# define gl_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_mutex_t NAME;
|
||||||
|
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
|
||||||
|
# define gl_lock_initializer \
|
||||||
|
PTH_MUTEX_INIT
|
||||||
|
# define gl_lock_init(NAME) \
|
||||||
|
if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
|
||||||
|
# define gl_lock_lock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
|
||||||
|
# define gl_lock_unlock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
|
||||||
|
# define gl_lock_destroy(NAME) \
|
||||||
|
(void)(&NAME)
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
typedef pth_rwlock_t gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_rwlock_t NAME;
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
|
||||||
|
# define gl_rwlock_initializer \
|
||||||
|
PTH_RWLOCK_INIT
|
||||||
|
# define gl_rwlock_init(NAME) \
|
||||||
|
if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
|
||||||
|
# define gl_rwlock_rdlock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
|
||||||
|
# define gl_rwlock_wrlock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
|
||||||
|
# define gl_rwlock_unlock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
|
||||||
|
# define gl_rwlock_destroy(NAME) \
|
||||||
|
(void)(&NAME)
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
/* In Pth, mutexes are recursive by default. */
|
||||||
|
typedef pth_mutex_t gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_mutex_t NAME;
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
PTH_MUTEX_INIT
|
||||||
|
# define gl_recursive_lock_init(NAME) \
|
||||||
|
if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
|
||||||
|
# define gl_recursive_lock_lock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
|
||||||
|
# define gl_recursive_lock_unlock(NAME) \
|
||||||
|
if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
|
||||||
|
# define gl_recursive_lock_destroy(NAME) \
|
||||||
|
(void)(&NAME)
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef pth_once_t gl_once_t;
|
||||||
|
# define gl_once_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
|
||||||
|
# define gl_once(NAME, INITFUNCTION) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (pth_in_use ()) \
|
||||||
|
{ \
|
||||||
|
void (*gl_once_temp) (void) = INITFUNCTION; \
|
||||||
|
if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
|
||||||
|
abort (); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
if (glthread_once_singlethreaded (&NAME)) \
|
||||||
|
INITFUNCTION (); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
extern void glthread_once_call (void *arg);
|
||||||
|
extern int glthread_once_singlethreaded (pth_once_t *once_control);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_SOLARIS_THREADS
|
||||||
|
|
||||||
|
/* Use the old Solaris threads library. */
|
||||||
|
|
||||||
|
# include <thread.h>
|
||||||
|
# include <synch.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
|
||||||
|
# if USE_SOLARIS_THREADS_WEAK
|
||||||
|
|
||||||
|
/* Use weak references to the old Solaris threads library. */
|
||||||
|
|
||||||
|
# pragma weak mutex_init
|
||||||
|
# pragma weak mutex_lock
|
||||||
|
# pragma weak mutex_unlock
|
||||||
|
# pragma weak mutex_destroy
|
||||||
|
# pragma weak rwlock_init
|
||||||
|
# pragma weak rw_rdlock
|
||||||
|
# pragma weak rw_wrlock
|
||||||
|
# pragma weak rw_unlock
|
||||||
|
# pragma weak rwlock_destroy
|
||||||
|
# pragma weak thr_self
|
||||||
|
|
||||||
|
# pragma weak thr_suspend
|
||||||
|
# define thread_in_use() (thr_suspend != NULL)
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
# define thread_in_use() 1
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef mutex_t gl_lock_t;
|
||||||
|
# define gl_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS mutex_t NAME;
|
||||||
|
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS mutex_t NAME = gl_lock_initializer;
|
||||||
|
# define gl_lock_initializer \
|
||||||
|
DEFAULTMUTEX
|
||||||
|
# define gl_lock_init(NAME) \
|
||||||
|
if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
|
||||||
|
# define gl_lock_lock(NAME) \
|
||||||
|
if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
|
||||||
|
# define gl_lock_unlock(NAME) \
|
||||||
|
if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_lock_destroy(NAME) \
|
||||||
|
if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
typedef rwlock_t gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS rwlock_t NAME;
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
|
||||||
|
# define gl_rwlock_initializer \
|
||||||
|
DEFAULTRWLOCK
|
||||||
|
# define gl_rwlock_init(NAME) \
|
||||||
|
if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
|
||||||
|
# define gl_rwlock_rdlock(NAME) \
|
||||||
|
if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_rwlock_wrlock(NAME) \
|
||||||
|
if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_rwlock_unlock(NAME) \
|
||||||
|
if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
|
||||||
|
# define gl_rwlock_destroy(NAME) \
|
||||||
|
if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
/* Old Solaris threads did not have recursive locks.
|
||||||
|
We have to implement them ourselves. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mutex_t mutex;
|
||||||
|
thread_t owner;
|
||||||
|
unsigned long depth;
|
||||||
|
}
|
||||||
|
gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME;
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
{ DEFAULTMUTEX, (thread_t) 0, 0 }
|
||||||
|
# define gl_recursive_lock_init(NAME) \
|
||||||
|
if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
|
||||||
|
# define gl_recursive_lock_lock(NAME) \
|
||||||
|
if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
|
||||||
|
# define gl_recursive_lock_unlock(NAME) \
|
||||||
|
if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
|
||||||
|
# define gl_recursive_lock_destroy(NAME) \
|
||||||
|
if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
|
||||||
|
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
volatile int inited;
|
||||||
|
mutex_t mutex;
|
||||||
|
}
|
||||||
|
gl_once_t;
|
||||||
|
# define gl_once_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
|
||||||
|
# define gl_once(NAME, INITFUNCTION) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (thread_in_use ()) \
|
||||||
|
{ \
|
||||||
|
glthread_once (&NAME, INITFUNCTION); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
if (glthread_once_singlethreaded (&NAME)) \
|
||||||
|
INITFUNCTION (); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
|
||||||
|
extern int glthread_once_singlethreaded (gl_once_t *once_control);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if USE_WIN32_THREADS
|
||||||
|
|
||||||
|
# include <windows.h>
|
||||||
|
|
||||||
|
/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
|
||||||
|
Semaphore types, because
|
||||||
|
- we need only to synchronize inside a single process (address space),
|
||||||
|
not inter-process locking,
|
||||||
|
- we don't need to support trylock operations. (TryEnterCriticalSection
|
||||||
|
does not work on Windows 95/98/ME. Packages that need trylock usually
|
||||||
|
define their own mutex type.) */
|
||||||
|
|
||||||
|
/* There is no way to statically initialize a CRITICAL_SECTION. It needs
|
||||||
|
to be done lazily, once only. For this we need spinlocks. */
|
||||||
|
|
||||||
|
typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gl_spinlock_t guard; /* protects the initialization */
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
}
|
||||||
|
gl_lock_t;
|
||||||
|
# define gl_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_lock_t NAME;
|
||||||
|
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
|
||||||
|
# define gl_lock_initializer \
|
||||||
|
{ { 0, -1 } }
|
||||||
|
# define gl_lock_init(NAME) \
|
||||||
|
glthread_lock_init (&NAME)
|
||||||
|
# define gl_lock_lock(NAME) \
|
||||||
|
glthread_lock_lock (&NAME)
|
||||||
|
# define gl_lock_unlock(NAME) \
|
||||||
|
glthread_lock_unlock (&NAME)
|
||||||
|
# define gl_lock_destroy(NAME) \
|
||||||
|
glthread_lock_destroy (&NAME)
|
||||||
|
extern void glthread_lock_init (gl_lock_t *lock);
|
||||||
|
extern void glthread_lock_lock (gl_lock_t *lock);
|
||||||
|
extern void glthread_lock_unlock (gl_lock_t *lock);
|
||||||
|
extern void glthread_lock_destroy (gl_lock_t *lock);
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
/* It is impossible to implement read-write locks using plain locks, without
|
||||||
|
introducing an extra thread dedicated to managing read-write locks.
|
||||||
|
Therefore here we need to use the low-level Event type. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HANDLE *array; /* array of waiting threads, each represented by an event */
|
||||||
|
unsigned int count; /* number of waiting threads */
|
||||||
|
unsigned int alloc; /* length of allocated array */
|
||||||
|
unsigned int offset; /* index of first waiting thread in array */
|
||||||
|
}
|
||||||
|
gl_waitqueue_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gl_spinlock_t guard; /* protects the initialization */
|
||||||
|
CRITICAL_SECTION lock; /* protects the remaining fields */
|
||||||
|
gl_waitqueue_t waiting_readers; /* waiting readers */
|
||||||
|
gl_waitqueue_t waiting_writers; /* waiting writers */
|
||||||
|
int runcount; /* number of readers running, or -1 when a writer runs */
|
||||||
|
}
|
||||||
|
gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_rwlock_t NAME;
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
|
||||||
|
# define gl_rwlock_initializer \
|
||||||
|
{ { 0, -1 } }
|
||||||
|
# define gl_rwlock_init(NAME) \
|
||||||
|
glthread_rwlock_init (&NAME)
|
||||||
|
# define gl_rwlock_rdlock(NAME) \
|
||||||
|
glthread_rwlock_rdlock (&NAME)
|
||||||
|
# define gl_rwlock_wrlock(NAME) \
|
||||||
|
glthread_rwlock_wrlock (&NAME)
|
||||||
|
# define gl_rwlock_unlock(NAME) \
|
||||||
|
glthread_rwlock_unlock (&NAME)
|
||||||
|
# define gl_rwlock_destroy(NAME) \
|
||||||
|
glthread_rwlock_destroy (&NAME)
|
||||||
|
extern void glthread_rwlock_init (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
|
||||||
|
extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
/* The Win32 documentation says that CRITICAL_SECTION already implements a
|
||||||
|
recursive lock. But we need not rely on it: It's easy to implement a
|
||||||
|
recursive lock without this assumption. */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gl_spinlock_t guard; /* protects the initialization */
|
||||||
|
DWORD owner;
|
||||||
|
unsigned long depth;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
}
|
||||||
|
gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME;
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
|
||||||
|
# define gl_recursive_lock_initializer \
|
||||||
|
{ { 0, -1 }, 0, 0 }
|
||||||
|
# define gl_recursive_lock_init(NAME) \
|
||||||
|
glthread_recursive_lock_init (&NAME)
|
||||||
|
# define gl_recursive_lock_lock(NAME) \
|
||||||
|
glthread_recursive_lock_lock (&NAME)
|
||||||
|
# define gl_recursive_lock_unlock(NAME) \
|
||||||
|
glthread_recursive_lock_unlock (&NAME)
|
||||||
|
# define gl_recursive_lock_destroy(NAME) \
|
||||||
|
glthread_recursive_lock_destroy (&NAME)
|
||||||
|
extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
|
||||||
|
extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
volatile int inited;
|
||||||
|
volatile long started;
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
}
|
||||||
|
gl_once_t;
|
||||||
|
# define gl_once_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_once_t NAME = { -1, -1 };
|
||||||
|
# define gl_once(NAME, INITFUNCTION) \
|
||||||
|
glthread_once (&NAME, INITFUNCTION)
|
||||||
|
extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
|
||||||
|
|
||||||
|
/* Provide dummy implementation if threads are not supported. */
|
||||||
|
|
||||||
|
/* -------------------------- gl_lock_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef int gl_lock_t;
|
||||||
|
# define gl_lock_define(STORAGECLASS, NAME)
|
||||||
|
# define gl_lock_define_initialized(STORAGECLASS, NAME)
|
||||||
|
# define gl_lock_init(NAME)
|
||||||
|
# define gl_lock_lock(NAME)
|
||||||
|
# define gl_lock_unlock(NAME)
|
||||||
|
|
||||||
|
/* ------------------------- gl_rwlock_t datatype ------------------------- */
|
||||||
|
|
||||||
|
typedef int gl_rwlock_t;
|
||||||
|
# define gl_rwlock_define(STORAGECLASS, NAME)
|
||||||
|
# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
|
||||||
|
# define gl_rwlock_init(NAME)
|
||||||
|
# define gl_rwlock_rdlock(NAME)
|
||||||
|
# define gl_rwlock_wrlock(NAME)
|
||||||
|
# define gl_rwlock_unlock(NAME)
|
||||||
|
|
||||||
|
/* --------------------- gl_recursive_lock_t datatype --------------------- */
|
||||||
|
|
||||||
|
typedef int gl_recursive_lock_t;
|
||||||
|
# define gl_recursive_lock_define(STORAGECLASS, NAME)
|
||||||
|
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
|
||||||
|
# define gl_recursive_lock_init(NAME)
|
||||||
|
# define gl_recursive_lock_lock(NAME)
|
||||||
|
# define gl_recursive_lock_unlock(NAME)
|
||||||
|
|
||||||
|
/* -------------------------- gl_once_t datatype -------------------------- */
|
||||||
|
|
||||||
|
typedef int gl_once_t;
|
||||||
|
# define gl_once_define(STORAGECLASS, NAME) \
|
||||||
|
STORAGECLASS gl_once_t NAME = 0;
|
||||||
|
# define gl_once(NAME, INITFUNCTION) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (NAME == 0) \
|
||||||
|
{ \
|
||||||
|
NAME = ~ 0; \
|
||||||
|
INITFUNCTION (); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
#endif /* _LOCK_H */
|
26
intl/version.c
Normal file
26
intl/version.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* libintl library version.
|
||||||
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License as published
|
||||||
|
by the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "libgnuintl.h"
|
||||||
|
|
||||||
|
/* Version number: (major<<16) + (minor<<8) + subminor */
|
||||||
|
int libintl_version = LIBINTL_VERSION;
|
30
m4/glibc2.m4
Normal file
30
m4/glibc2.m4
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# glibc2.m4 serial 1
|
||||||
|
dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# Test for the GNU C Library, version 2.0 or newer.
|
||||||
|
# From Bruno Haible.
|
||||||
|
|
||||||
|
AC_DEFUN([gt_GLIBC2],
|
||||||
|
[
|
||||||
|
AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer,
|
||||||
|
ac_cv_gnu_library_2,
|
||||||
|
[AC_EGREP_CPP([Lucky GNU user],
|
||||||
|
[
|
||||||
|
#include <features.h>
|
||||||
|
#ifdef __GNU_LIBRARY__
|
||||||
|
#if (__GLIBC__ >= 2)
|
||||||
|
Lucky GNU user
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
],
|
||||||
|
ac_cv_gnu_library_2=yes,
|
||||||
|
ac_cv_gnu_library_2=no)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
AC_SUBST(GLIBC2)
|
||||||
|
GLIBC2="$ac_cv_gnu_library_2"
|
||||||
|
]
|
||||||
|
)
|
69
m4/libusb.m4
Normal file
69
m4/libusb.m4
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
dnl Check for libusb
|
||||||
|
dnl Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||||
|
dnl
|
||||||
|
dnl This file is free software, distributed under the terms of the GNU
|
||||||
|
dnl General Public License. As a special exception to the GNU General
|
||||||
|
dnl Public License, this file may be distributed as part of a program
|
||||||
|
dnl that contains a configuration script generated by Autoconf, under
|
||||||
|
dnl the same distribution terms as the rest of that program.
|
||||||
|
dnl
|
||||||
|
dnl Defines HAVE_LIBUSB to 1 if a working libusb setup is found, and sets
|
||||||
|
dnl @LIBUSB@ to the necessary libraries. HAVE_USB_GET_BUSSES is set if
|
||||||
|
dnl usb_get_busses() exists.
|
||||||
|
|
||||||
|
AC_DEFUN([GNUPG_CHECK_LIBUSB],
|
||||||
|
[
|
||||||
|
AC_ARG_WITH(libusb,
|
||||||
|
AC_HELP_STRING([--with-libusb=DIR],
|
||||||
|
[look for the libusb library in DIR]),
|
||||||
|
[_do_libusb=$withval],[_do_libusb=yes])
|
||||||
|
|
||||||
|
if test "$_do_libusb" != "no" ; then
|
||||||
|
if test -d "$withval" ; then
|
||||||
|
CPPFLAGS="${CPPFLAGS} -I$withval/include"
|
||||||
|
LDFLAGS="${LDFLAGS} -L$withval/lib"
|
||||||
|
AC_PATH_PROG([_usb_config],["$_do_libusb/bin/libusb-config"])
|
||||||
|
else
|
||||||
|
AC_PATH_PROG([_usb_config],[libusb-config])
|
||||||
|
fi
|
||||||
|
|
||||||
|
_libusb_save_libs=$LIBS
|
||||||
|
_libusb_save_cflags=$CFLAGS
|
||||||
|
|
||||||
|
if test x$_usb_config != "x" ; then
|
||||||
|
_libusb_try_libs=`$LIBS $_usb_config --libs`
|
||||||
|
_libusb_try_cflags=`$LIBS $_usb_config --cflags`
|
||||||
|
else
|
||||||
|
_libusb_try_libs="-lusb"
|
||||||
|
_libusb_try_cflags=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
LIBS="$LIBS $_libusb_try_libs"
|
||||||
|
CFLAGS="$CFLAGS $_libusb_try_cflags"
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether libusb is present and sane])
|
||||||
|
|
||||||
|
AC_LINK_IFELSE(AC_LANG_PROGRAM([#include <usb.h>],[
|
||||||
|
usb_bulk_write(NULL,0,NULL,0,0);
|
||||||
|
]),_found_libusb=yes,_found_libusb=no)
|
||||||
|
|
||||||
|
AC_MSG_RESULT([$_found_libusb])
|
||||||
|
|
||||||
|
if test $_found_libusb = yes ; then
|
||||||
|
AC_DEFINE(HAVE_LIBUSB,1,
|
||||||
|
[Define to 1 if you have a fully functional libusb library.])
|
||||||
|
AC_SUBST(LIBUSB_CPPFLAGS,$_libusb_try_cflags)
|
||||||
|
AC_SUBST(LIBUSB,$_libusb_try_libs)
|
||||||
|
AC_CHECK_FUNCS(usb_get_busses)
|
||||||
|
fi
|
||||||
|
|
||||||
|
LIBS=$_libusb_save_libs
|
||||||
|
CFLAGS=$_libusb_save_cflags
|
||||||
|
|
||||||
|
unset _libusb_save_libs
|
||||||
|
unset _libusb_save_cflags
|
||||||
|
unset _libusb_try_libs
|
||||||
|
unset _libusb_try_cflags
|
||||||
|
unset _found_libusb
|
||||||
|
fi
|
||||||
|
])dnl
|
289
m4/lock.m4
Normal file
289
m4/lock.m4
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
# lock.m4 serial 2 (gettext-0.15)
|
||||||
|
dnl Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Bruno Haible.
|
||||||
|
|
||||||
|
dnl Tests for a multithreading library to be used.
|
||||||
|
dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS,
|
||||||
|
dnl USE_PTH_THREADS, USE_WIN32_THREADS
|
||||||
|
dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use
|
||||||
|
dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with
|
||||||
|
dnl libtool).
|
||||||
|
dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for
|
||||||
|
dnl programs that really need multithread functionality. The difference
|
||||||
|
dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak
|
||||||
|
dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread".
|
||||||
|
dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for
|
||||||
|
dnl multithread-safe programs.
|
||||||
|
|
||||||
|
AC_DEFUN([gl_LOCK],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([gl_LOCK_BODY])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl The guts of gl_LOCK. Needs to be expanded only once.
|
||||||
|
|
||||||
|
AC_DEFUN([gl_LOCK_BODY],
|
||||||
|
[
|
||||||
|
dnl Ordering constraints: This macro modifies CPPFLAGS in a way that
|
||||||
|
dnl influences the result of the autoconf tests that test for *_unlocked
|
||||||
|
dnl declarations, on AIX 5 at least. Therefore it must come early.
|
||||||
|
AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl
|
||||||
|
AC_BEFORE([$0], [gl_ARGP])dnl
|
||||||
|
|
||||||
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
AC_REQUIRE([AC_GNU_SOURCE]) dnl needed for pthread_rwlock_t on glibc systems
|
||||||
|
dnl Check for multithreading.
|
||||||
|
AC_ARG_ENABLE(threads,
|
||||||
|
AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API])
|
||||||
|
AC_HELP_STRING([--disable-threads], [build without multithread safety]),
|
||||||
|
gl_use_threads=$enableval, gl_use_threads=yes)
|
||||||
|
gl_threads_api=none
|
||||||
|
LIBTHREAD=
|
||||||
|
LTLIBTHREAD=
|
||||||
|
LIBMULTITHREAD=
|
||||||
|
LTLIBMULTITHREAD=
|
||||||
|
if test "$gl_use_threads" != no; then
|
||||||
|
dnl Check whether the compiler and linker support weak declarations.
|
||||||
|
AC_MSG_CHECKING([whether imported symbols can be declared weak])
|
||||||
|
gl_have_weak=no
|
||||||
|
AC_TRY_LINK([extern void xyzzy ();
|
||||||
|
#pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes])
|
||||||
|
AC_MSG_RESULT([$gl_have_weak])
|
||||||
|
if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
|
||||||
|
# On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that
|
||||||
|
# it groks <pthread.h>.
|
||||||
|
gl_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_REENTRANT"
|
||||||
|
AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no)
|
||||||
|
CPPFLAGS="$gl_save_CPPFLAGS"
|
||||||
|
if test "$gl_have_pthread_h" = yes; then
|
||||||
|
# Other possible tests:
|
||||||
|
# -lpthreads (FSU threads, PCthreads)
|
||||||
|
# -lgthreads
|
||||||
|
case "$host_os" in
|
||||||
|
osf*)
|
||||||
|
# On OSF/1, the compiler needs the flag -D_REENTRANT so that it
|
||||||
|
# groks <pthread.h>. cc also understands the flag -pthread, but
|
||||||
|
# we don't use it because 1. gcc-2.95 doesn't understand -pthread,
|
||||||
|
# 2. putting a flag into CPPFLAGS that has an effect on the linker
|
||||||
|
# causes the AC_TRY_LINK test below to succeed unexpectedly,
|
||||||
|
# leading to wrong values of LIBTHREAD and LTLIBTHREAD.
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_REENTRANT"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
gl_have_pthread=
|
||||||
|
# Test whether both pthread_mutex_lock and pthread_mutexattr_init exist
|
||||||
|
# in libc. IRIX 6.5 has the first one in both libc and libpthread, but
|
||||||
|
# the second one only in libpthread, and lock.c needs it.
|
||||||
|
AC_TRY_LINK([#include <pthread.h>],
|
||||||
|
[pthread_mutex_lock((pthread_mutex_t*)0);
|
||||||
|
pthread_mutexattr_init((pthread_mutexattr_t*)0);],
|
||||||
|
[gl_have_pthread=yes])
|
||||||
|
# Test for libpthread by looking for pthread_kill. (Not pthread_self,
|
||||||
|
# since it is defined as a macro on OSF/1.)
|
||||||
|
if test -n "$gl_have_pthread"; then
|
||||||
|
# The program links fine without libpthread. But it may actually
|
||||||
|
# need to link with libpthread in order to create multiple threads.
|
||||||
|
AC_CHECK_LIB(pthread, pthread_kill,
|
||||||
|
[LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread
|
||||||
|
# On Solaris and HP-UX, most pthread functions exist also in libc.
|
||||||
|
# Therefore pthread_in_use() needs to actually try to create a
|
||||||
|
# thread: pthread_create from libc will fail, whereas
|
||||||
|
# pthread_create will actually create a thread.
|
||||||
|
case "$host_os" in
|
||||||
|
solaris* | hpux*)
|
||||||
|
AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1,
|
||||||
|
[Define if the pthread_in_use() detection is hard.])
|
||||||
|
esac
|
||||||
|
])
|
||||||
|
else
|
||||||
|
# Some library is needed. Try libpthread and libc_r.
|
||||||
|
AC_CHECK_LIB(pthread, pthread_kill,
|
||||||
|
[gl_have_pthread=yes
|
||||||
|
LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread
|
||||||
|
LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread])
|
||||||
|
if test -z "$gl_have_pthread"; then
|
||||||
|
# For FreeBSD 4.
|
||||||
|
AC_CHECK_LIB(c_r, pthread_kill,
|
||||||
|
[gl_have_pthread=yes
|
||||||
|
LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r
|
||||||
|
LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -n "$gl_have_pthread"; then
|
||||||
|
gl_threads_api=posix
|
||||||
|
AC_DEFINE([USE_POSIX_THREADS], 1,
|
||||||
|
[Define if the POSIX multithreading library can be used.])
|
||||||
|
if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
|
||||||
|
if test $gl_have_weak = yes; then
|
||||||
|
AC_DEFINE([USE_POSIX_THREADS_WEAK], 1,
|
||||||
|
[Define if references to the POSIX multithreading library should be made weak.])
|
||||||
|
LIBTHREAD=
|
||||||
|
LTLIBTHREAD=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the
|
||||||
|
# pthread_rwlock_* functions.
|
||||||
|
AC_CHECK_TYPE([pthread_rwlock_t],
|
||||||
|
[AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1,
|
||||||
|
[Define if the POSIX multithreading library has read/write locks.])],
|
||||||
|
[],
|
||||||
|
[#include <pthread.h>])
|
||||||
|
# glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro.
|
||||||
|
AC_TRY_COMPILE([#include <pthread.h>],
|
||||||
|
[#if __FreeBSD__ == 4
|
||||||
|
error "No, in FreeBSD 4.0 recursive mutexes actually don't work."
|
||||||
|
#else
|
||||||
|
int x = (int)PTHREAD_MUTEX_RECURSIVE;
|
||||||
|
#endif],
|
||||||
|
[AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1,
|
||||||
|
[Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE.])])
|
||||||
|
# Some systems optimize for single-threaded programs by default, and
|
||||||
|
# need special flags to disable these optimizations. For example, the
|
||||||
|
# definition of 'errno' in <errno.h>.
|
||||||
|
case "$host_os" in
|
||||||
|
aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
|
||||||
|
solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$gl_have_pthread"; then
|
||||||
|
if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then
|
||||||
|
gl_have_solaristhread=
|
||||||
|
gl_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lthread"
|
||||||
|
AC_TRY_LINK([#include <thread.h>
|
||||||
|
#include <synch.h>],
|
||||||
|
[thr_self();],
|
||||||
|
[gl_have_solaristhread=yes])
|
||||||
|
LIBS="$gl_save_LIBS"
|
||||||
|
if test -n "$gl_have_solaristhread"; then
|
||||||
|
gl_threads_api=solaris
|
||||||
|
LIBTHREAD=-lthread
|
||||||
|
LTLIBTHREAD=-lthread
|
||||||
|
LIBMULTITHREAD="$LIBTHREAD"
|
||||||
|
LTLIBMULTITHREAD="$LTLIBTHREAD"
|
||||||
|
AC_DEFINE([USE_SOLARIS_THREADS], 1,
|
||||||
|
[Define if the old Solaris multithreading library can be used.])
|
||||||
|
if test $gl_have_weak = yes; then
|
||||||
|
AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1,
|
||||||
|
[Define if references to the old Solaris multithreading library should be made weak.])
|
||||||
|
LIBTHREAD=
|
||||||
|
LTLIBTHREAD=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "$gl_use_threads" = pth; then
|
||||||
|
gl_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
AC_LIB_LINKFLAGS(pth)
|
||||||
|
gl_have_pth=
|
||||||
|
gl_save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS -lpth"
|
||||||
|
AC_TRY_LINK([#include <pth.h>], [pth_self();], gl_have_pth=yes)
|
||||||
|
LIBS="$gl_save_LIBS"
|
||||||
|
if test -n "$gl_have_pth"; then
|
||||||
|
gl_threads_api=pth
|
||||||
|
LIBTHREAD="$LIBPTH"
|
||||||
|
LTLIBTHREAD="$LTLIBPTH"
|
||||||
|
LIBMULTITHREAD="$LIBTHREAD"
|
||||||
|
LTLIBMULTITHREAD="$LTLIBTHREAD"
|
||||||
|
AC_DEFINE([USE_PTH_THREADS], 1,
|
||||||
|
[Define if the GNU Pth multithreading library can be used.])
|
||||||
|
if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
|
||||||
|
if test $gl_have_weak = yes; then
|
||||||
|
AC_DEFINE([USE_PTH_THREADS_WEAK], 1,
|
||||||
|
[Define if references to the GNU Pth multithreading library should be made weak.])
|
||||||
|
LIBTHREAD=
|
||||||
|
LTLIBTHREAD=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
CPPFLAGS="$gl_save_CPPFLAGS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test -z "$gl_have_pthread"; then
|
||||||
|
if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then
|
||||||
|
if { case "$host_os" in
|
||||||
|
mingw*) true;;
|
||||||
|
*) false;;
|
||||||
|
esac
|
||||||
|
}; then
|
||||||
|
gl_threads_api=win32
|
||||||
|
AC_DEFINE([USE_WIN32_THREADS], 1,
|
||||||
|
[Define if the Win32 multithreading API can be used.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AC_MSG_CHECKING([for multithread API to use])
|
||||||
|
AC_MSG_RESULT([$gl_threads_api])
|
||||||
|
AC_SUBST(LIBTHREAD)
|
||||||
|
AC_SUBST(LTLIBTHREAD)
|
||||||
|
AC_SUBST(LIBMULTITHREAD)
|
||||||
|
AC_SUBST(LTLIBMULTITHREAD)
|
||||||
|
gl_PREREQ_LOCK
|
||||||
|
])
|
||||||
|
|
||||||
|
# Prerequisites of lib/lock.c.
|
||||||
|
AC_DEFUN([gl_PREREQ_LOCK], [
|
||||||
|
AC_REQUIRE([AC_C_INLINE])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Survey of platforms:
|
||||||
|
dnl
|
||||||
|
dnl Platform Available Compiler Supports test-lock
|
||||||
|
dnl flavours option weak result
|
||||||
|
dnl --------------- --------- --------- -------- ---------
|
||||||
|
dnl Linux 2.4/glibc posix -lpthread Y OK
|
||||||
|
dnl
|
||||||
|
dnl GNU Hurd/glibc posix
|
||||||
|
dnl
|
||||||
|
dnl FreeBSD 5.3 posix -lc_r Y
|
||||||
|
dnl posix -lkse ? Y
|
||||||
|
dnl posix -lpthread ? Y
|
||||||
|
dnl posix -lthr Y
|
||||||
|
dnl
|
||||||
|
dnl FreeBSD 5.2 posix -lc_r Y
|
||||||
|
dnl posix -lkse Y
|
||||||
|
dnl posix -lthr Y
|
||||||
|
dnl
|
||||||
|
dnl FreeBSD 4.0,4.10 posix -lc_r Y OK
|
||||||
|
dnl
|
||||||
|
dnl NetBSD 1.6 --
|
||||||
|
dnl
|
||||||
|
dnl OpenBSD 3.4 posix -lpthread Y OK
|
||||||
|
dnl
|
||||||
|
dnl MacOS X 10.[123] posix -lpthread Y OK
|
||||||
|
dnl
|
||||||
|
dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK
|
||||||
|
dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK
|
||||||
|
dnl
|
||||||
|
dnl HP-UX 11 posix -lpthread N (cc) OK
|
||||||
|
dnl Y (gcc)
|
||||||
|
dnl
|
||||||
|
dnl IRIX 6.5 posix -lpthread Y 0.5
|
||||||
|
dnl
|
||||||
|
dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK
|
||||||
|
dnl
|
||||||
|
dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK
|
||||||
|
dnl -lpthread (gcc) Y
|
||||||
|
dnl
|
||||||
|
dnl Cygwin posix -lpthread Y OK
|
||||||
|
dnl
|
||||||
|
dnl Any of the above pth -lpth 0.0
|
||||||
|
dnl
|
||||||
|
dnl Mingw win32 N OK
|
||||||
|
dnl
|
||||||
|
dnl BeOS 5 --
|
||||||
|
dnl
|
||||||
|
dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is
|
||||||
|
dnl turned off:
|
||||||
|
dnl OK if all three tests terminate OK,
|
||||||
|
dnl 0.5 if the first test terminates OK but the second one loops endlessly,
|
||||||
|
dnl 0.0 if the first test already loops endlessly.
|
52
m4/visibility.m4
Normal file
52
m4/visibility.m4
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# visibility.m4 serial 1 (gettext-0.15)
|
||||||
|
dnl Copyright (C) 2005 Free Software Foundation, Inc.
|
||||||
|
dnl This file is free software; the Free Software Foundation
|
||||||
|
dnl gives unlimited permission to copy and/or distribute it,
|
||||||
|
dnl with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
dnl From Bruno Haible.
|
||||||
|
|
||||||
|
dnl Tests whether the compiler supports the command-line option
|
||||||
|
dnl -fvisibility=hidden and the function and variable attributes
|
||||||
|
dnl __attribute__((__visibility__("hidden"))) and
|
||||||
|
dnl __attribute__((__visibility__("default"))).
|
||||||
|
dnl Does *not* test for __visibility__("protected") - which has tricky
|
||||||
|
dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
|
||||||
|
dnl MacOS X.
|
||||||
|
dnl Does *not* test for __visibility__("internal") - which has processor
|
||||||
|
dnl dependent semantics.
|
||||||
|
dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
|
||||||
|
dnl "really only recommended for legacy code".
|
||||||
|
dnl Set the variable CFLAG_VISIBILITY.
|
||||||
|
dnl Defines and sets the variable HAVE_VISIBILITY.
|
||||||
|
|
||||||
|
AC_DEFUN([gl_VISIBILITY],
|
||||||
|
[
|
||||||
|
AC_REQUIRE([AC_PROG_CC])
|
||||||
|
CFLAG_VISIBILITY=
|
||||||
|
HAVE_VISIBILITY=0
|
||||||
|
if test -n "$GCC"; then
|
||||||
|
AC_MSG_CHECKING([for simple visibility declarations])
|
||||||
|
AC_CACHE_VAL(gl_cv_cc_visibility, [
|
||||||
|
gl_save_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS -fvisibility=hidden"
|
||||||
|
AC_TRY_COMPILE(
|
||||||
|
[extern __attribute__((__visibility__("hidden"))) int hiddenvar;
|
||||||
|
extern __attribute__((__visibility__("default"))) int exportedvar;
|
||||||
|
extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
|
||||||
|
extern __attribute__((__visibility__("default"))) int exportedfunc (void);],
|
||||||
|
[],
|
||||||
|
gl_cv_cc_visibility=yes,
|
||||||
|
gl_cv_cc_visibility=no)
|
||||||
|
CFLAGS="$gl_save_CFLAGS"])
|
||||||
|
AC_MSG_RESULT([$gl_cv_cc_visibility])
|
||||||
|
if test $gl_cv_cc_visibility = yes; then
|
||||||
|
CFLAG_VISIBILITY="-fvisibility=hidden"
|
||||||
|
HAVE_VISIBILITY=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AC_SUBST([CFLAG_VISIBILITY])
|
||||||
|
AC_SUBST([HAVE_VISIBILITY])
|
||||||
|
AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
|
||||||
|
[Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
|
||||||
|
])
|
Loading…
x
Reference in New Issue
Block a user