* winsup.api/user_malloc.c: New file.
This commit is contained in:
		
							parent
							
								
									730f10974a
								
							
						
					
					
						commit
						e3f56b2b3d
					
				| 
						 | 
				
			
			@ -1,3 +1,7 @@
 | 
			
		|||
2006-06-12  Pierre Humblet  Pierre.Humblet@ieee.org
 | 
			
		||||
 | 
			
		||||
	* winsup.api/user_malloc.c: New file.
 | 
			
		||||
 | 
			
		||||
2006-05-30  Christopher Faylor  <cgf@timesys.com>
 | 
			
		||||
 | 
			
		||||
	* winsup.api/cygload.h: Increase padding to 32768.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,216 @@
 | 
			
		|||
/* Test of external malloc, calloc, realloc and free capability */
 | 
			
		||||
 | 
			
		||||
#if 1
 | 
			
		||||
#include "test.h"
 | 
			
		||||
#include "usctest.h"
 | 
			
		||||
#else
 | 
			
		||||
enum {TPASS, TFAIL, TBROK, TINFO};
 | 
			
		||||
#define tst_resm(xxx, yyy...) printf(yyy), printf(" RES %d\n", xxx)
 | 
			
		||||
#define tst_brkm(xxx, yyy, zzz...) printf(zzz), printf(" RES %d\n", xxx)
 | 
			
		||||
#define tst_exit()
 | 
			
		||||
int Tst_count;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <strings.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
const char *TCID = "malloc";    /* Test program identifier. */
 | 
			
		||||
int TST_TOTAL = 2;              /* Total number of test cases. */
 | 
			
		||||
extern int Tst_count;           /* Test Case counter for tst_* routines */
 | 
			
		||||
 | 
			
		||||
/* Main test.
 | 
			
		||||
   Verbose mode if argc > 0
 | 
			
		||||
   Note that malloc and friends are also called by Cygwin before main,
 | 
			
		||||
   and that malloc can call getenv. */
 | 
			
		||||
 | 
			
		||||
int malloc_error = 0, realloc_error = 0, free_error = 0; 
 | 
			
		||||
int calloc_count = 0, malloc_count = 0, realloc_count = 0, free_count = 0;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
cleanup (void)
 | 
			
		||||
{
 | 
			
		||||
  tst_exit(); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
syncwithchild (pid_t pid, int expected_exit_status)
 | 
			
		||||
{
 | 
			
		||||
  int status;
 | 
			
		||||
 | 
			
		||||
  if (waitpid (pid, &status, 0) != pid)
 | 
			
		||||
    {
 | 
			
		||||
      tst_brkm (TBROK, cleanup, "Wait for child: %s", strerror (errno));
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  if (!WIFEXITED (status))
 | 
			
		||||
    {
 | 
			
		||||
      tst_brkm (TBROK, cleanup, "Child had abnormal exit");
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  if (WEXITSTATUS (status) != expected_exit_status)
 | 
			
		||||
    {
 | 
			
		||||
      tst_brkm (TFAIL, cleanup, "Child had exit status %d != %d",
 | 
			
		||||
		WEXITSTATUS (status), expected_exit_status);
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
void * mallocX (size_t size);
 | 
			
		||||
void * callocX (size_t nmemb, size_t size);
 | 
			
		||||
void * reallocX (void * ptr, size_t size);
 | 
			
		||||
void freeX(void *);
 | 
			
		||||
 | 
			
		||||
#define malloc mallocX
 | 
			
		||||
#define calloc callocX
 | 
			
		||||
#define realloc reallocX
 | 
			
		||||
#define free freeX
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int main (int argc, char * argv[])
 | 
			
		||||
{ 
 | 
			
		||||
  void * ptr;
 | 
			
		||||
  int error = 0;
 | 
			
		||||
  pid_t pid;
 | 
			
		||||
 | 
			
		||||
  Tst_count = 0;
 | 
			
		||||
 | 
			
		||||
  tst_resm(TINFO, "Testing if external malloc works. ppid %d", getppid());
 | 
			
		||||
 | 
			
		||||
  ptr = malloc (16);
 | 
			
		||||
  ptr = calloc (1, 16);
 | 
			
		||||
  ptr = realloc (ptr, 24);
 | 
			
		||||
  free (ptr);
 | 
			
		||||
 | 
			
		||||
  error = (malloc_count == 0 || calloc_count == 0 || realloc_count == 0 || free_count == 0);
 | 
			
		||||
 | 
			
		||||
  if (error || argc > 1)
 | 
			
		||||
    {
 | 
			
		||||
      printf ("malloc_count %d, calloc_count %d, realloc_count %d, free_count %d\n", 
 | 
			
		||||
	      malloc_count, calloc_count, realloc_count, free_count);
 | 
			
		||||
      printf ("malloc_error %d, realloc_error %d, free_error %d\n",
 | 
			
		||||
	      malloc_error, realloc_error, free_error);
 | 
			
		||||
    }
 | 
			
		||||
  tst_resm (!error ? TPASS : TFAIL, "Running in pid %d", getpid());
 | 
			
		||||
 | 
			
		||||
  /* If run from Windows, run also from Cygwin */
 | 
			
		||||
  if (getppid() == 1)
 | 
			
		||||
    {
 | 
			
		||||
      tst_resm(TINFO, "Ready to test if malloc works from Cygwin");
 | 
			
		||||
 | 
			
		||||
      if ((pid = fork()) == 0)
 | 
			
		||||
	{
 | 
			
		||||
	  tst_resm(TINFO, "Ready to exec with pid %d\n", getpid());
 | 
			
		||||
	  error = execl(argv[0], argv[0], argc > 1? argv[1]:NULL, NULL);
 | 
			
		||||
	  exit(error);
 | 
			
		||||
	}
 | 
			
		||||
      else if (pid < 0)
 | 
			
		||||
	tst_brkm (TBROK, cleanup, "Fork failed: %s", strerror (errno));
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  error = syncwithchild (pid, 0);
 | 
			
		||||
	  tst_resm (!error ? TPASS : TFAIL, "Running in pid %d", pid);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  tst_exit ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/****************************************
 | 
			
		||||
Actual malloc & friends implementation 
 | 
			
		||||
****************************************/
 | 
			
		||||
 | 
			
		||||
typedef unsigned long long ull;
 | 
			
		||||
 
 | 
			
		||||
#define SIZE (1024*1024ULL) /* long long */ 
 | 
			
		||||
ull buffer[SIZE]; 
 | 
			
		||||
ull * current = buffer;
 | 
			
		||||
 | 
			
		||||
static int is_valid (void * ptr)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int iptr = (unsigned int) ptr;
 | 
			
		||||
  ull * ullptr = (ull *) ptr;
 | 
			
		||||
 | 
			
		||||
  iptr = (iptr / sizeof(ull)) * sizeof(ull);
 | 
			
		||||
  if (iptr != (int) ptr)
 | 
			
		||||
    return 0;
 | 
			
		||||
  if (--ullptr < buffer || ullptr[0] > SIZE || ullptr  + ullptr[0]  > current)
 | 
			
		||||
    return 0;
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void * malloc (size_t size)
 | 
			
		||||
{
 | 
			
		||||
  ull llsize = (size + 2 * sizeof (ull) - 1) / sizeof (ull);
 | 
			
		||||
  static char * envptr;
 | 
			
		||||
  void * ret;
 | 
			
		||||
  
 | 
			
		||||
  /* Make sure getenv works */
 | 
			
		||||
  if (!envptr)
 | 
			
		||||
    envptr = getenv ("PATH");
 | 
			
		||||
 | 
			
		||||
  malloc_count++;
 | 
			
		||||
  if (current + llsize >= buffer + SIZE) 
 | 
			
		||||
    {
 | 
			
		||||
      malloc_error++;
 | 
			
		||||
      errno = ENOMEM;
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
  *current = llsize;
 | 
			
		||||
  ret = (void *) (current + 1);
 | 
			
		||||
  current += llsize;
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void * calloc (size_t nmemb, size_t size) 
 | 
			
		||||
{
 | 
			
		||||
  calloc_count++;
 | 
			
		||||
  void * ptr = malloc (nmemb * size);
 | 
			
		||||
  malloc_count--;
 | 
			
		||||
  if (ptr)
 | 
			
		||||
    memset(ptr, 0, nmemb * size);
 | 
			
		||||
  return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void * realloc (void * ptr, size_t size)
 | 
			
		||||
{
 | 
			
		||||
  const ull ullsize = (size + 2 * sizeof (ull) - 1) / sizeof (ull);
 | 
			
		||||
  ull * const ullptr = (ull *) ptr;
 | 
			
		||||
  void * newptr;
 | 
			
		||||
  
 | 
			
		||||
  realloc_count++;
 | 
			
		||||
  
 | 
			
		||||
  if (ptr)
 | 
			
		||||
    {
 | 
			
		||||
      if (!is_valid (ptr))
 | 
			
		||||
	{
 | 
			
		||||
	  realloc_error++;
 | 
			
		||||
	  errno = ENOMEM;
 | 
			
		||||
	  return NULL;
 | 
			
		||||
	}  
 | 
			
		||||
      if (ullptr[-1] >= ullsize)
 | 
			
		||||
	return ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  newptr = malloc (size);
 | 
			
		||||
  malloc_count--;
 | 
			
		||||
  
 | 
			
		||||
  if (ptr && newptr)
 | 
			
		||||
    memcpy (newptr, ptr, size);
 | 
			
		||||
  
 | 
			
		||||
  return newptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void free (void * x)
 | 
			
		||||
{
 | 
			
		||||
  free_count++;
 | 
			
		||||
  if (x && ! is_valid (x))
 | 
			
		||||
      free_error++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue