e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
44466d2010-09-21Henrik Grubbström (Grubba) || $Id: pike_memory.h,v 1.45 2010/09/21 15:24:55 grubba Exp $
e576bb2002-10-11Martin Nilsson */
24ddc71998-03-28Henrik Grubbström (Grubba) 
cde67a2008-04-29Martin Stjernholm #ifndef PIKE_MEMORY_H #define PIKE_MEMORY_H
9aa6fa1997-05-19Fredrik Hübinette (Hubbe)  #include "global.h"
3e625c1998-10-11Fredrik Hübinette (Hubbe) #include "stralloc.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) 
4281d22002-11-20Henrik Grubbström (Grubba) #ifdef USE_VALGRIND
7ca8592002-11-23Martin Stjernholm 
ca32102006-07-02Martin Stjernholm #define HAVE_VALGRIND_MACROS /* Assume that any of the following header files have the macros we * need. Haven't checked if it's true or not. */
08445f2003-05-30Martin Stjernholm #ifdef HAVE_MEMCHECK_H #include <memcheck.h> #elif defined(HAVE_VALGRIND_MEMCHECK_H) #include <valgrind/memcheck.h> #elif defined(HAVE_VALGRIND_H) #include <valgrind.h>
ca32102006-07-02Martin Stjernholm #else #undef HAVE_VALGRIND_MACROS
08445f2003-05-30Martin Stjernholm #endif
ca32102006-07-02Martin Stjernholm #endif /* USE_VALGRIND */ #ifdef HAVE_VALGRIND_MACROS
cde67a2008-04-29Martin Stjernholm #ifndef VALGRIND_MAKE_NOACCESS #define VALGRIND_MAKE_NOACCESS VALGRIND_MAKE_MEM_NOACCESS #define VALGRIND_MAKE_WRITABLE VALGRIND_MAKE_MEM_UNDEFINED #define VALGRIND_MAKE_READABLE VALGRIND_MAKE_MEM_DEFINED #endif
4281d22002-11-20Henrik Grubbström (Grubba) /* No Access */
7ca8592002-11-23Martin Stjernholm #define PIKE_MEM_NA(lvalue) do { \
6546b22002-11-23Martin Stjernholm  PIKE_MEM_NA_RANGE(&(lvalue), sizeof (lvalue)); \
7ca8592002-11-23Martin Stjernholm  } while (0) #define PIKE_MEM_NA_RANGE(addr, bytes) do { \ VALGRIND_DISCARD(VALGRIND_MAKE_NOACCESS(addr, bytes)); \ } while (0) /* Write Only -- Will become RW when having been written to */ #define PIKE_MEM_WO(lvalue) do { \
6546b22002-11-23Martin Stjernholm  PIKE_MEM_WO_RANGE(&(lvalue), sizeof (lvalue)); \
7ca8592002-11-23Martin Stjernholm  } while (0) #define PIKE_MEM_WO_RANGE(addr, bytes) do { \ VALGRIND_DISCARD(VALGRIND_MAKE_WRITABLE(addr, bytes)); \ } while (0)
4281d22002-11-20Henrik Grubbström (Grubba) /* Read/Write */
7ca8592002-11-23Martin Stjernholm #define PIKE_MEM_RW(lvalue) do { \
6546b22002-11-23Martin Stjernholm  PIKE_MEM_RW_RANGE(&(lvalue), sizeof (lvalue)); \
7ca8592002-11-23Martin Stjernholm  } while (0) #define PIKE_MEM_RW_RANGE(addr, bytes) do { \ VALGRIND_DISCARD(VALGRIND_MAKE_READABLE(addr, bytes)); \ } while (0)
4281d22002-11-20Henrik Grubbström (Grubba) /* Read Only -- Not currently supported by valgrind */
7ca8592002-11-23Martin Stjernholm #define PIKE_MEM_RO(lvalue) do { \
6546b22002-11-23Martin Stjernholm  PIKE_MEM_RO_RANGE(&(lvalue), sizeof (lvalue)); \
7ca8592002-11-23Martin Stjernholm  } while (0) #define PIKE_MEM_RO_RANGE(addr, bytes) do { \ VALGRIND_DISCARD(VALGRIND_MAKE_READABLE(addr, bytes)); \ } while (0)
f09e482002-11-23Martin Stjernholm #define PIKE_MEM_CHECKER() RUNNING_ON_VALGRIND
4281d22002-11-20Henrik Grubbström (Grubba) #else
7ca8592002-11-23Martin Stjernholm  #define PIKE_MEM_NA(lvalue) do {} while (0) #define PIKE_MEM_NA_RANGE(addr, bytes) do {} while (0) #define PIKE_MEM_WO(lvalue) do {} while (0) #define PIKE_MEM_WO_RANGE(addr, bytes) do {} while (0) #define PIKE_MEM_RW(lvalue) do {} while (0) #define PIKE_MEM_RW_RANGE(addr, bytes) do {} while (0) #define PIKE_MEM_RO(lvalue) do {} while (0) #define PIKE_MEM_RO_RANGE(addr, bytes) do {} while (0)
f09e482002-11-23Martin Stjernholm #define PIKE_MEM_CHECKER() 0
7ca8592002-11-23Martin Stjernholm 
ca32102006-07-02Martin Stjernholm #endif /* HAVE_VALGRIND_MACROS */
4281d22002-11-20Henrik Grubbström (Grubba) 
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #define MEMSEARCH_LINKS 512 struct link { struct link *next;
e0755c2000-08-15Henrik Grubbström (Grubba)  INT32 key; ptrdiff_t offset;
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) }; enum methods { no_search, use_memchr, memchr_and_memcmp,
db4a401998-10-09Fredrik Hübinette (Hubbe)  hubbe_search, boyer_moore
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) }; struct mem_searcher { enum methods method; char *needle;
61a8ec2000-08-11Henrik Grubbström (Grubba)  size_t needlelen;
7901142000-08-15Henrik Grubbström (Grubba)  size_t hsize, max;
9aa6fa1997-05-19Fredrik Hübinette (Hubbe)  struct link links[MEMSEARCH_LINKS]; struct link *set[MEMSEARCH_LINKS]; };
9b1f032000-10-09Fredrik Hübinette (Hubbe)  #if 1 /* use new searching stuff */ #include "pike_search.h" #else
db4a401998-10-09Fredrik Hübinette (Hubbe) struct generic_mem_searcher { char needle_shift; char haystack_shift; union data_u { struct mem_searcher eightbit; struct other_search_s { enum methods method; void *needle;
393a592000-08-16Henrik Grubbström (Grubba)  size_t needlelen;
db4a401998-10-09Fredrik Hübinette (Hubbe)  int first_char; } other; } data; };
9b1f032000-10-09Fredrik Hübinette (Hubbe) #endif
4218011999-01-31Fredrik Hübinette (Hubbe) #include "block_alloc_h.h"
db4a401998-10-09Fredrik Hübinette (Hubbe) #define MEMCHR0 MEMCHR
d0e2311999-10-24Henrik Grubbström (Grubba) /* Note to self: Prototypes must be updated manually /Hubbe */
f5757f2000-08-11Henrik Grubbström (Grubba) PMOD_EXPORT ptrdiff_t pcharp_memcmp(PCHARP a, PCHARP b, int sz);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT long pcharp_strlen(PCHARP a);
a309212000-09-11Henrik Grubbström (Grubba) PMOD_EXPORT INLINE p_wchar1 *MEMCHR1(p_wchar1 *p, p_wchar2 c, ptrdiff_t e);
51f0e02000-08-10Henrik Grubbström (Grubba) PMOD_EXPORT INLINE p_wchar2 *MEMCHR2(p_wchar2 *p, p_wchar2 c, ptrdiff_t e);
84f8952000-08-16Henrik Grubbström (Grubba) PMOD_EXPORT void swap(char *a, char *b, size_t size); PMOD_EXPORT void reverse(char *memory, size_t nitems, size_t size);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void reorder(char *memory, INT32 nitems, INT32 size,INT32 *order);
51f0e02000-08-10Henrik Grubbström (Grubba) PMOD_EXPORT size_t hashmem(const unsigned char *a, size_t len, size_t mlen); PMOD_EXPORT size_t hashstr(const unsigned char *str, ptrdiff_t maxn); PMOD_EXPORT size_t simple_hashmem(const unsigned char *str, ptrdiff_t len, ptrdiff_t maxn);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void init_memsearch(struct mem_searcher *s,
9aa6fa1997-05-19Fredrik Hübinette (Hubbe)  char *needle,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t needlelen, size_t max_haystacklen);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT char *memory_search(struct mem_searcher *s,
9aa6fa1997-05-19Fredrik Hübinette (Hubbe)  char *haystack,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t haystacklen);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void init_generic_memsearcher(struct generic_mem_searcher *s,
db4a401998-10-09Fredrik Hübinette (Hubbe)  void *needle,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t needlelen,
db4a401998-10-09Fredrik Hübinette (Hubbe)  char needle_shift,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t estimated_haystack,
db4a401998-10-09Fredrik Hübinette (Hubbe)  char haystack_shift);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void *generic_memory_search(struct generic_mem_searcher *s,
db4a401998-10-09Fredrik Hübinette (Hubbe)  void *haystack,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t haystacklen,
db4a401998-10-09Fredrik Hübinette (Hubbe)  char haystack_shift);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT char *my_memmem(char *needle,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t needlelen,
9aa6fa1997-05-19Fredrik Hübinette (Hubbe)  char *haystack,
c9f0312000-08-10Henrik Grubbström (Grubba)  size_t haystacklen);
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void memfill(char *to,
9aa6fa1997-05-19Fredrik Hübinette (Hubbe)  INT32 tolen, char *from, INT32 fromlen, INT32 offset);
5c37fd2001-10-03Martin Stjernholm PMOD_EXPORT void *debug_xalloc(size_t size);
f1792d2000-12-13Fredrik Hübinette (Hubbe) PMOD_EXPORT void *debug_xmalloc(size_t s); PMOD_EXPORT void debug_xfree(void *mem); PMOD_EXPORT void *debug_xrealloc(void *m, size_t s); PMOD_EXPORT void *debug_xcalloc(size_t n, size_t s);
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) 
caf84c2005-05-26Henrik Grubbström (Grubba) void *mexec_alloc(size_t sz); void *mexec_realloc(void *ptr, size_t sz); void mexec_free(void *ptr);
db4a401998-10-09Fredrik Hübinette (Hubbe) #undef BLOCK_ALLOC
52068e2000-12-01Henrik Grubbström (Grubba) #ifdef HANDLES_UNALIGNED_MEMORY_ACCESS #define DO_IF_ELSE_UNALIGNED_MEMORY_ACCESS(IF, ELSE) IF #else /* !HANDLES_UNALIGNED_MEMORY_ACCESS */ #define DO_IF_ELSE_UNALIGNED_MEMORY_ACCESS(IF, ELSE) ELSE #endif /* HANDLES_UNALIGNED_MEMORY_ACCESS */ #if SIZEOF_CHAR_P == 4 #define DIVIDE_BY_2_CHAR_P(X) (X >>= 3) #else /* sizeof(char *) != 4 */ #if SIZEOF_CHAR_P == 8 #define DIVIDE_BY_2_CHAR_P(X) (X >>= 4) #else /* sizeof(char *) != 8 */ #define DIVIDE_BY_2_CHAR_P(X) (X /= 2*sizeof(size_t)) #endif /* sizeof(char *) == 8 */ #endif /* sizeof(char *) == 4 */
d4f7bc2000-12-01Henrik Grubbström (Grubba) /* NB: RET should be an lvalue of type size_t. */ #define DO_HASHMEM(RET, A, LEN, MLEN) \
52068e2000-12-01Henrik Grubbström (Grubba)  do { \ const unsigned char *a = A; \ size_t len = LEN; \ size_t mlen = MLEN; \ size_t ret; \ \ ret = 9248339*len; \
44466d2010-09-21Henrik Grubbström (Grubba)  if(len<=mlen) \
52068e2000-12-01Henrik Grubbström (Grubba)  mlen=len; \ else \ { \ switch(len-mlen) \ { \ default: ret^=(ret<<6) + a[len-7]; \ case 7: \ case 6: ret^=(ret<<7) + a[len-5]; \ case 5: \ case 4: ret^=(ret<<4) + a[len-4]; \ case 3: ret^=(ret<<3) + a[len-3]; \ case 2: ret^=(ret<<3) + a[len-2]; \ case 1: ret^=(ret<<3) + a[len-1]; \ } \ } \ a += mlen & 7; \ switch(mlen&7) \ { \ case 7: ret^=a[-7]; \ case 6: ret^=(ret<<4)+a[-6]; \ case 5: ret^=(ret<<7)+a[-5]; \ case 4: ret^=(ret<<6)+a[-4]; \ case 3: ret^=(ret<<3)+a[-3]; \ case 2: ret^=(ret<<7)+a[-2]; \ case 1: ret^=(ret<<5)+a[-1]; \ } \ \ DO_IF_ELSE_UNALIGNED_MEMORY_ACCESS( \ { \ size_t *b; \ b=(size_t *)a; \ \ for(DIVIDE_BY_2_CHAR_P(mlen);mlen--;) \ { \ ret^=(ret<<7)+*(b++); \ ret^=(ret>>6)+*(b++); \ } \ } \ , \ for(mlen >>= 3; mlen--;) \ { \
d2f2052000-12-01Henrik Grubbström (Grubba)  register size_t t1; \ register size_t t2; \
52068e2000-12-01Henrik Grubbström (Grubba)  t1= a[0]; \ t2= a[1]; \ t1=(t1<<5) + a[2]; \ t2=(t2<<4) + a[3]; \ t1=(t1<<7) + a[4]; \ t2=(t2<<5) + a[5]; \ t1=(t1<<3) + a[6]; \ t2=(t2<<4) + a[7]; \ a += 8; \ ret^=(ret<<7) + (ret>>6) + t1 + (t2<<6); \ } \ ) \ \
d4f7bc2000-12-01Henrik Grubbström (Grubba)  RET = ret; \
52068e2000-12-01Henrik Grubbström (Grubba)  } while(0)
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #endif