diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-03-18 11:17:57 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-03-18 11:17:57 +0000 |
commit | 86a9ee5e87cc084ccce131cd51166c98ea87f28f (patch) | |
tree | 66fc7276b0bd25d53b007efe496c330a6725adfc /nptl | |
parent | 4773086e0498c99ee11422fc39606e9a53f12502 (diff) | |
download | glibc-86a9ee5e87cc084ccce131cd51166c98ea87f28f.tar glibc-86a9ee5e87cc084ccce131cd51166c98ea87f28f.tar.gz glibc-86a9ee5e87cc084ccce131cd51166c98ea87f28f.tar.bz2 glibc-86a9ee5e87cc084ccce131cd51166c98ea87f28f.zip |
Update.
2003-03-18 Ulrich Drepper <drepper@redhat.com>
* pthread_condattr_getclock.c: New file.
* pthread_condattr_setclock.c: New file.
* sysdeps/pthread/pthread.h: Declare these new functions.
* Versions [GLIBC_2.3.3] (libpthread): Add the new functions.
* Makefile (libpthread-routines): Add the new functions.
* sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_condattr):
Renamed field to value. Document use of the bits.
* pthread_condattr_getpshared.c: Adjust for struct pthread_condattr
change.
* pthread_condattr_setpshared.c: Likewise.
* sysdeps/unix/sysv/linux/lowlevelcond.sym: Add cond_clock symbol.
* sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t):
Add __clock field.
* sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise.
* sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise.
* sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise.
* sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S:
Implement clock selection.
* sysdeps/pthread/pthread_cond_timedwait.c: Likewise.
* pthread-errnos.sym: Add ENOSYS.
* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define
_POSIX_CLOCK_SELECTION.
* sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Remove
invalid .size directive.
Diffstat (limited to 'nptl')
21 files changed, 245 insertions, 12 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 14e1e1c21e..579e985298 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,33 @@ +2003-03-18 Ulrich Drepper <drepper@redhat.com> + + * pthread_condattr_getclock.c: New file. + * pthread_condattr_setclock.c: New file. + * sysdeps/pthread/pthread.h: Declare these new functions. + * Versions [GLIBC_2.3.3] (libpthread): Add the new functions. + * Makefile (libpthread-routines): Add the new functions. + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_condattr): + Renamed field to value. Document use of the bits. + * pthread_condattr_getpshared.c: Adjust for struct pthread_condattr + change. + * pthread_condattr_setpshared.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add cond_clock symbol. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __clock field. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Implement clock selection. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * pthread-errnos.sym: Add ENOSYS. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_CLOCK_SELECTION. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Remove + invalid .size directive. + 2003-03-17 Roland McGrath <roland@redhat.com> * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): diff --git a/nptl/Makefile b/nptl/Makefile index b59ffd86bb..5c8676f26c 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -76,6 +76,7 @@ libpthread-routines = init events version \ old_pthread_cond_signal old_pthread_cond_broadcast \ pthread_condattr_init pthread_condattr_destroy \ pthread_condattr_getpshared pthread_condattr_setpshared \ + pthread_condattr_getclock pthread_condattr_setclock \ pthread_spin_init pthread_spin_destroy \ pthread_spin_lock pthread_spin_trylock \ pthread_spin_unlock \ diff --git a/nptl/Versions b/nptl/Versions index c6346ef8b5..1d6e6b2582 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -206,6 +206,11 @@ libpthread { pthread_tryjoin_np; pthread_timedjoin_np; } + GLIBC_2.3.3 { + # Unix CS option. + pthread_condattr_getclock; pthread_condattr_setclock; + } + GLIBC_PRIVATE { __pthread_initialize_minimal; __pthread_cleanup_upto; __pthread_clock_gettime; __pthread_clock_settime; diff --git a/nptl/pthread-errnos.sym b/nptl/pthread-errnos.sym index a3289c6dcc..2bb4d0d3ca 100644 --- a/nptl/pthread-errnos.sym +++ b/nptl/pthread-errnos.sym @@ -7,5 +7,6 @@ EBUSY EBUSY EDEADLK EDEADLK EINTR EINTR EINVAL EINVAL +ENOSYS ENOSYS ETIMEDOUT ETIMEDOUT EWOULDBLOCK EWOULDBLOCK diff --git a/nptl/pthread_condattr_getclock.c b/nptl/pthread_condattr_getclock.c new file mode 100644 index 0000000000..f8be655bf9 --- /dev/null +++ b/nptl/pthread_condattr_getclock.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_condattr_getclock (attr, clock_id) + const pthread_condattr_t *attr; + clockid_t *clock_id; +{ + *clock_id = ((((const struct pthread_condattr *) attr)->value) & 0xfe) >> 1; + + return 0; +} diff --git a/nptl/pthread_condattr_getpshared.c b/nptl/pthread_condattr_getpshared.c index 7b91f14f46..b44eac94e7 100644 --- a/nptl/pthread_condattr_getpshared.c +++ b/nptl/pthread_condattr_getpshared.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -25,7 +25,7 @@ pthread_condattr_getpshared (attr, pshared) const pthread_condattr_t *attr; int *pshared; { - *pshared = ((const struct pthread_condattr *) attr)->pshared; + *pshared = ((const struct pthread_condattr *) attr)->value & 1; return 0; } diff --git a/nptl/pthread_condattr_setclock.c b/nptl/pthread_condattr_setclock.c new file mode 100644 index 0000000000..09488aff9b --- /dev/null +++ b/nptl/pthread_condattr_setclock.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdbool.h> +#include <time.h> +#include <sysdep.h> +#include "pthreadP.h" +#include <kernel-features.h> + + +int +pthread_condattr_setclock (attr, clock_id) + pthread_condattr_t *attr; + clockid_t clock_id; +{ + /* Only a few clocks are allowed. CLOCK_REALTIME is always allowed. + CLOCK_MONOTONIC only if the kernel has the necessary support. */ + if (clock_id == CLOCK_MONOTONIC) + { +#ifndef __ASSUME_POSIX_TIMERS +# ifdef __NR_clock_getres + /* Check whether the clock is available. */ + static int avail; + + if (avail == 0) + { + struct timespec ts; + + INTERNAL_SYSCALL_DECL (err); + int val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, + &ts); + avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; + } + + if (avail < 0) +# endif + /* Not available. */ + return EINVAL; +#endif + } + else if (clock_id != CLOCK_REALTIME) + return EINVAL; + + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = (*valuep & ~0xfe) | (clock_id << 1); + + return 0; +} diff --git a/nptl/pthread_condattr_setpshared.c b/nptl/pthread_condattr_setpshared.c index 518c1c791e..f47afccef0 100644 --- a/nptl/pthread_condattr_setpshared.c +++ b/nptl/pthread_condattr_setpshared.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -24,7 +24,9 @@ pthread_condattr_setpshared (attr, pshared) pthread_condattr_t *attr; int pshared; { - ((struct pthread_condattr *) attr)->pshared = pshared; + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = (*valuep & ~1) | (pshared != 0); return 0; } diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h index 135b255a53..36a996a664 100644 --- a/nptl/sysdeps/pthread/pthread.h +++ b/nptl/sysdeps/pthread/pthread.h @@ -602,6 +602,18 @@ extern int pthread_condattr_getpshared (__const pthread_condattr_t * extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, int __pshared) __THROW; +#ifdef __USE_XOPEN2K +/* Get the clock selected for the conditon variable attribute ATTR. */ +extern int pthread_condattr_getclock (__const pthread_condattr_t * + __restrict __attr, + __clockid_t *__restrict __clock_id) + __THROW; + +/* Set the clock selected for the conditon variable attribute ATTR. */ +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, + __clockid_t __clock_id) __THROW; + +#endif #ifdef __USE_XOPEN2K diff --git a/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/nptl/sysdeps/pthread/pthread_cond_timedwait.c index af9929c500..e0200b4cd8 100644 --- a/nptl/sysdeps/pthread/pthread_cond_timedwait.c +++ b/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -92,14 +92,37 @@ __pthread_cond_timedwait (cond, mutex, abstime) while (1) { + struct timespec rt; +#ifdef __NR_clock_gettime + INTERNAL_SYSCALL_DECL (err); + int val = INTERNAL_SYSCALL (clock_gettime, err, 2, cond->__data.__clock, + &ts); +# ifndef __ASSUME_POSIX_TIMERS + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (val, err), 0)) + { + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + } + else +# endif + { + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - rt.tv_sec; + rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; + } +#else /* Get the current time. So far we support only one clock. */ struct timeval tv; (void) gettimeofday (&tv, NULL); /* Convert the absolute timeout value to a relative timeout. */ - struct timespec rt; rt.tv_sec = abstime->tv_sec - tv.tv_sec; rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +#endif if (rt.tv_nsec < 0) { rt.tv_nsec += 1000000000; diff --git a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h index f40e3c633a..2e2a609625 100644 --- a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h +++ b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h @@ -132,4 +132,7 @@ /* The monotonic clock might be available. */ #define _POSIX_MONOTONIC_CLOCK 0 +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200112L + #endif /* posix_opt.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/posix_opt.h index ad50705d4f..556c5fd873 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/posix_opt.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/posix_opt.h @@ -138,4 +138,7 @@ /* The monotonic clock might be available. */ #define _POSIX_MONOTONIC_CLOCK 0 +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200112L + #endif /* posix_opt.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h index 756ece29e0..c14f1b1ef6 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -74,6 +74,7 @@ typedef union struct { int __lock; + int __clock; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S index c1ce3bec17..151018ce23 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -112,6 +112,29 @@ __pthread_cond_timedwait: /* Get the current time. */ movl %ebx, %edx +#ifdef __NR_clock_gettime + /* Get the clock number. Note that the field in the condvar + structure stores the number minus 1. */ + movl cond_clock(%ebx), %ebx + /* Only clocks 0 and 1 are allowed. Both are handled in the + kernel. */ + leal 12(%esp), %ecx + movl $__NR_clock_gettime, %eax + ENTER_KERNEL +# ifndef __ASSUME_POSIX_TIMERS + cmpl $-ENOSYS, %eax + je 19f +# endif + movl %edx, %ebx + + /* Compute relative timeout. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 12(%esp), %ecx + subl 16(%esp), %edx +#else + /* Get the current time. */ + movl %ebx, %edx leal 12(%esp), %ebx xorl %ecx, %ecx movl $SYS_gettimeofday, %eax @@ -126,6 +149,7 @@ __pthread_cond_timedwait: movl 4(%ebp), %edx subl 12(%esp), %ecx subl %eax, %edx +#endif jns 12f addl $1000000000, %edx subl $1, %ecx @@ -133,7 +157,7 @@ __pthread_cond_timedwait: js 13f /* Store relative timeout. */ - movl %ecx, 12(%esp) +21: movl %ecx, 12(%esp) movl %edx, 16(%esp) leal 12(%esp), %esi xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ @@ -275,7 +299,30 @@ __pthread_cond_timedwait: 17: popl %eax jmp 18b - .size __pthread_cond_wait, .-__pthread_cond_wait + +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS + /* clock_gettime not available. */ +19: leal 12(%esp), %ebx + xorl %ecx, %ecx + movl $SYS_gettimeofday, %eax + ENTER_KERNEL + movl %edx, %ebx + + /* Compute relative timeout. */ + movl 16(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 12(%esp), %ecx + subl %eax, %edx + jns 20f + addl $1000000000, %edx + subl $1, %ecx +20: testl %ecx, %ecx + js 13b + jmp 21b +#endif .size __pthread_cond_timedwait, .-__pthread_cond_timedwait versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, GLIBC_2_3_2) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h index ebe2818d4b..5b4127c76b 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h @@ -74,6 +74,7 @@ typedef union struct { int __lock; + int __clock; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h index 9ae35eff9a..17d78e4b9f 100644 --- a/nptl/sysdeps/unix/sysv/linux/internaltypes.h +++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -63,8 +63,13 @@ struct pthread_mutexattr /* Conditional variable attribute data structure. */ struct pthread_condattr { - /* Flag whether coditional variable will be shareable between processes. */ - int pshared; + /* Combination of values: + + Bit 0 : flag whether coditional variable will be shareable between + processes. + + Bit 1-7: clock ID. */ + int value; }; diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym index 17c1825483..5eb535e157 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym +++ b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym @@ -4,6 +4,7 @@ -- cond_lock offsetof (pthread_cond_t, __data.__lock) +cond_clock offsetof (pthread_cond_t, __data.__clock) total_seq offsetof (pthread_cond_t, __data.__total_seq) wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) woken_seq offsetof (pthread_cond_t, __data.__woken_seq) diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h index 332f50f1a1..728712a8c6 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -89,7 +89,7 @@ typedef union struct { int __lock; - int __pad; + int __clock; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h index 7c207beb53..aae8e90cdc 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h @@ -88,6 +88,7 @@ typedef union struct { int __lock; + int __clock; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; diff --git a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h index 97b94a3074..09890d3a19 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -75,6 +75,7 @@ typedef union struct { int __lock; + int __clock; unsigned long long int __total_seq; unsigned long long int __wakeup_seq; unsigned long long int __woken_seq; diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S index 9da9af8d01..97a642e65e 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -265,7 +265,6 @@ __pthread_cond_timedwait: 17: movq (%rsp), %rax jmp 18b - .size __pthread_cond_wait, .-__pthread_cond_wait .size __pthread_cond_timedwait, .-__pthread_cond_timedwait versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, GLIBC_2_3_2) |