In on-going discussion about malloc(0), I made a mention about this
approach.  As this idea is somehow independent of the malloc(0) stuff,
I'm starting a new thread.

Folks, in the attached file you can see how easy is to support
coalesced mallocs at runtime. This would enable us to disable the
coalesced mallocs for optimized builds and run the code under valgrind
to catch invalid memory accesses.

The code has memory leaks on purpose to get output from -malloc_dump,
you can try it with debug/opt builds, passing  -malloc_coalesced [0|1]
option and value. If you pass "-n size1,size2" you can control the
sizes for the PetscMalloc2 calls.

If you use a optimized build, and any of the sizes is 0, and you pass
-malloc_coalesced 0, valgrind will be able to catch the invalid
writes.

$ PETSC_ARCH=arch-linux2-c-opt make TestMalloc

$ valgrind -q ./TestMalloc -n 0,1 -malloc_coalesced 1 2>&1 | grep
"Invalid write"
<no-ouput>

$ valgrind -q ./TestMalloc -n 0,1 -malloc_coalesced 0 2>&1 | grep
"Invalid write"
==2304== Invalid write of size 1
==2304== Invalid write of size 4
==2304== Invalid write of size 8

$ valgrind -q ./TestMalloc -n 0,0 -malloc_coalesced 0 2>&1 | grep
"Invalid write"
==2306== Invalid write of size 1
==2306== Invalid write of size 1
==2306== Invalid write of size 4
==2306== Invalid write of size 4
==2306== Invalid write of size 8
==2306== Invalid write of size 8


IMHO, we should definitely implement this approach. If you agree, let
discuss about when to enable/disable the coalesced mallocs (e.g., if
users pass -malloc or -malloc_dump, perhaps we should disable
coalescing, and only enable it back if -malloc_coalesced 1 is
explicitly asked for).


-- 
Lisandro Dalcin
============
Research Scientist
Computer, Electrical and Mathematical Sciences & Engineering (CEMSE)
Numerical Porous Media Center (NumPor)
King Abdullah University of Science and Technology (KAUST)
http://numpor.kaust.edu.sa/

4700 King Abdullah University of Science and Technology
al-Khawarizmi Bldg (Bldg 1), Office # 4332
Thuwal 23955-6900, Kingdom of Saudi Arabia
http://www.kaust.edu.sa

Office Phone: +966 12 808-0459
#include <petsc.h>

#undef PetscMalloc1
#undef PetscMalloc2
#undef PetscMalloc3

/* ----------------------------------------------------------- */

/* include/petscsys.h */

#define PetscMalloc1(m1,r1) PetscMalloc((m1)*sizeof(**(r1)),r1)

#define PetscMalloc2(m1,r1,m2,r2) \
  (PetscLikely(PetscMallocCoalesced) \
   ? (PetscMalloc((m1)*sizeof(**(r1))+(m2)*sizeof(**(r2))+(PETSC_MEMALIGN-1),r1) || \
      (*(void**)(r2) = PetscAddrAlign(*(r1)+(m1)),0)) \
   : (PetscMalloc1(m1,r1) || PetscMalloc1(m2,r2)))

#define PetscMalloc3(m1,r1,m2,r2,m3,r3) \
  (PetscLikely(PetscMallocCoalesced) \
   ? (PetscMalloc((m1)*sizeof(**(r1))+(m2)*sizeof(**(r2))+(m3)*sizeof(**(r3))+2*(PETSC_MEMALIGN-1),r1) || \
      (*(void**)(r2) = PetscAddrAlign(*(r1)+(m1)), \
       *(void**)(r3) = PetscAddrAlign(*(r2)+(m2)),0)) \
   : (PetscMalloc1(m1,r1) || PetscMalloc1(m2,r2) || PetscMalloc1(m3,r3)))

PETSC_EXTERN PetscBool PetscMallocCoalesced;

/* ----------------------------------------------------------- */

/* src/sys/memory/mtr.c */

#if defined(PETSC_USE_DEBUG)
PetscBool PetscMallocCoalesced = PETSC_FALSE;
#else
PetscBool PetscMallocCoalesced = PETSC_TRUE;
#endif

/* ----------------------------------------------------------- */

#undef  __FUNCT__
#define __FUNCT__ "main"
int main(int argc, char *argv[])
{
  PetscInt        n[2] = {1,1},nn = 2;
  char           *c1,*c2;
  PetscInt       *i1,*i2;
  PetscScalar    *s1,*s2;
  PetscErrorCode ierr;

  ierr = PetscInitialize(&argc,&argv,0,0);CHKERRQ(ierr);

  /* this line should go inside PetscOptionsCheckInitial_Private() */
  ierr = PetscOptionsGetBool(NULL,"-malloc_coalesced",&PetscMallocCoalesced,NULL);CHKERRQ(ierr);

  ierr = PetscOptionsGetIntArray(NULL,"-n",n,&nn,NULL);CHKERRQ(ierr);
  ierr = PetscMalloc2((size_t)n[0],&c1,(size_t)n[1],&c2);CHKERRQ(ierr);
  ierr = PetscMalloc2((size_t)n[0],&i1,(size_t)n[1],&i2);CHKERRQ(ierr);
  ierr = PetscMalloc2((size_t)n[0],&s1,(size_t)n[1],&s2);CHKERRQ(ierr);

  printf("c1=%p c2=%p\n",c1,c2);
  printf("i1=%p i2=%p\n",i1,i2);
  printf("s1=%p s2=%p\n",s1,s2);
  c1[0] = 0; c2[0] = 0;
  i1[0] = 0; i2[0] = 0;
  s1[0] = 0; s2[0] = 0;

  if (0) {
    ierr = PetscFree2(c1,c2);CHKERRQ(ierr);
    ierr = PetscFree2(i1,i2);CHKERRQ(ierr);
    ierr = PetscFree2(s1,s2);CHKERRQ(ierr);
  }

  ierr = PetscFinalize();CHKERRQ(ierr);
  return 0;
}

Attachment: makefile
Description: Binary data

Reply via email to