OSDN Git Service

* winsup.api/user_malloc.c: New file.
authorcorinna <corinna>
Mon, 12 Jun 2006 13:59:36 +0000 (13:59 +0000)
committercorinna <corinna>
Mon, 12 Jun 2006 13:59:36 +0000 (13:59 +0000)
winsup/testsuite/ChangeLog
winsup/testsuite/winsup.api/user_malloc.c [new file with mode: 0644]

index 95162a4..8e8cdda 100644 (file)
@@ -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.
diff --git a/winsup/testsuite/winsup.api/user_malloc.c b/winsup/testsuite/winsup.api/user_malloc.c
new file mode 100644 (file)
index 0000000..8685f86
--- /dev/null
@@ -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++;
+}
+