X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/3ef97fb6a70598253c4f7f293b516f449389ff7e..c3702194809d8772afa226d5107ec3abb05e8d35:/src/gmalloc.c diff --git a/src/gmalloc.c b/src/gmalloc.c index 08de77df0e..1cf9a8ee9b 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -5,21 +5,22 @@ /* The malloc headers and source files from the C library follow here. */ /* Declarations for `malloc' and friends. - Copyright 1990, 91, 92, 93, 95, 96, 99 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2002, 2003, 2004, + 2005, 2006, 2007 Free Software Foundation, Inc. Written May 1989 by Mike Haertel. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -36,6 +37,10 @@ Fifth Floor, Boston, MA 02110-1301, USA. #include #endif +#ifdef HAVE_GTK_AND_PTHREAD +#define USE_PTHREAD +#endif + #if ((defined __cplusplus || (defined (__STDC__) && __STDC__) \ || defined STDC_HEADERS || defined PROTOTYPES) \ && ! defined (BROKEN_PROTOTYPES)) @@ -72,6 +77,10 @@ Fifth Floor, Boston, MA 02110-1301, USA. #include #endif +#ifdef USE_PTHREAD +#include +#endif + #endif /* _MALLOC_INTERNAL. */ @@ -101,10 +110,6 @@ extern "C" #define NULL 0 #endif -#ifndef FREE_RETURN_TYPE -#define FREE_RETURN_TYPE void -#endif - /* Allocate SIZE bytes of memory. */ extern __ptr_t malloc PP ((__malloc_size_t __size)); @@ -114,12 +119,14 @@ extern __ptr_t realloc PP ((__ptr_t __ptr, __malloc_size_t __size)); /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ extern __ptr_t calloc PP ((__malloc_size_t __nmemb, __malloc_size_t __size)); /* Free a block allocated by `malloc', `realloc' or `calloc'. */ -extern FREE_RETURN_TYPE free PP ((__ptr_t __ptr)); +extern void free PP ((__ptr_t __ptr)); /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ #if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict. */ extern __ptr_t memalign PP ((__malloc_size_t __alignment, __malloc_size_t __size)); +extern int posix_memalign PP ((__ptr_t *, __malloc_size_t, + __malloc_size_t size)); #endif /* Allocate SIZE bytes on a page boundary. */ @@ -127,6 +134,10 @@ extern __ptr_t memalign PP ((__malloc_size_t __alignment, extern __ptr_t valloc PP ((__malloc_size_t __size)); #endif +#ifdef USE_PTHREAD +/* Set up mutexes and make malloc etc. thread-safe. */ +extern void malloc_enable_thread PP ((void)); +#endif #ifdef _MALLOC_INTERNAL @@ -227,6 +238,39 @@ extern __malloc_size_t _bytes_free; extern __ptr_t _malloc_internal PP ((__malloc_size_t __size)); extern __ptr_t _realloc_internal PP ((__ptr_t __ptr, __malloc_size_t __size)); extern void _free_internal PP ((__ptr_t __ptr)); +extern __ptr_t _malloc_internal_nolock PP ((__malloc_size_t __size)); +extern __ptr_t _realloc_internal_nolock PP ((__ptr_t __ptr, __malloc_size_t __size)); +extern void _free_internal_nolock PP ((__ptr_t __ptr)); + +#ifdef USE_PTHREAD +extern pthread_mutex_t _malloc_mutex, _aligned_blocks_mutex; +extern int _malloc_thread_enabled_p; +#define LOCK() \ + do { \ + if (_malloc_thread_enabled_p) \ + pthread_mutex_lock (&_malloc_mutex); \ + } while (0) +#define UNLOCK() \ + do { \ + if (_malloc_thread_enabled_p) \ + pthread_mutex_unlock (&_malloc_mutex); \ + } while (0) +#define LOCK_ALIGNED_BLOCKS() \ + do { \ + if (_malloc_thread_enabled_p) \ + pthread_mutex_lock (&_aligned_blocks_mutex); \ + } while (0) +#define UNLOCK_ALIGNED_BLOCKS() \ + do { \ + if (_malloc_thread_enabled_p) \ + pthread_mutex_unlock (&_aligned_blocks_mutex); \ + } while (0) +#else +#define LOCK() +#define UNLOCK() +#define LOCK_ALIGNED_BLOCKS() +#define UNLOCK_ALIGNED_BLOCKS() +#endif #endif /* _MALLOC_INTERNAL. */ @@ -328,17 +372,17 @@ extern __ptr_t r_re_alloc PP ((__ptr_t *__handleptr, __malloc_size_t __size)); Written May 1989 by Mike Haertel. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -356,7 +400,7 @@ Fifth Floor, Boston, MA 02110-1301, USA. extern __ptr_t bss_sbrk PP ((ptrdiff_t __size)); extern int bss_sbrk_did_unexec; #endif -__ptr_t (*__morecore) PP ((ptrdiff_t __size)) = __default_morecore; +__ptr_t (*__morecore) PP ((__malloc_ptrdiff_t __size)) = __default_morecore; /* Debugging hook for `malloc'. */ __ptr_t (*__malloc_hook) PP ((__malloc_size_t __size)); @@ -535,13 +579,55 @@ register_heapinfo () _heapinfo[block + blocks].busy.info.size = -blocks; } -/* Set everything up and remember that we have. */ -int -__malloc_initialize () +#ifdef USE_PTHREAD +pthread_mutex_t _malloc_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t _aligned_blocks_mutex = PTHREAD_MUTEX_INITIALIZER; +int _malloc_thread_enabled_p; + +static void +malloc_atfork_handler_prepare () { - if (__malloc_initialized) - return 0; + LOCK (); + LOCK_ALIGNED_BLOCKS (); +} + +static void +malloc_atfork_handler_parent () +{ + UNLOCK_ALIGNED_BLOCKS (); + UNLOCK (); +} + +static void +malloc_atfork_handler_child () +{ + UNLOCK_ALIGNED_BLOCKS (); + UNLOCK (); +} + +/* Set up mutexes and make malloc etc. thread-safe. */ +void +malloc_enable_thread () +{ + if (_malloc_thread_enabled_p) + return; + /* Some pthread implementations call malloc for statically + initialized mutexes when they are used first. To avoid such a + situation, we initialize mutexes here while their use is + disabled in malloc etc. */ + pthread_mutex_init (&_malloc_mutex, NULL); + pthread_mutex_init (&_aligned_blocks_mutex, NULL); + pthread_atfork (malloc_atfork_handler_prepare, + malloc_atfork_handler_parent, + malloc_atfork_handler_child); + _malloc_thread_enabled_p = 1; +} +#endif + +static void +malloc_initialize_1 () +{ #ifdef GC_MCHECK mcheck (NULL); #endif @@ -552,7 +638,7 @@ __malloc_initialize () heapsize = HEAP / BLOCKSIZE; _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info)); if (_heapinfo == NULL) - return 0; + return; memset (_heapinfo, 0, heapsize * sizeof (malloc_info)); _heapinfo[0].free.size = 0; _heapinfo[0].free.next = _heapinfo[0].free.prev = 0; @@ -564,16 +650,30 @@ __malloc_initialize () __malloc_initialized = 1; PROTECT_MALLOC_STATE (1); - return 1; + return; +} + +/* Set everything up and remember that we have. + main will call malloc which calls this function. That is before any threads + or signal handlers has been set up, so we don't need thread protection. */ +int +__malloc_initialize () +{ + if (__malloc_initialized) + return 0; + + malloc_initialize_1 (); + + return __malloc_initialized; } static int morecore_recursing; /* Get neatly aligned memory, initializing or growing the heap info table as necessary. */ -static __ptr_t morecore PP ((__malloc_size_t)); +static __ptr_t morecore_nolock PP ((__malloc_size_t)); static __ptr_t -morecore (size) +morecore_nolock (size) __malloc_size_t size; { __ptr_t result; @@ -616,7 +716,7 @@ morecore (size) `morecore_recursing' flag and return null. */ int save = errno; /* Don't want to clobber errno with ENOMEM. */ morecore_recursing = 1; - newinfo = (malloc_info *) _realloc_internal + newinfo = (malloc_info *) _realloc_internal_nolock (_heapinfo, newsize * sizeof (malloc_info)); morecore_recursing = 0; if (newinfo == NULL) @@ -672,7 +772,7 @@ morecore (size) /* Reset _heaplimit so _free_internal never decides it can relocate or resize the info table. */ _heaplimit = 0; - _free_internal (oldinfo); + _free_internal_nolock (oldinfo); PROTECT_MALLOC_STATE (0); /* The new heap limit includes the new table just allocated. */ @@ -687,7 +787,7 @@ morecore (size) /* Allocate memory from the heap. */ __ptr_t -_malloc_internal (size) +_malloc_internal_nolock (size) __malloc_size_t size; { __ptr_t result; @@ -712,11 +812,6 @@ _malloc_internal (size) if (size < sizeof (struct list)) size = sizeof (struct list); -#ifdef SUNOS_LOCALTIME_BUG - if (size < 16) - size = 16; -#endif - /* Determine the allocation policy based on the request size. */ if (size <= BLOCKSIZE / 2) { @@ -756,15 +851,17 @@ _malloc_internal (size) /* No free fragments of the desired size, so get a new block and break it into fragments, returning the first. */ #ifdef GC_MALLOC_CHECK - result = _malloc_internal (BLOCKSIZE); + result = _malloc_internal_nolock (BLOCKSIZE); PROTECT_MALLOC_STATE (0); +#elif defined (USE_PTHREAD) + result = _malloc_internal_nolock (BLOCKSIZE); #else result = malloc (BLOCKSIZE); #endif if (result == NULL) { PROTECT_MALLOC_STATE (1); - return NULL; + goto out; } /* Link all fragments but the first into the free list. */ @@ -814,7 +911,7 @@ _malloc_internal (size) final free block; if so we don't need to get as much. */ if (_heaplimit != 0 && block + lastblocks == _heaplimit && /* We can't do this if we will have to make the heap info - table bigger to accomodate the new space. */ + table bigger to accommodate the new space. */ block + wantblocks <= heapsize && get_contiguous_space ((wantblocks - lastblocks) * BLOCKSIZE, ADDRESS (block + lastblocks))) @@ -828,9 +925,9 @@ _malloc_internal (size) _heaplimit += wantblocks - lastblocks; continue; } - result = morecore (wantblocks * BLOCKSIZE); + result = morecore_nolock (wantblocks * BLOCKSIZE); if (result == NULL) - return NULL; + goto out; block = BLOCK (result); /* Put the new block at the end of the free list. */ _heapinfo[block].free.size = wantblocks; @@ -885,6 +982,20 @@ _malloc_internal (size) } PROTECT_MALLOC_STATE (1); + out: + return result; +} + +__ptr_t +_malloc_internal (size) + __malloc_size_t size; +{ + __ptr_t result; + + LOCK (); + result = _malloc_internal_nolock (size); + UNLOCK (); + return result; } @@ -892,10 +1003,21 @@ __ptr_t malloc (size) __malloc_size_t size; { + __ptr_t (*hook) (__malloc_size_t); + if (!__malloc_initialized && !__malloc_initialize ()) return NULL; - return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size); + /* Copy the value of __malloc_hook to an automatic variable in case + __malloc_hook is modified in another thread between its + NULL-check and the use. + + Note: Strictly speaking, this is not a right solution. We should + use mutexes to access non-read-only variables that are shared + among multiple threads. We just leave it for compatibility with + glibc malloc (i.e., assignments to __malloc_hook) for now. */ + hook = __malloc_hook; + return (hook != NULL ? *hook : _malloc_internal) (size); } #ifndef _LIBC @@ -931,17 +1053,17 @@ _realloc (ptr, size) Written May 1989 by Mike Haertel. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -956,8 +1078,7 @@ Fifth Floor, Boston, MA 02110-1301, USA. /* Cope with systems lacking `memmove'. */ #ifndef memmove -#if (defined (MEMMOVE_MISSING) || \ - !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) +#if (!defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) #ifdef emacs #undef __malloc_safe_bcopy #define __malloc_safe_bcopy safe_bcopy @@ -976,9 +1097,9 @@ void (*__free_hook) PP ((__ptr_t __ptr)); struct alignlist *_aligned_blocks = NULL; /* Return memory to the heap. - Like `free' but don't call a __free_hook if there is one. */ + Like `_free_internal' but don't lock mutex. */ void -_free_internal (ptr) +_free_internal_nolock (ptr) __ptr_t ptr; { int type; @@ -997,6 +1118,7 @@ _free_internal (ptr) PROTECT_MALLOC_STATE (0); + LOCK_ALIGNED_BLOCKS (); for (l = _aligned_blocks; l != NULL; l = l->next) if (l->aligned == ptr) { @@ -1004,6 +1126,7 @@ _free_internal (ptr) ptr = l->exact; break; } + UNLOCK_ALIGNED_BLOCKS (); block = BLOCK (ptr); @@ -1109,7 +1232,7 @@ _free_internal (ptr) table's blocks to the system before we have copied them to the new location. */ _heaplimit = 0; - _free_internal (_heapinfo); + _free_internal_nolock (_heapinfo); _heaplimit = oldlimit; /* Tell malloc to search from the beginning of the heap for @@ -1117,8 +1240,8 @@ _free_internal (ptr) _heapindex = 0; /* Allocate new space for the info table and move its data. */ - newinfo = (malloc_info *) _malloc_internal (info_blocks - * BLOCKSIZE); + newinfo = (malloc_info *) _malloc_internal_nolock (info_blocks + * BLOCKSIZE); PROTECT_MALLOC_STATE (0); memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE); _heapinfo = newinfo; @@ -1181,8 +1304,8 @@ _free_internal (ptr) _chunks_free -= BLOCKSIZE >> type; _bytes_free -= BLOCKSIZE; -#ifdef GC_MALLOC_CHECK - _free_internal (ADDRESS (block)); +#if defined (GC_MALLOC_CHECK) || defined (USE_PTHREAD) + _free_internal_nolock (ADDRESS (block)); #else free (ADDRESS (block)); #endif @@ -1222,14 +1345,27 @@ _free_internal (ptr) PROTECT_MALLOC_STATE (1); } +/* Return memory to the heap. + Like `free' but don't call a __free_hook if there is one. */ +void +_free_internal (ptr) + __ptr_t ptr; +{ + LOCK (); + _free_internal_nolock (ptr); + UNLOCK (); +} + /* Return memory to the heap. */ -FREE_RETURN_TYPE +void free (ptr) __ptr_t ptr; { - if (__free_hook != NULL) - (*__free_hook) (ptr); + void (*hook) (__ptr_t) = __free_hook; + + if (hook != NULL) + (*hook) (ptr); else _free_internal (ptr); } @@ -1250,17 +1386,17 @@ cfree (ptr) Written May 1989 by Mike Haertel. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -1275,8 +1411,7 @@ Fifth Floor, Boston, MA 02110-1301, USA. /* Cope with systems lacking `memmove'. */ -#if (defined (MEMMOVE_MISSING) || \ - !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) +#if (!defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG)) #ifdef emacs #undef __malloc_safe_bcopy @@ -1365,7 +1500,7 @@ __ptr_t (*__realloc_hook) PP ((__ptr_t __ptr, __malloc_size_t __size)); new region. This module has incestuous knowledge of the internals of both free and malloc. */ __ptr_t -_realloc_internal (ptr, size) +_realloc_internal_nolock (ptr, size) __ptr_t ptr; __malloc_size_t size; { @@ -1375,11 +1510,11 @@ _realloc_internal (ptr, size) if (size == 0) { - _free_internal (ptr); - return _malloc_internal (0); + _free_internal_nolock (ptr); + return _malloc_internal_nolock (0); } else if (ptr == NULL) - return _malloc_internal (size); + return _malloc_internal_nolock (size); block = BLOCK (ptr); @@ -1392,12 +1527,12 @@ _realloc_internal (ptr, size) /* Maybe reallocate a large block to a small fragment. */ if (size <= BLOCKSIZE / 2) { - result = _malloc_internal (size); + result = _malloc_internal_nolock (size); if (result != NULL) { memcpy (result, ptr, size); - _free_internal (ptr); - return result; + _free_internal_nolock (ptr); + goto out; } } @@ -1416,7 +1551,7 @@ _realloc_internal (ptr, size) Now we will free this chunk; increment the statistics counter so it doesn't become wrong when _free_internal decrements it. */ ++_chunks_used; - _free_internal (ADDRESS (block + blocks)); + _free_internal_nolock (ADDRESS (block + blocks)); result = ptr; } else if (blocks == _heapinfo[block].busy.info.size) @@ -1431,8 +1566,8 @@ _realloc_internal (ptr, size) /* Prevent free from actually returning memory to the system. */ oldlimit = _heaplimit; _heaplimit = 0; - _free_internal (ptr); - result = _malloc_internal (size); + _free_internal_nolock (ptr); + result = _malloc_internal_nolock (size); PROTECT_MALLOC_STATE (0); if (_heaplimit == 0) _heaplimit = oldlimit; @@ -1442,15 +1577,15 @@ _realloc_internal (ptr, size) the thing we just freed. Unfortunately it might have been coalesced with its neighbors. */ if (_heapindex == block) - (void) _malloc_internal (blocks * BLOCKSIZE); + (void) _malloc_internal_nolock (blocks * BLOCKSIZE); else { __ptr_t previous - = _malloc_internal ((block - _heapindex) * BLOCKSIZE); - (void) _malloc_internal (blocks * BLOCKSIZE); - _free_internal (previous); + = _malloc_internal_nolock ((block - _heapindex) * BLOCKSIZE); + (void) _malloc_internal_nolock (blocks * BLOCKSIZE); + _free_internal_nolock (previous); } - return NULL; + goto out; } if (ptr != result) memmove (result, ptr, blocks * BLOCKSIZE); @@ -1468,16 +1603,31 @@ _realloc_internal (ptr, size) { /* The new size is different; allocate a new space, and copy the lesser of the new size and the old. */ - result = _malloc_internal (size); + result = _malloc_internal_nolock (size); if (result == NULL) - return NULL; + goto out; memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type)); - _free_internal (ptr); + _free_internal_nolock (ptr); } break; } PROTECT_MALLOC_STATE (1); + out: + return result; +} + +__ptr_t +_realloc_internal (ptr, size) + __ptr_t ptr; + __malloc_size_t size; +{ + __ptr_t result; + + LOCK(); + result = _realloc_internal_nolock (ptr, size); + UNLOCK (); + return result; } @@ -1486,26 +1636,28 @@ realloc (ptr, size) __ptr_t ptr; __malloc_size_t size; { + __ptr_t (*hook) (__ptr_t, __malloc_size_t); + if (!__malloc_initialized && !__malloc_initialize ()) return NULL; - return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal) - (ptr, size); + hook = __realloc_hook; + return (hook != NULL ? *hook : _realloc_internal) (ptr, size); } /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -1592,17 +1744,17 @@ __default_morecore (increment) /* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -1628,9 +1780,10 @@ memalign (alignment, size) { __ptr_t result; unsigned long int adj, lastadj; + __ptr_t (*hook) (__malloc_size_t, __malloc_size_t) = __memalign_hook; - if (__memalign_hook) - return (*__memalign_hook) (alignment, size); + if (hook) + return (*hook) (alignment, size); /* Allocate a block with enough extra space to pad the block with up to (ALIGNMENT - 1) bytes if necessary. */ @@ -1665,6 +1818,7 @@ memalign (alignment, size) of an allocated block. */ struct alignlist *l; + LOCK_ALIGNED_BLOCKS (); for (l = _aligned_blocks; l != NULL; l = l->next) if (l->aligned == NULL) /* This slot is free. Use it. */ @@ -1672,37 +1826,74 @@ memalign (alignment, size) if (l == NULL) { l = (struct alignlist *) malloc (sizeof (struct alignlist)); - if (l == NULL) + if (l != NULL) { - free (result); - return NULL; + l->next = _aligned_blocks; + _aligned_blocks = l; } - l->next = _aligned_blocks; - _aligned_blocks = l; } - l->exact = result; - result = l->aligned = (char *) result + alignment - adj; + if (l != NULL) + { + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; + } + UNLOCK_ALIGNED_BLOCKS (); + if (l == NULL) + { + free (result); + result = NULL; + } } return result; } +#ifndef ENOMEM +#define ENOMEM 12 +#endif + +#ifndef EINVAL +#define EINVAL 22 +#endif + +int +posix_memalign (memptr, alignment, size) + __ptr_t *memptr; + __malloc_size_t alignment; + __malloc_size_t size; +{ + __ptr_t mem; + + if (alignment == 0 + || alignment % sizeof (__ptr_t) != 0 + || (alignment & (alignment - 1)) != 0) + return EINVAL; + + mem = memalign (alignment, size); + if (mem == NULL) + return ENOMEM; + + *memptr = mem; + + return 0; +} + #endif /* Not DJGPP v1 */ /* Allocate memory on a page boundary. Copyright (C) 1991, 92, 93, 94, 96 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -1759,17 +1950,17 @@ valloc (size) Written May 1989 by Mike Haertel. This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as +modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 -Library General Public License for more details. +General Public License for more details. -You should have received a copy of the GNU Library General Public -License along with this library; see the file COPYING.LIB. If +You should have received a copy of the GNU General Public +License along with this library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.