From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-out.m-online.net (mail-out.m-online.net [212.18.0.9]) by sourceware.org (Postfix) with ESMTPS id 8EE303861875 for ; Wed, 26 Aug 2020 17:59:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8EE303861875 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: sourceware.org; spf=none smtp.mailfrom=lukma@denx.de Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 4BcDBr4Dm9z1qs39; Wed, 26 Aug 2020 19:59:16 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 4BcDBr2jd7z1qtwG; Wed, 26 Aug 2020 19:59:16 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id lxlglC3VST0F; Wed, 26 Aug 2020 19:59:13 +0200 (CEST) X-Auth-Info: 7WfPh77JGf8VQIlRz8TMut1D1w1LZioE2DU5rUSMAXw= Received: from jawa (85-222-111-42.dynamic.chello.pl [85.222.111.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPSA; Wed, 26 Aug 2020 19:59:13 +0200 (CEST) Date: Wed, 26 Aug 2020 19:59:06 +0200 From: Lukasz Majewski To: Adhemerval Zanella Cc: Joseph Myers , Paul Eggert , Alistair Francis , Arnd Bergmann , Alistair Francis , GNU C Library , Florian Weimer , Carlos O'Donell , Stepan Golosunov , Andreas Schwab , Zack Weinberg , Jeff Law Subject: Re: [PATCH] [RFC] y2038: nptl: Convert pthread_cond_{clock|timed}wait to support 64 bit time Message-ID: <20200826195906.50fb3854@jawa> In-Reply-To: <669c5162-af5f-a9f1-4ad1-5c721d044d54@linaro.org> References: <20200824164000.1619-1-lukma@denx.de> <669c5162-af5f-a9f1-4ad1-5c721d044d54@linaro.org> Organization: denx.de X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; boundary="Sig_/0_nvKNAfcbJl3RYpVAf6/iu"; protocol="application/pgp-signature" X-Spam-Status: No, score=-17.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Aug 2020 17:59:22 -0000 --Sig_/0_nvKNAfcbJl3RYpVAf6/iu Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Hi Adhemerval, > On 24/08/2020 13:40, Lukasz Majewski wrote: > > The pthread_cond_clockwait and pthread_cond_timedwait have been > > converted to support 64 bit time. > >=20 > > This change introduces new futex_abstimed_wait_cancelable64 > > function in ./sysdeps/nptl/futex-helpers.c, which uses futex_time64 > > where possible and tries to replace low-level preprocessor macros > > from lowlevellock-futex.h > > The pthread_cond_{clock|timed}wait only accepts absolute time. > > Moreover, there is no need to check for NULL passed as *abstime > > pointer as __pthread_cond_wait_common() always passes non-NULL > > struct __timespec64 pointer to futex_abstimed_wait_cancellable64(). > >=20 > > For systems with __TIMESIZE !=3D 64 && __WORDSIZE =3D=3D 32: > > - Conversions between 64 bit time to 32 bit are necessary > > - Redirection to __pthread_cond_{clock|timed}wait64 will provide > > support for 64 bit time > >=20 > > The futex_abstimed_wait_cancelable64 function has been put into a > > separate file on the purpose - to avoid issues apparent on m68k > > architecture related to small number of available registers (there > > is not enough registers to put all necessary arguments in them when > > inlining). In fact - the futex_helper.c is reused, but extra flag > > "-fno-inline" is set when it is build for this architecture. Such > > approach fixes the build issue. > >=20 > >=20 > > Build tests: > > ./src/scripts/build-many-glibcs.py glibcs > >=20 > > Run-time tests: > > - Run specific tests on ARM/x86 32bit systems (qemu): > > https://github.com/lmajewski/meta-y2038 and run tests: > > https://github.com/lmajewski/y2038-tests/commits/master > >=20 > > Above tests were performed with Y2038 redirection applied as well > > as without to test the proper usage of both > > __pthread_cond_{clock|timed}wait64 and > > __pthread_cond_{clock|timed}wait. =20 >=20 > Some comments below. As a general comment, I think you are using 8 > whitespace instead of tab. Yes, correct. I've already enabled the "gnu" coding style (c-set-style) in emacs. It automatically replaces some spaces with tabs. However, with some earlier patches - such approach was not accepted and using 2 spaces for indentation like: if (foo) { if (baz) flag =3D 1; } was recommended. Which indentation style is correct then? As the manual: https://www.gnu.org/prep/standards/standards.html did not say about it explicitly. Also here: https://sourceware.org/glibc/wiki/Style_and_Conventions it is not said explicitly. The only recommendation I had from Joseph on the very beginning of my involvement in the project: https://sourceware.org/pipermail/libc-alpha/2019-March/102274.html >=20 > > --- > > nptl/pthreadP.h | 11 +++ > > nptl/pthread_cond_wait.c | 46 ++++++++-- > > sysdeps/nptl/Makefile | 2 +- > > sysdeps/nptl/futex-helpers.c | 89 > > ++++++++++++++++++++ sysdeps/nptl/futex-internal.h | > > 11 +++ sysdeps/unix/sysv/linux/m68k/Makefile | 5 ++ > > sysdeps/unix/sysv/linux/m68k/futex-helpers.c | 19 +++++ > > 7 files changed, 173 insertions(+), 10 deletions(-) > > create mode 100644 sysdeps/nptl/futex-helpers.c > > create mode 100644 sysdeps/unix/sysv/linux/m68k/futex-helpers.c > >=20 > > diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h > > index 99713c8447..e288c7e778 100644 > > --- a/nptl/pthreadP.h > > +++ b/nptl/pthreadP.h > > @@ -462,6 +462,8 @@ extern int __pthread_cond_wait (pthread_cond_t > > *cond, pthread_mutex_t *mutex); #if __TIMESIZE =3D=3D 64 > > # define __pthread_clockjoin_np64 __pthread_clockjoin_np > > # define __pthread_timedjoin_np64 __pthread_timedjoin_np > > +# define __pthread_cond_timedwait64 __pthread_cond_timedwait > > +# define __pthread_cond_clockwait64 __pthread_cond_clockwait > > #else > > extern int __pthread_clockjoin_np64 (pthread_t threadid, void > > **thread_return, clockid_t clockid, =20 >=20 > Ok. >=20 > > @@ -470,6 +472,15 @@ libc_hidden_proto (__pthread_clockjoin_np64) > > extern int __pthread_timedjoin_np64 (pthread_t threadid, void > > **thread_return, const struct __timespec64 *abstime); > > libc_hidden_proto (__pthread_timedjoin_np64) > > +extern int __pthread_cond_timedwait64 (pthread_cond_t *cond, > > + pthread_mutex_t *mutex, > > + const struct __timespec64 > > *abstime); +libc_hidden_proto (__pthread_cond_timedwait64) > > +extern int __pthread_cond_clockwait64 (pthread_cond_t *cond, > > + pthread_mutex_t *mutex, > > + clockid_t clockid, > > + const struct __timespec64 > > *abstime); +libc_hidden_proto (__pthread_cond_clockwait64) > > #endif > > =20 > > extern int __pthread_cond_timedwait (pthread_cond_t *cond, =20 >=20 > They are symbol that will be implementated only for libpthread, so > this should be libpthread_hidden_proto instead. >=20 > > diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c > > index 85ddbc1011..560b30129b 100644 > > --- a/nptl/pthread_cond_wait.c > > +++ b/nptl/pthread_cond_wait.c > > @@ -31,6 +31,7 @@ > > #include > > #include > > =20 > > + =20 >=20 > Gratuitous new line. Ok. I will remove it >=20 > > #include "pthread_cond_common.c" > > =20 > > =20 > > @@ -378,8 +379,7 @@ __condvar_cleanup_waiting (void *arg) > > */ > > static __always_inline int > > __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > - clockid_t clockid, > > - const struct timespec *abstime) > > + clockid_t clockid, const struct __timespec64 *abstime) > > { > > const int maxspin =3D 0; > > int err; > > @@ -517,7 +517,7 @@ __pthread_cond_wait_common (pthread_cond_t > > *cond, pthread_mutex_t *mutex, err =3D ETIMEDOUT; > > else > > { > > - err =3D futex_abstimed_wait_cancelable > > + err =3D futex_abstimed_wait_cancelable64 > > (cond->__data.__g_signals + g, 0, clockid, > > abstime, private); > > } =20 >=20 > Ok. >=20 > > @@ -640,8 +640,8 @@ __pthread_cond_wait (pthread_cond_t *cond, > > pthread_mutex_t *mutex)=20 > > /* See __pthread_cond_wait_common. */ > > int > > -__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > - const struct timespec *abstime) > > +__pthread_cond_timedwait64 (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > + const struct __timespec64 *abstime) > > { > > /* Check parameter validity. This should also tell the compiler > > that it can assume that abstime is not NULL. */ =20 >=20 > Ok. >=20 > > @@ -655,6 +655,20 @@ __pthread_cond_timedwait (pthread_cond_t > > *cond, pthread_mutex_t *mutex, ? CLOCK_MONOTONIC : CLOCK_REALTIME; > > return __pthread_cond_wait_common (cond, mutex, clockid, > > abstime); } > > + > > +#if __TIMESIZE !=3D 64 > > +libc_hidden_def (__pthread_cond_timedwait64) =20 >=20 > It should be libpthread_hidden_def here. Ok >=20 > > + > > +int > > +__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > + const struct timespec *abstime) > > +{ > > + struct __timespec64 ts64 =3D valid_timespec_to_timespec64 > > (*abstime); + > > + return __pthread_cond_timedwait64 (cond, mutex, &ts64); > > +} > > +#endif > > + > > versioned_symbol (libpthread, __pthread_cond_wait, > > pthread_cond_wait, GLIBC_2_3_2); > > versioned_symbol (libpthread, __pthread_cond_timedwait, > > pthread_cond_timedwait, =20 >=20 > Ok, 'abstime' is marked as nonnull.=20 Yes, I've double checked it now :-) >=20 > > @@ -662,18 +676,32 @@ versioned_symbol (libpthread, > > __pthread_cond_timedwait, pthread_cond_timedwait,=20 > > /* See __pthread_cond_wait_common. */ > > int > > -__pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > - clockid_t clockid, > > - const struct timespec *abstime) > > +__pthread_cond_clockwait64 (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > + clockid_t clockid, > > + const struct __timespec64 *abstime) > > { > > /* Check parameter validity. This should also tell the compiler > > that it can assume that abstime is not NULL. */ > > if (! valid_nanoseconds (abstime->tv_nsec)) > > return EINVAL; > > =20 > > - if (!futex_abstimed_supported_clockid (clockid)) > > + if (! futex_abstimed_supported_clockid (clockid)) > > return EINVAL; =20 >=20 > Gratuitous change. Yes, this change is not related to this change. However, IIRC the if (! futex*...) for '!' (a space after it) is the correct coding style. >=20 > > =20 > > return __pthread_cond_wait_common (cond, mutex, clockid, > > abstime); } > > + > > +#if __TIMESIZE !=3D 64 > > +libc_hidden_def (__pthread_cond_clockwait64) > > + > > +int > > +__pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t > > *mutex, > > + clockid_t clockid, > > + const struct timespec *abstime) > > +{ > > + struct __timespec64 ts64 =3D valid_timespec_to_timespec64 > > (*abstime); + > > + return __pthread_cond_clockwait64 (cond, mutex, clockid, &ts64); > > +} > > +#endif > > weak_alias (__pthread_cond_clockwait, pthread_cond_clockwait); =20 >=20 > Ok, 'abstime' is marked as nonnull. Yes. >=20 > > diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile > > index 0631a870c8..6d649a94a2 100644 > > --- a/sysdeps/nptl/Makefile > > +++ b/sysdeps/nptl/Makefile > > @@ -17,7 +17,7 @@ > > # . > > =20 > > ifeq ($(subdir),nptl) > > -libpthread-sysdep_routines +=3D errno-loc > > +libpthread-sysdep_routines +=3D errno-loc futex-helpers > > endif > > =20 > > ifeq ($(subdir),rt) =20 >=20 > Ok. >=20 > > diff --git a/sysdeps/nptl/futex-helpers.c > > b/sysdeps/nptl/futex-helpers.c new file mode 100644 > > index 0000000000..dfd8870d35 > > --- /dev/null > > +++ b/sysdeps/nptl/futex-helpers.c =20 >=20 > I think it should be named sysdeps/nptl/futex-internal.c since it > implements the usual inline function from the header. Ok. >=20 > > @@ -0,0 +1,89 @@ > > +/* futex helper functions for glibc-internal use. > > + Copyright (C) 2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it > > and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later > > version. + > > + The GNU C Library is distributed in the hope that it will be > > useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > > See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + . */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +int > > +futex_abstimed_wait_cancelable64 (unsigned int* futex_word, > > + unsigned int expected, clockid_t > > clockid, > > + const struct __timespec64* > > abstime, > > + int private) =20 >=20 > As it was raised before, rename to __futex_abstimed_wait_cancelable64. >=20 I've already done it. This works and linknamespace tests pass. > > +{ > > + unsigned int clockbit; > > + int oldtype, err, op; > > + > > + /* Work around the fact that the kernel rejects negative timeout > > values > > + despite them being valid. */ > > + if (__glibc_unlikely ((abstime !=3D NULL) && (abstime->tv_sec < > > 0))) > > + return ETIMEDOUT; > > + > > + if (! lll_futex_supported_clockid (clockid)) > > + return EINVAL; > > + > > + oldtype =3D __pthread_enable_asynccancel (); > > + clockbit =3D (clockid =3D=3D CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : > > 0; > > + op =3D __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); > > + > > + err =3D INTERNAL_SYSCALL_CALL (futex_time64, futex_word, op, > > expected, > > + abstime, NULL /* Unused. */, > > + FUTEX_BITSET_MATCH_ANY); =20 >=20 > I think it would be better to just use INTERNAL_SYSCALL_CANCEL, since > in the long term to fiz the cancellation race (BZ#12683) it would > require to get rid of __*_{enable,disable}_asynccancel. It would > incur in more code size, but I think it is feasible. >=20 Ok. > > +#ifndef __ASSUME_TIME64_SYSCALLS > > + if (err =3D=3D -ENOSYS) > > + { > > + struct timespec ts32; =20 >=20 >=20 > Identation seems of here. Ok. Fixed. >=20 > > + if (in_time_t_range (abstime->tv_sec)) > > + { > > + ts32 =3D valid_timespec64_to_timespec (*abstime); > > + > > + err =3D INTERNAL_SYSCALL_CALL (futex, futex_word, op, > > expected, > > + &ts32, NULL /* Unused. */, > > + FUTEX_BITSET_MATCH_ANY); > > + } > > + else > > + err =3D -EOVERFLOW; > > + } > > +#endif > > + __pthread_disable_asynccancel (oldtype); > > + > > + switch (err) > > + { > > + case 0: > > + case -EAGAIN: > > + case -EINTR: > > + case -ETIMEDOUT: > > + case -EOVERFLOW: /* Passed absolute timeout uses 64 bit > > time_t type, but > > + underlying kernel does not support 64 bit > > time_t futex > > + syscalls. */ > > + return -err; > > + > > + case -EFAULT: /* Must have been caused by a glibc or > > application bug. */ > > + case -EINVAL: /* Either due to wrong alignment or due to the > > timeout not > > + being normalized. Must have been caused by a > > glibc or > > + application bug. */ > > + case -ENOSYS: /* Must have been caused by a glibc bug. */ > > + /* No other errors are documented at this time. */ > > + default: > > + futex_fatal_error (); > > + } > > +} > > + > > +libpthread_hidden_def (futex_abstimed_wait_cancelable64) =20 >=20 > There is no need to add a hidden def here, the function is internal > to libpthread so just mark as attribute_hidden. Ok. >=20 > > diff --git a/sysdeps/nptl/futex-internal.h > > b/sysdeps/nptl/futex-internal.h index 159aae82dc..aea01e5bcd 100644 > > --- a/sysdeps/nptl/futex-internal.h > > +++ b/sysdeps/nptl/futex-internal.h > > @@ -519,4 +519,15 @@ futex_timed_wait_cancel64 (pid_t *tidp, pid_t > > tid, futex_fatal_error (); > > } > > } > > + > > +/* The futex_abstimed_wait_cancelable64 has been moved to a > > separate file > > + to avoid problems with exhausting available registers on some > > architectures > > + - e.g. on m68k architecture. */ > > +int > > +futex_abstimed_wait_cancelable64 (unsigned int* futex_word, > > + unsigned int expected, clockid_t > > clockid, > > + const struct __timespec64* > > abstime, > > + int private); > > +libpthread_hidden_proto (futex_abstimed_wait_cancelable64) > > + > > #endif /* futex-internal.h */ =20 >=20 > Remove the libpthread_hidden_proto and move to attribute_hidden. >=20 Ok. > > diff --git a/sysdeps/unix/sysv/linux/m68k/Makefile > > b/sysdeps/unix/sysv/linux/m68k/Makefile index > > be40fae68a..f19c8c825d 100644 --- > > a/sysdeps/unix/sysv/linux/m68k/Makefile +++ > > b/sysdeps/unix/sysv/linux/m68k/Makefile @@ -21,3 +21,8 @@ > > sysdep-dl-routines +=3D dl-static sysdep-others +=3D lddlibc4 > > install-bin +=3D lddlibc4 > > endif > > + > > +ifeq ($(subdir),nptl) > > +libpthread-sysdep_routines +=3D futex-helpers =20 >=20 > There is no need to duplicate it here, you already do it on > sysdeps/nptl/Makefile. >=20 Ok. > > +CFLAGS-futex-helpers.c +=3D -fno-inline > > +endif =20 >=20 > This is trick one that I would to avoid. One change to the generic > code that did not triggered the compiler issue is to move the 32-bit > __NR_futex call to auxiliary function: >=20 > --- > #ifndef __ASSUME_TIME64_SYSCALLS > static int > __futex_abstimed_wait_cancellable32 (unsigned int* futex_word, > unsigned int expected, clockid_t > clockid, const struct __timespec64* abstime, > int private) > {=20 > if (! in_time_t_range (abstime->tv_sec)) > return -EOVERFLOW; > =20 > unsigned int clockbit =3D (clockid =3D=3D CLOCK_REALTIME) > ? FUTEX_CLOCK_REALTIME : 0; > int op =3D __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); > struct timespec ts32 =3D valid_timespec64_to_timespec (*abstime); > return INTERNAL_SYSCALL_CALL (futex, futex_word, op, expected, > &ts32, NULL /* Unused. */, > FUTEX_BITSET_MATCH_ANY); > } =20 > #endif >=20 > [...] >=20 > int=20 > __futex_abstimed_wait_cancelable64 (unsigned int* futex_word, > unsigned int expected, clockid_t > clockid, const struct __timespec64* abstime, > int private) > { > [...] > #ifndef __ASSUME_TIME64_SYSCALLS =20 > if (err =3D=3D -ENOSYS) > err =3D __futex_abstimed_wait_cancellable32 (futex_word, op, > clockid, abstime, private); > #endif > [...] > } > --- >=20 > It builds file on gcc version 8.3.1 for m68k-linux-gnu and > m68k-linux-gnu without requiring extra compiler options. I've also tested it on my side - seems to work correctly. >=20 > > diff --git a/sysdeps/unix/sysv/linux/m68k/futex-helpers.c > > b/sysdeps/unix/sysv/linux/m68k/futex-helpers.c new file mode 100644 > > index 0000000000..fb03b5d174 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/m68k/futex-helpers.c > > @@ -0,0 +1,19 @@ > > +/* futex helper functions for glibc-internal use for m68k > > architecture > > + Copyright (C) 2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it > > and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later > > version. + > > + The GNU C Library is distributed in the hope that it will be > > useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > > See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + . */ > > + > > +#include > > =20 >=20 > There file is not needed, sysdeps makefile rules will pick the nptl > generic one.=20 I will remove this file from this patch. Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de --Sig_/0_nvKNAfcbJl3RYpVAf6/iu Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQEzBAEBCgAdFiEEgAyFJ+N6uu6+XupJAR8vZIA0zr0FAl9GouoACgkQAR8vZIA0 zr3VDwf9FWjJ31mJFfcDahwJVgvsIlvottNsB6xsWBcgOAsuskMg9cQY36bQYzL0 7/j2xCw/Dvn+IKV9lXLz8XfFJhYyWEa2lda9BWFS+EDJKKH+snxaKVR9ak539mnH L+IiSaWJlbCukkifqTuUFEVkv9njgcopBJemNI1wctwdkPo+jMAb/xRu1ftJAQ0K SXKiw5W8qoF6VQgOseMVGlPEzvgGAzguoZh21wJQz3k4bTQ6eLg/aX/cJTuCHeXH 9f3Ev6eoznidUBshC9o1FCEAxOJq+MuCD/zJwhaGnRXTT97XTU2eopN6UCU4sEqO 4/HdX2MY8AVcdglUBSQjRJU8qvOkhg== =nIGY -----END PGP SIGNATURE----- --Sig_/0_nvKNAfcbJl3RYpVAf6/iu--