From 8396447cdbdff0b62914748de2fec04281dc9114 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 12 Feb 2013 10:33:40 -0300
Subject: [PATCH] Create libpgcommon, and move pg_malloc et al to it
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

libpgcommon is a new static library to allow sharing code among the
various frontend programs and backend; this lets us eliminate duplicate
implementations of common routines.  We avoid libpgport, because that's
intended as a place for porting issues; per discussion, it seems better
to keep them separate.

The first use case, and the only implemented by this patch, is pg_malloc
and friends, which many frontend programs were already using.

At the same time, we can use this to provide palloc emulation functions
for the frontend; this way, some palloc-using files in the backend can
also be used by the frontend cleanly.  To do this, we change palloc() in
the backend to be a function instead of a macro on top of
MemoryContextAlloc().  This was previously believed to cause loss of
performance, but this implementation has been tweaked by Tom and Andres
so that on modern compilers it provides a slight improvement over the
previous one.

This lets us clean up some places that were already with
localized hacks.

Most of the pg_malloc/palloc changes in this patch were authored by
Andres Freund. Zoltán Böszörményi also independently provided a form of
that.  libpgcommon infrastructure was authored by Álvaro.
---
 contrib/oid2name/oid2name.c           |  50 ----------
 contrib/pg_upgrade/check.c            |   2 +-
 contrib/pg_upgrade/controldata.c      |   2 +-
 contrib/pg_upgrade/dump.c             |   2 +-
 contrib/pg_upgrade/exec.c             |   2 +-
 contrib/pg_upgrade/file.c             |   2 +-
 contrib/pg_upgrade/function.c         |   2 +-
 contrib/pg_upgrade/info.c             |   2 +-
 contrib/pg_upgrade/option.c           |   2 +-
 contrib/pg_upgrade/page.c             |   2 +-
 contrib/pg_upgrade/parallel.c         |   2 +-
 contrib/pg_upgrade/pg_upgrade.c       |   2 +-
 contrib/pg_upgrade/pg_upgrade.h       |   4 -
 contrib/pg_upgrade/relfilenode.c      |   2 +-
 contrib/pg_upgrade/server.c           |   2 +-
 contrib/pg_upgrade/tablespace.c       |   2 +-
 contrib/pg_upgrade/util.c             |  51 +---------
 contrib/pg_upgrade/version.c          |   2 +-
 contrib/pg_upgrade/version_old_8_3.c  |   2 +-
 contrib/pgbench/pgbench.c             |  53 -----------
 src/Makefile                          |   1 +
 src/Makefile.global.in                |  25 ++---
 src/backend/storage/file/copydir.c    |  11 ---
 src/backend/utils/mmgr/mcxt.c         |  78 ++++++++--------
 src/bin/initdb/initdb.c               |  39 --------
 src/bin/pg_basebackup/streamutil.c    |  37 --------
 src/bin/pg_basebackup/streamutil.h    |   4 -
 src/bin/pg_ctl/pg_ctl.c               |  38 --------
 src/bin/pg_dump/Makefile              |   6 +-
 src/bin/pg_dump/common.c              |   2 -
 src/bin/pg_dump/compress_io.c         |   1 -
 src/bin/pg_dump/dumpmem.c             |  76 ---------------
 src/bin/pg_dump/dumpmem.h             |  22 -----
 src/bin/pg_dump/dumputils.c           |   1 -
 src/bin/pg_dump/nls.mk                |   2 +-
 src/bin/pg_dump/pg_backup_archiver.c  |   1 -
 src/bin/pg_dump/pg_backup_custom.c    |   1 -
 src/bin/pg_dump/pg_backup_db.c        |   1 -
 src/bin/pg_dump/pg_backup_directory.c |   1 -
 src/bin/pg_dump/pg_backup_null.c      |   1 -
 src/bin/pg_dump/pg_backup_tar.c       |   1 -
 src/bin/pg_dump/pg_dump.c             |   1 -
 src/bin/pg_dump/pg_dump_sort.c        |   1 -
 src/bin/pg_dump/pg_dumpall.c          |   1 -
 src/bin/pg_dump/pg_restore.c          |   1 -
 src/bin/pg_resetxlog/pg_resetxlog.c   |   5 +-
 src/bin/psql/common.c                 |  50 ----------
 src/bin/psql/common.h                 |   9 --
 src/bin/scripts/common.c              |  49 ----------
 src/bin/scripts/common.h              |   4 -
 src/common/Makefile                   |  64 +++++++++++++
 src/common/fe_memutils.c              | 128 ++++++++++++++++++++++++++
 src/include/common/fe_memutils.h      |  20 ++++
 src/include/postgres_fe.h             |   2 +
 src/include/utils/palloc.h            |  30 ++----
 src/port/dirmod.c                     |  74 ---------------
 src/tools/msvc/Install.pm             |   1 +
 src/tools/msvc/Mkvcbuild.pm           |  35 +++++--
 src/tools/msvc/Project.pm             |   2 +-
 59 files changed, 332 insertions(+), 684 deletions(-)
 delete mode 100644 src/bin/pg_dump/dumpmem.c
 delete mode 100644 src/bin/pg_dump/dumpmem.h
 create mode 100644 src/common/Makefile
 create mode 100644 src/common/fe_memutils.c
 create mode 100644 src/include/common/fe_memutils.h

diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c
index a666731e727..d8ed06f4202 100644
--- a/contrib/oid2name/oid2name.c
+++ b/contrib/oid2name/oid2name.c
@@ -50,9 +50,6 @@ struct options
 /* function prototypes */
 static void help(const char *progname);
 void		get_opts(int, char **, struct options *);
-void	   *pg_malloc(size_t size);
-void	   *pg_realloc(void *ptr, size_t size);
-char	   *pg_strdup(const char *str);
 void		add_one_elt(char *eltname, eary *eary);
 char	   *get_comma_elts(eary *eary);
 PGconn	   *sql_conn(struct options *);
@@ -201,53 +198,6 @@ help(const char *progname)
 		   progname, progname);
 }
 
-void *
-pg_malloc(size_t size)
-{
-	void	   *ptr;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	ptr = malloc(size);
-	if (!ptr)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return ptr;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	result = realloc(ptr, size);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-char *
-pg_strdup(const char *str)
-{
-	char	   *result = strdup(str);
-
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
 /*
  * add_one_elt
  *
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 818864346ea..a7d4a68ce3c 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/check.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
index 01c66776e44..0d9a64c967f 100644
--- a/contrib/pg_upgrade/controldata.c
+++ b/contrib/pg_upgrade/controldata.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/controldata.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
index 9c6c2773bb8..66d4846eae5 100644
--- a/contrib/pg_upgrade/dump.c
+++ b/contrib/pg_upgrade/dump.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/dump.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 44dafc36a91..af752a66d00 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/exec.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c
index f76dcb66825..62e8deb69b5 100644
--- a/contrib/pg_upgrade/file.c
+++ b/contrib/pg_upgrade/file.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/file.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
index 7bb5f915f62..b24e43eebad 100644
--- a/contrib/pg_upgrade/function.c
+++ b/contrib/pg_upgrade/function.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/function.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
index 7fd4584dff0..1905c4399d9 100644
--- a/contrib/pg_upgrade/info.c
+++ b/contrib/pg_upgrade/info.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/info.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
index d5d94c70970..aee8d3d1537 100644
--- a/contrib/pg_upgrade/option.c
+++ b/contrib/pg_upgrade/option.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/option.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "miscadmin.h"
 
diff --git a/contrib/pg_upgrade/page.c b/contrib/pg_upgrade/page.c
index d11d227fa93..fb044d1b62c 100644
--- a/contrib/pg_upgrade/page.c
+++ b/contrib/pg_upgrade/page.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/page.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/parallel.c b/contrib/pg_upgrade/parallel.c
index d157511781e..688a53112c2 100644
--- a/contrib/pg_upgrade/parallel.c
+++ b/contrib/pg_upgrade/parallel.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/parallel.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index 55155d22e28..3089a72fe52 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -35,7 +35,7 @@
 
 
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index 69b9c6030b7..c110e45c360 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -451,10 +451,6 @@ void
 prep_status(const char *fmt,...)
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
 void		check_ok(void);
-char	   *pg_strdup(const char *s);
-void	   *pg_malloc(size_t size);
-void	   *pg_realloc(void *ptr, size_t size);
-void		pg_free(void *ptr);
 const char *getErrorText(int errNum);
 unsigned int str2uint(const char *str);
 void		pg_putenv(const char *var, const char *val);
diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
index 552f2033c2f..56c702e2581 100644
--- a/contrib/pg_upgrade/relfilenode.c
+++ b/contrib/pg_upgrade/relfilenode.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/relfilenode.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index d1a3f76eff3..ed6775935bc 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/server.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/tablespace.c b/contrib/pg_upgrade/tablespace.c
index 321738dabc7..805e402d4a7 100644
--- a/contrib/pg_upgrade/tablespace.c
+++ b/contrib/pg_upgrade/tablespace.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/tablespace.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/util.c b/contrib/pg_upgrade/util.c
index c91003a46db..4e51ed72e98 100644
--- a/contrib/pg_upgrade/util.c
+++ b/contrib/pg_upgrade/util.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/util.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
@@ -213,55 +213,6 @@ get_user_info(char **user_name)
 }
 
 
-void *
-pg_malloc(size_t size)
-{
-	void	   *p;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	p = malloc(size);
-	if (p == NULL)
-		pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-	return p;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *p;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	p = realloc(ptr, size);
-	if (p == NULL)
-		pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-	return p;
-}
-
-
-void
-pg_free(void *ptr)
-{
-	if (ptr != NULL)
-		free(ptr);
-}
-
-
-char *
-pg_strdup(const char *s)
-{
-	char	   *result = strdup(s);
-
-	if (result == NULL)
-		pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-
-	return result;
-}
-
-
 /*
  * getErrorText()
  *
diff --git a/contrib/pg_upgrade/version.c b/contrib/pg_upgrade/version.c
index 80383cd1a62..5fe7ec45202 100644
--- a/contrib/pg_upgrade/version.c
+++ b/contrib/pg_upgrade/version.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/version.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/version_old_8_3.c b/contrib/pg_upgrade/version_old_8_3.c
index a224be1ab8f..4551d68ba48 100644
--- a/contrib/pg_upgrade/version_old_8_3.c
+++ b/contrib/pg_upgrade/version_old_8_3.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/version_old_8_3.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index 11c006209fa..d5f8f73190d 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -320,59 +320,6 @@ static char *select_only = {
 static void setalarm(int seconds);
 static void *threadRun(void *arg);
 
-
-/*
- * routines to check mem allocations and fail noisily.
- */
-static void *
-pg_malloc(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-static void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	result = realloc(ptr, size);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-static char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-
 static void
 usage(void)
 {
diff --git a/src/Makefile b/src/Makefile
index a0460342e8a..e859826dc4f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -13,6 +13,7 @@ top_builddir = ..
 include Makefile.global
 
 SUBDIRS = \
+	common \
 	port \
 	timezone \
 	backend \
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index ecfb80147f5..1077e0b98ab 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -243,14 +243,15 @@ LD = @LD@
 with_gnu_ld = @with_gnu_ld@
 ld_R_works = @ld_R_works@
 
-# We want -L for libpgport.a to be first in LDFLAGS.  We also need LDFLAGS
-# to be a "recursively expanded" variable, else adjustments to rpathdir
-# don't work right.  So we must NOT do LDFLAGS := something, meaning this has
-# to be done first and elsewhere we must only do LDFLAGS += something.
+# We want -L for libpgport.a and libpgcommon.a to be first in LDFLAGS.  We
+# also need LDFLAGS to be a "recursively expanded" variable, else adjustments
+# to rpathdir don't work right.  So we must NOT do LDFLAGS := something,
+# meaning this has to be done first and elsewhere we must only do LDFLAGS +=
+# something.
 ifdef PGXS
   LDFLAGS = -L$(libdir)
 else
-  LDFLAGS = -L$(top_builddir)/src/port
+  LDFLAGS = -L$(top_builddir)/src/port -L$(top_builddir)/src/common
 endif
 LDFLAGS += @LDFLAGS@
 
@@ -400,16 +401,17 @@ endif
 libpq = -L$(libpq_builddir) -lpq
 
 # This macro is for use by client executables (not libraries) that use libpq.
-# We force clients to pull symbols from the non-shared library libpgport
-# rather than pulling some libpgport symbols from libpq just because
-# libpq uses those functions too.  This makes applications less
+# We force clients to pull symbols from the non-shared libraries libpgport
+# and libpgcommon rather than pulling some libpgport symbols from libpq just
+# because libpq uses those functions too.  This makes applications less
 # dependent on changes in libpq's usage of pgport.  To do this we link to
 # pgport before libpq.  This does cause duplicate -lpgport's to appear
 # on client link lines.
 ifdef PGXS
-libpq_pgport = -L$(libdir) -lpgport $(libpq)
+libpq_pgport = -L$(libdir) -lpgport -lpgcommon $(libpq)
 else
-libpq_pgport = -L$(top_builddir)/src/port -lpgport $(libpq)
+libpq_pgport = -L$(top_builddir)/src/port -lpgport \
+			   -L$(top_builddir)/src/common -lpgcommon $(libpq)
 endif
 
 
@@ -418,6 +420,7 @@ submake-libpq:
 
 submake-libpgport:
 	$(MAKE) -C $(top_builddir)/src/port all
+	$(MAKE) -C $(top_builddir)/src/common all
 
 .PHONY: submake-libpq submake-libpgport
 
@@ -496,7 +499,7 @@ endif
 
 LIBOBJS = @LIBOBJS@
 
-LIBS := -lpgport $(LIBS)
+LIBS := -lpgport -lpgcommon $(LIBS)
 
 # to make ws2_32.lib the last library, and always link with shfolder,
 # so SHGetFolderName isn't picked up from shell32.dll
diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c
index 017f862dc05..391359cdd92 100644
--- a/src/backend/storage/file/copydir.c
+++ b/src/backend/storage/file/copydir.c
@@ -26,17 +26,6 @@
 #include "storage/fd.h"
 #include "miscadmin.h"
 
-/*
- *	On Windows, call non-macro versions of palloc; we can't reference
- *	CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
- */
-#if defined(WIN32) || defined(__CYGWIN__)
-#undef palloc
-#undef pstrdup
-#define palloc(sz)		pgport_palloc(sz)
-#define pstrdup(str)	pgport_pstrdup(str)
-#endif
-
 
 static void fsync_fname(char *fname, bool isdir);
 
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index d71f206dee4..8dd3cf48896 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -634,6 +634,42 @@ MemoryContextAllocZeroAligned(MemoryContext context, Size size)
 	return ret;
 }
 
+void *
+palloc(Size size)
+{
+	/* duplicates MemoryContextAlloc to avoid increased overhead */
+	AssertArg(MemoryContextIsValid(CurrentMemoryContext));
+
+	if (!AllocSizeIsValid(size))
+		elog(ERROR, "invalid memory alloc request size %lu",
+			 (unsigned long) size);
+
+	CurrentMemoryContext->isReset = false;
+
+	return (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
+}
+
+void *
+palloc0(Size size)
+{
+	/* duplicates MemoryContextAllocZero to avoid increased overhead */
+	void	   *ret;
+
+	AssertArg(MemoryContextIsValid(CurrentMemoryContext));
+
+	if (!AllocSizeIsValid(size))
+		elog(ERROR, "invalid memory alloc request size %lu",
+			 (unsigned long) size);
+
+	CurrentMemoryContext->isReset = false;
+
+	ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
+
+	MemSetAligned(ret, 0, size);
+
+	return ret;
+}
+
 /*
  * pfree
  *		Release an allocated chunk.
@@ -715,6 +751,12 @@ MemoryContextStrdup(MemoryContext context, const char *string)
 	return nstr;
 }
 
+char *
+pstrdup(const char *in)
+{
+	return MemoryContextStrdup(CurrentMemoryContext, in);
+}
+
 /*
  * pnstrdup
  *		Like pstrdup(), but append null byte to a
@@ -729,39 +771,3 @@ pnstrdup(const char *in, Size len)
 	out[len] = '\0';
 	return out;
 }
-
-
-#if defined(WIN32) || defined(__CYGWIN__)
-/*
- *	Memory support routines for libpgport on Win32
- *
- *	Win32 can't load a library that PGDLLIMPORTs a variable
- *	if the link object files also PGDLLIMPORT the same variable.
- *	For this reason, libpgport can't reference CurrentMemoryContext
- *	in the palloc macro calls.
- *
- *	To fix this, we create several functions here that allow us to
- *	manage memory without doing the inline in libpgport.
- */
-void *
-pgport_palloc(Size sz)
-{
-	return palloc(sz);
-}
-
-
-char *
-pgport_pstrdup(const char *str)
-{
-	return pstrdup(str);
-}
-
-
-/* Doesn't reference a PGDLLIMPORT variable, but here for completeness. */
-void
-pgport_pfree(void *pointer)
-{
-	pfree(pointer);
-}
-
-#endif
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index b75d9768561..2ea3f6ed02b 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -200,8 +200,6 @@ const char *subdirs[] = {
 static char bin_path[MAXPGPATH];
 static char backend_exec[MAXPGPATH];
 
-static void *pg_malloc(size_t size);
-static char *pg_strdup(const char *s);
 static char **replace_token(char **lines,
 			  const char *token, const char *replacement);
 
@@ -317,43 +315,6 @@ do { \
 #define DIR_SEP "\\"
 #endif
 
-/*
- * routines to check mem allocations and fail noisily.
- *
- * Note that we can't call exit_nicely() on a memory failure, as it calls
- * rmtree() which needs memory allocation. So we just exit with a bang.
- */
-static void *
-pg_malloc(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
-static char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
 static char *
 escape_quotes(const char *src)
 {
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 71abbfa9de9..8a43c4bad1d 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -25,43 +25,6 @@ int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
 
-/*
- * strdup() and malloc() replacements that print an error and exit
- * if something goes wrong. Can never return NULL.
- */
-char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	MemSet(result, 0, size);
-	return result;
-}
-
-
 /*
  * Connect to the server. Returns a valid PGconn pointer if connected,
  * or NULL on non-permanent error. On permanent error, the function will
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index fdf36418616..4f5ff914e23 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -15,8 +15,4 @@ extern PGconn *conn;
 	exit(code);									\
 	}
 
-
-extern char *pg_strdup(const char *s);
-extern void *pg_malloc0(size_t size);
-
 extern PGconn *GetConnection(void);
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index e086b1244cc..04de977e3f9 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -118,8 +118,6 @@ write_stderr(const char *fmt,...)
 /* This extension allows gcc to check the format string for consistency with
    the supplied arguments. */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
-static void *pg_malloc(size_t size);
-static char *pg_strdup(const char *s);
 static void do_advice(void);
 static void do_help(void);
 static void set_mode(char *modeopt);
@@ -225,42 +223,6 @@ write_stderr(const char *fmt,...)
 	va_end(ap);
 }
 
-/*
- * routines to check memory allocations and fail noisily.
- */
-
-static void *
-pg_malloc(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		write_stderr(_("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
-
-static char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		write_stderr(_("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
 /*
  * Given an already-localized string, print it to stdout unless the
  * user has specified that no messages should be printed.
diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile
index 57aea6f8130..a6ab39d3478 100644
--- a/src/bin/pg_dump/Makefile
+++ b/src/bin/pg_dump/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=	pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
 	pg_backup_null.o pg_backup_tar.o \
-	pg_backup_directory.o dumpmem.o dumputils.o compress_io.o $(WIN32RES)
+	pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
 
 KEYWRDOBJS = keywords.o kwlookup.o
 
@@ -35,8 +35,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq
 pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-pg_dumpall: pg_dumpall.o dumputils.o dumpmem.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
-	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o dumpmem.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X)
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 706b9a75e3b..01739ab717c 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -18,8 +18,6 @@
 #include <ctype.h>
 
 #include "catalog/pg_class.h"
-#include "dumpmem.h"
-#include "dumputils.h"
 
 
 /*
diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c
index aac991bd10f..768b923ae5f 100644
--- a/src/bin/pg_dump/compress_io.c
+++ b/src/bin/pg_dump/compress_io.c
@@ -53,7 +53,6 @@
  */
 
 #include "compress_io.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 /*----------------------
diff --git a/src/bin/pg_dump/dumpmem.c b/src/bin/pg_dump/dumpmem.c
deleted file mode 100644
index d96655e7f4e..00000000000
--- a/src/bin/pg_dump/dumpmem.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dumpmem.c
- *	  Memory allocation routines used by pg_dump, pg_dumpall, and pg_restore
- *
- * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  src/bin/pg_dump/dumpmem.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include "dumputils.h"
-#include "dumpmem.h"
-
-
-/*
- * Safer versions of some standard C library functions. If an
- * out-of-memory condition occurs, these functions will bail out via exit();
- *therefore, their return value is guaranteed to be non-NULL.
- */
-
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-		exit_horribly(NULL, "cannot duplicate null pointer\n");
-	tmp = strdup(string);
-	if (!tmp)
-		exit_horribly(NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	tmp = malloc(size);
-	if (!tmp)
-		exit_horribly(NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *tmp;
-
-	tmp = pg_malloc(size);
-	MemSet(tmp, 0, size);
-	return tmp;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	tmp = realloc(ptr, size);
-	if (!tmp)
-		exit_horribly(NULL, "out of memory\n");
-	return tmp;
-}
diff --git a/src/bin/pg_dump/dumpmem.h b/src/bin/pg_dump/dumpmem.h
deleted file mode 100644
index 0a4ab1bed37..00000000000
--- a/src/bin/pg_dump/dumpmem.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dumpmem.h
- *	  Memory allocation routines used by pg_dump, pg_dumpall, and pg_restore
- *
- * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/bin/pg_dump/dumpmem.h
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef DUMPMEM_H
-#define DUMPMEM_H
-
-extern char *pg_strdup(const char *string);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-extern void *pg_realloc(void *ptr, size_t size);
-
-#endif   /* DUMPMEM_H */
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 7ca0c60f3e5..0a09882f5dc 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -17,7 +17,6 @@
 #include <ctype.h>
 
 #include "dumputils.h"
-#include "dumpmem.h"
 
 #include "parser/keywords.h"
 
diff --git a/src/bin/pg_dump/nls.mk b/src/bin/pg_dump/nls.mk
index 8bf6ec9b5e8..84486003d08 100644
--- a/src/bin/pg_dump/nls.mk
+++ b/src/bin/pg_dump/nls.mk
@@ -3,7 +3,7 @@ CATALOG_NAME     = pg_dump
 AVAIL_LANGUAGES  = de es fr it ja ko pt_BR sv tr zh_CN zh_TW
 GETTEXT_FILES    = pg_backup_archiver.c pg_backup_db.c pg_backup_custom.c \
                    pg_backup_null.c pg_backup_tar.c \
-                   pg_backup_directory.c dumpmem.c dumputils.c compress_io.c \
+                   pg_backup_directory.c dumputils.c compress_io.c \
                    pg_dump.c common.c pg_dump_sort.c \
                    pg_restore.c pg_dumpall.c \
                    ../../port/exec.c
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index a810efd3bb9..1c663cd14f8 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -21,7 +21,6 @@
  */
 
 #include "pg_backup_db.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <ctype.h>
diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
index c9adc6f82fe..7081598baaa 100644
--- a/src/bin/pg_dump/pg_backup_custom.c
+++ b/src/bin/pg_dump/pg_backup_custom.c
@@ -26,7 +26,6 @@
 
 #include "compress_io.h"
 #include "dumputils.h"
-#include "dumpmem.h"
 
 /*--------
  * Routines in the format interface
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index c295fc5ddd2..21c203e8e7b 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -11,7 +11,6 @@
  */
 
 #include "pg_backup_db.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <unistd.h>
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index 2dcf7be80da..5b71ebaeebc 100644
--- a/src/bin/pg_dump/pg_backup_directory.c
+++ b/src/bin/pg_dump/pg_backup_directory.c
@@ -34,7 +34,6 @@
  */
 
 #include "compress_io.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <dirent.h>
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index ba1e461af45..6ac81982b8d 100644
--- a/src/bin/pg_dump/pg_backup_null.c
+++ b/src/bin/pg_dump/pg_backup_null.c
@@ -23,7 +23,6 @@
  */
 
 #include "pg_backup_archiver.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <unistd.h>				/* for dup */
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index d090612d0f3..03ae4f82bce 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -31,7 +31,6 @@
 #include "pg_backup.h"
 #include "pg_backup_archiver.h"
 #include "pg_backup_tar.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 #include "pgtar.h"
 
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 9f1ef32b158..43d571ca5bb 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -59,7 +59,6 @@
 
 #include "pg_backup_archiver.h"
 #include "pg_backup_db.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 extern char *optarg;
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index f828a45800c..955c231b1a8 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -15,7 +15,6 @@
  */
 #include "pg_backup_archiver.h"
 #include "dumputils.h"
-#include "dumpmem.h"
 
 /* translator: this is a module name */
 static const char *modulename = gettext_noop("sorter");
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 0662bc20695..9afbab4b07b 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -25,7 +25,6 @@
 #include "getopt_long.h"
 
 #include "dumputils.h"
-#include "dumpmem.h"
 #include "pg_backup.h"
 
 /* version string we expect back from pg_dump */
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index 45b8b587e41..5dbe98f7145 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -41,7 +41,6 @@
 
 #include "pg_backup_archiver.h"
 
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <ctype.h>
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 317d8606a0b..f075b6e9323 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -54,6 +54,7 @@
 #include "access/xlog_internal.h"
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
+#include "common/fe_memutils.h"
 
 extern int	optind;
 extern char *optarg;
@@ -420,7 +421,7 @@ ReadControlFile(void)
 	}
 
 	/* Use malloc to ensure we have a maxaligned buffer */
-	buffer = (char *) malloc(PG_CONTROL_SIZE);
+	buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
 
 	len = read(fd, buffer, PG_CONTROL_SIZE);
 	if (len < 0)
@@ -942,7 +943,7 @@ WriteEmptyXLOG(void)
 	int			nbytes;
 
 	/* Use malloc() to ensure buffer is MAXALIGNED */
-	buffer = (char *) malloc(XLOG_BLCKSZ);
+	buffer = (char *) pg_malloc(XLOG_BLCKSZ);
 	page = (XLogPageHeader) buffer;
 	memset(buffer, 0, XLOG_BLCKSZ);
 
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index a8aa1a2df1b..dd183cacc14 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -32,56 +32,6 @@ static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
 static bool command_no_begin(const char *query);
 static bool is_select_command(const char *query);
 
-/*
- * "Safe" wrapper around strdup()
- */
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-	{
-		psql_error("%s: pg_strdup: cannot duplicate null pointer (internal error)\n",
-				   pset.progname);
-		exit(EXIT_FAILURE);
-	}
-	tmp = strdup(string);
-	if (!tmp)
-	{
-		psql_error("out of memory\n");
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	tmp = malloc(size);
-	if (!tmp)
-	{
-		psql_error("out of memory\n");
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *tmp;
-
-	tmp = pg_malloc(size);
-	MemSet(tmp, 0, size);
-	return tmp;
-}
-
 /*
  * setQFout
  * -- handler for -o command line option and \o command
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index f9f3b1f3c84..d8bb0930b41 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -14,15 +14,6 @@
 
 #define atooid(x)  ((Oid) strtoul((x), NULL, 10))
 
-/*
- * Safer versions of some standard C library functions. If an
- * out-of-memory condition occurs, these functions will bail out
- * safely; therefore, their return value is guaranteed to be non-NULL.
- */
-extern char *pg_strdup(const char *string);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-
 extern bool setQFout(const char *fname);
 
 extern void
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index c7cc04aea4b..03193b6fcdc 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -277,55 +277,6 @@ executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
 	return r;
 }
 
-/*
- * "Safe" wrapper around strdup().	Pulled from psql/common.c
- */
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-	{
-		fprintf(stderr, _("pg_strdup: cannot duplicate null pointer (internal error)\n"));
-		exit(EXIT_FAILURE);
-	}
-	tmp = strdup(string);
-	if (!tmp)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	tmp = malloc(size);
-	if (!tmp)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *tmp;
-
-	tmp = pg_malloc(size);
-	MemSet(tmp, 0, size);
-	return tmp;
-}
-
 /*
  * Check yes/no answer in a localized way.	1=yes, 0=no, -1=neither.
  */
diff --git a/src/bin/scripts/common.h b/src/bin/scripts/common.h
index a174da79b05..6cf490f7484 100644
--- a/src/bin/scripts/common.h
+++ b/src/bin/scripts/common.h
@@ -50,8 +50,4 @@ extern bool yesno_prompt(const char *question);
 
 extern void setup_cancel_handler(void);
 
-extern char *pg_strdup(const char *string);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-
 #endif   /* COMMON_H */
diff --git a/src/common/Makefile b/src/common/Makefile
new file mode 100644
index 00000000000..3aa6e70322f
--- /dev/null
+++ b/src/common/Makefile
@@ -0,0 +1,64 @@
+#-------------------------------------------------------------------------
+#
+# Makefile
+#    Makefile for src/common
+#
+# This makefile generates two outputs:
+#
+#	libpgcommon.a - contains object files with FRONTEND defined,
+#		for use by client application and libraries
+#
+#	libpgcommon_srv.a - contains object files without FRONTEND defined,
+#		for use only by the backend binaries
+#
+# IDENTIFICATION
+#    src/common/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/common
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
+LIBS += $(PTHREAD_LIBS)
+
+OBJS_COMMON =
+
+OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o
+
+OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o)
+
+all: libpgcommon.a libpgcommon_srv.a
+
+# libpgcommon is needed by some contrib
+install: all installdirs
+	$(INSTALL_STLIB) libpgcommon.a '$(DESTDIR)$(libdir)/libpgcommon.a'
+
+installdirs:
+	$(MKDIR_P) '$(DESTDIR)$(libdir)'
+
+uninstall:
+	rm -f '$(DESTDIR)$(libdir)/libpgcommon.a'
+
+libpgcommon.a: $(OBJS_FRONTEND)
+	$(AR) $(AROPT) $@ $^
+
+#
+# Server versions of object files
+#
+
+libpgcommon_srv.a: $(OBJS_SRV)
+	$(AR) $(AROPT) $@ $^
+
+# Because this uses its own compilation rule, it doesn't use the
+# dependency tracking logic from Makefile.global.  To make sure that
+# dependency tracking works anyway for the *_srv.o files, depend on
+# their *.o siblings as well, which do have proper dependencies.  It's
+# a hack that might fail someday if there is a *_srv.o without a
+# corresponding *.o, but it works for now.
+%_srv.o: %.c %.o
+	$(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@
+
+clean distclean maintainer-clean:
+	rm -f libpgcommon.a libpgcommon_srv.a $(OBJS_FRONTEND) $(OBJS_SRV)
diff --git a/src/common/fe_memutils.c b/src/common/fe_memutils.c
new file mode 100644
index 00000000000..7d4d99eefd5
--- /dev/null
+++ b/src/common/fe_memutils.c
@@ -0,0 +1,128 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe_memutils.c
+ *	  memory management support for frontend code
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/common/fe_memutils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#error "This file is not expected to be compiled for backend code"
+#endif
+
+#include "postgres_fe.h"
+
+void *
+pg_malloc(size_t size)
+{
+	void	   *tmp;
+
+	/* Avoid unportable behavior of malloc(0) */
+	if (size == 0)
+		size = 1;
+	tmp = malloc(size);
+	if (!tmp)
+	{
+		fprintf(stderr, _("out of memory\n"));
+		exit(EXIT_FAILURE);
+	}
+	return tmp;
+}
+
+void *
+pg_malloc0(size_t size)
+{
+	void	   *tmp;
+
+	tmp = pg_malloc(size);
+	MemSet(tmp, 0, size);
+	return tmp;
+}
+
+void *
+pg_realloc(void *ptr, size_t size)
+{
+   void       *tmp;
+
+   /* Avoid unportable behavior of realloc(NULL, 0) */
+   if (ptr == NULL && size == 0)
+       size = 1;
+   tmp = realloc(ptr, size);
+   if (!tmp)
+   {
+		fprintf(stderr, _("out of memory\n"));
+		exit(EXIT_FAILURE);
+   }
+   return tmp;
+}
+
+/*
+ * "Safe" wrapper around strdup().
+ */
+char *
+pg_strdup(const char *string)
+{
+	char	   *tmp;
+
+	if (!string)
+	{
+		fprintf(stderr,
+				_("cannot duplicate null pointer (internal error)\n"));
+		exit(EXIT_FAILURE);
+	}
+	tmp = strdup(string);
+	if (!tmp)
+	{
+		fprintf(stderr, _("out of memory\n"));
+		exit(EXIT_FAILURE);
+	}
+	return tmp;
+}
+
+void
+pg_free(void *ptr)
+{
+	if (ptr != NULL)
+		free(ptr);
+}
+
+/*
+ * Frontend emulation of backend memory management functions.  Useful for
+ * programs that compile backend files.
+ */
+void *
+palloc(Size size)
+{
+	return pg_malloc(size);
+}
+
+void *
+palloc0(Size size)
+{
+	return pg_malloc0(size);
+}
+
+void
+pfree(void *pointer)
+{
+	pg_free(pointer);
+}
+
+char *
+pstrdup(const char *string)
+{
+	return pg_strdup(string);
+}
+
+void *
+repalloc(void *pointer, Size size)
+{
+	return pg_realloc(pointer, size);
+}
diff --git a/src/include/common/fe_memutils.h b/src/include/common/fe_memutils.h
new file mode 100644
index 00000000000..cefa7ecedc8
--- /dev/null
+++ b/src/include/common/fe_memutils.h
@@ -0,0 +1,20 @@
+/*
+ *	fe_memutils.h
+ *		memory management support for frontend code
+ *
+ *	Copyright (c) 2003-2013, PostgreSQL Global Development Group
+ *
+ *	src/include/common/fe_memutils.h
+ */
+#ifndef FE_MEMUTILS_H
+#define FE_MEMUTILS_H
+
+extern char *pg_strdup(const char *string);
+extern void *pg_malloc(size_t size);
+extern void *pg_malloc0(size_t size);
+extern void *pg_realloc(void *pointer, size_t size);
+extern void  pg_free(void *pointer);
+
+#include "utils/palloc.h"
+
+#endif   /* FE_MEMUTILS_H */
diff --git a/src/include/postgres_fe.h b/src/include/postgres_fe.h
index 0f35eccc748..6798b4c05ce 100644
--- a/src/include/postgres_fe.h
+++ b/src/include/postgres_fe.h
@@ -24,4 +24,6 @@
 
 #include "c.h"
 
+#include "common/fe_memutils.h"
+
 #endif   /* POSTGRES_FE_H */
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index d86558e417f..7fc7ccc3b52 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -28,6 +28,8 @@
 #ifndef PALLOC_H
 #define PALLOC_H
 
+#ifndef FRONTEND
+
 /*
  * Type MemoryContextData is declared in nodes/memnodes.h.	Most users
  * of memory allocation should just treat it as an abstract type, so we
@@ -49,10 +51,6 @@ extern void *MemoryContextAlloc(MemoryContext context, Size size);
 extern void *MemoryContextAllocZero(MemoryContext context, Size size);
 extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
 
-#define palloc(sz)	MemoryContextAlloc(CurrentMemoryContext, (sz))
-
-#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz))
-
 /*
  * The result of palloc() is always word-aligned, so we can skip testing
  * alignment of the pointer when deciding which MemSet variant to use.
@@ -66,20 +64,11 @@ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
 		MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
 		MemoryContextAllocZero(CurrentMemoryContext, sz) )
 
-extern void pfree(void *pointer);
-
-extern void *repalloc(void *pointer, Size size);
-
 /*
  * MemoryContextSwitchTo can't be a macro in standard C compilers.
  * But we can make it an inline function if the compiler supports it.
  * See STATIC_IF_INLINE in c.h.
- *
- * This file has to be includable by some non-backend code such as
- * pg_resetxlog, so don't expose the CurrentMemoryContext reference
- * if FRONTEND is defined.
  */
-#ifndef FRONTEND
 
 #ifndef PG_USE_INLINE
 extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
@@ -94,22 +83,19 @@ MemoryContextSwitchTo(MemoryContext context)
 	return old;
 }
 #endif   /* PG_USE_INLINE || MCXT_INCLUDE_DEFINITIONS */
-#endif   /* !FRONTEND */
 
 /*
  * These are like standard strdup() except the copied string is
  * allocated in a context, not with malloc().
  */
 extern char *MemoryContextStrdup(MemoryContext context, const char *string);
+#endif /* !FRONTEND */
 
-#define pstrdup(str)  MemoryContextStrdup(CurrentMemoryContext, (str))
-
+extern char *pstrdup(const char *in);
 extern char *pnstrdup(const char *in, Size len);
-
-#if defined(WIN32) || defined(__CYGWIN__)
-extern void *pgport_palloc(Size sz);
-extern char *pgport_pstrdup(const char *str);
-extern void pgport_pfree(void *pointer);
-#endif
+extern void *palloc(Size size);
+extern void *palloc0(Size size);
+extern void pfree(void *pointer);
+extern void *repalloc(void *pointer, Size size);
 
 #endif   /* PALLOC_H */
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index e7ff1f0d271..5dd0983a2de 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -40,80 +40,6 @@
 #endif
 #endif
 
-
-#ifndef FRONTEND
-
-/*
- *	On Windows, call non-macro versions of palloc; we can't reference
- *	CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
- */
-#if defined(WIN32) || defined(__CYGWIN__)
-#undef palloc
-#undef pstrdup
-#define palloc(sz)		pgport_palloc(sz)
-#define pstrdup(str)	pgport_pstrdup(str)
-#endif
-#else							/* FRONTEND */
-
-/*
- *	In frontend, fake palloc behavior with these
- */
-#undef palloc
-#undef pstrdup
-#define palloc(sz)		fe_palloc(sz)
-#define pstrdup(str)	fe_pstrdup(str)
-#define repalloc(pointer,sz)	fe_repalloc(pointer,sz)
-#define pfree(pointer)	free(pointer)
-
-static void *
-fe_palloc(Size size)
-{
-	void	   *res;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	res = malloc(size);
-	if (res == NULL)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(1);
-	}
-	return res;
-}
-
-static char *
-fe_pstrdup(const char *string)
-{
-	char	   *res;
-
-	if ((res = strdup(string)) == NULL)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(1);
-	}
-	return res;
-}
-
-static void *
-fe_repalloc(void *pointer, Size size)
-{
-	void	   *res;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (pointer == NULL && size == 0)
-		size = 1;
-	res = realloc(pointer, size);
-	if (res == NULL)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(1);
-	}
-	return res;
-}
-#endif   /* FRONTEND */
-
-
 #if defined(WIN32) || defined(__CYGWIN__)
 
 /*
diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm
index e92354e6213..0d0c46e18bb 100644
--- a/src/tools/msvc/Install.pm
+++ b/src/tools/msvc/Install.pm
@@ -86,6 +86,7 @@ sub Install
 		'Import libraries',         $target . '/lib/',
 		"$conf\\",                  "postgres\\postgres.lib",
 		"libpq\\libpq.lib",         "libecpg\\libecpg.lib",
+		"libpgcommon\\libpgcommon.lib",
 		"libpgport\\libpgport.lib", "libpgtypes\\libpgtypes.lib",
 		"libecpg_compat\\libecpg_compat.lib");
 	CopySetOfFiles(
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index d587365437c..75e7e4173f8 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -24,6 +24,7 @@ our (@ISA, @EXPORT_OK);
 
 my $solution;
 my $libpgport;
+my $libpgcommon;
 my $postgres;
 my $libpq;
 
@@ -35,6 +36,11 @@ my @contrib_uselibpgport = (
 	'pg_standby',    'pg_archivecleanup',
 	'pg_test_fsync', 'pg_test_timing',
 	'pg_upgrade',    'vacuumlo');
+my @contrib_uselibpgcommon = (
+	'oid2name',      'pgbench',
+	'pg_standby',    'pg_archivecleanup',
+	'pg_test_fsync', 'pg_test_timing',
+	'pg_upgrade',    'vacuumlo');
 my $contrib_extralibs = { 'pgbench' => ['wsock32.lib'] };
 my $contrib_extraincludes =
   { 'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend'] };
@@ -63,10 +69,19 @@ sub mkvcbuild
 	  sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c rint.c win32env.c
 	  win32error.c win32setlocale.c);
 
+	our @pgcommonfiles = qw(
+		fe_memutils.c);
+
+	our @pgcommonbkndfiles = qw();
+
 	$libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
 	$libpgport->AddDefine('FRONTEND');
 	$libpgport->AddFiles('src\port', @pgportfiles);
 
+	$libpgcommon = $solution->AddProject('libpgcommon', 'lib', 'misc');
+	$libpgcommon->AddDefine('FRONTEND');
+	$libpgcommon->AddFiles('src\common', @pgcommonfiles);
+
 	$postgres = $solution->AddProject('postgres', 'exe', '', 'src\backend');
 	$postgres->AddIncludeDir('src\backend');
 	$postgres->AddDir('src\backend\port\win32');
@@ -81,6 +96,7 @@ sub mkvcbuild
 	$postgres->ReplaceFile('src\backend\port\pg_latch.c',
 		'src\backend\port\win32_latch.c');
 	$postgres->AddFiles('src\port', @pgportfiles);
+	$postgres->AddFiles('src\common', @pgcommonbkndfiles);
 	$postgres->AddDir('src\timezone');
 	$postgres->AddFiles('src\backend\parser', 'scan.l', 'gram.y');
 	$postgres->AddFiles('src\backend\bootstrap', 'bootscanner.l',
@@ -297,7 +313,7 @@ sub mkvcbuild
 	$ecpg->AddDefine('MINOR_VERSION=9');
 	$ecpg->AddDefine('PATCHLEVEL=0');
 	$ecpg->AddDefine('ECPG_COMPILE');
-	$ecpg->AddReference($libpgport);
+	$ecpg->AddReference($libpgport, $libpgcommon);
 
 	my $pgregress_ecpg =
 	  $solution->AddProject('pg_regress_ecpg', 'exe', 'misc');
@@ -307,7 +323,7 @@ sub mkvcbuild
 	$pgregress_ecpg->AddIncludeDir('src\test\regress');
 	$pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
 	$pgregress_ecpg->AddDefine('FRONTEND');
-	$pgregress_ecpg->AddReference($libpgport);
+	$pgregress_ecpg->AddReference($libpgport, $libpgcommon);
 
 	my $isolation_tester =
 	  $solution->AddProject('isolationtester', 'exe', 'misc');
@@ -332,7 +348,7 @@ sub mkvcbuild
 	$pgregress_isolation->AddIncludeDir('src\test\regress');
 	$pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
 	$pgregress_isolation->AddDefine('FRONTEND');
-	$pgregress_isolation->AddReference($libpgport);
+	$pgregress_isolation->AddReference($libpgport, $libpgcommon);
 
 	# src/bin
 	my $initdb = AddSimpleFrontend('initdb');
@@ -393,7 +409,6 @@ sub mkvcbuild
 	$pgdumpall->AddIncludeDir('src\backend');
 	$pgdumpall->AddFile('src\bin\pg_dump\pg_dumpall.c');
 	$pgdumpall->AddFile('src\bin\pg_dump\dumputils.c');
-	$pgdumpall->AddFile('src\bin\pg_dump\dumpmem.c');
 	$pgdumpall->AddFile('src\bin\pg_dump\keywords.c');
 	$pgdumpall->AddFile('src\backend\parser\kwlookup.c');
 
@@ -407,7 +422,7 @@ sub mkvcbuild
 	my $zic = $solution->AddProject('zic', 'exe', 'utils');
 	$zic->AddFiles('src\timezone', 'zic.c', 'ialloc.c', 'scheck.c',
 		'localtime.c');
-	$zic->AddReference($libpgport);
+	$zic->AddReference($libpgport, $libpgcommon);
 
 	if ($solution->{options}->{xml})
 	{
@@ -547,7 +562,7 @@ sub mkvcbuild
 		$proj->AddIncludeDir('src\interfaces\libpq');
 		$proj->AddIncludeDir('src\bin\pg_dump');
 		$proj->AddIncludeDir('src\bin\psql');
-		$proj->AddReference($libpq, $libpgport);
+		$proj->AddReference($libpq, $libpgport, $libpgcommon);
 		$proj->AddResourceFile('src\bin\scripts', 'PostgreSQL Utility');
 	}
 
@@ -561,7 +576,7 @@ sub mkvcbuild
 	$pgregress->AddFile('src\test\regress\pg_regress_main.c');
 	$pgregress->AddIncludeDir('src\port');
 	$pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
-	$pgregress->AddReference($libpgport);
+	$pgregress->AddReference($libpgport, $libpgcommon);
 
 	$solution->Save();
 	return $solution->{vcver};
@@ -579,7 +594,7 @@ sub AddSimpleFrontend
 
 	my $p = $solution->AddProject($n, 'exe', 'bin');
 	$p->AddDir('src\bin\\' . $n);
-	$p->AddReference($libpgport);
+	$p->AddReference($libpgport, $libpgcommon);
 	if ($uselibpq)
 	{
 		$p->AddIncludeDir('src\interfaces\libpq');
@@ -730,6 +745,10 @@ sub AdjustContribProj
 	{
 		$proj->AddReference($libpgport);
 	}
+	if (grep { /^$n$/ } @contrib_uselibpgcommon)
+	{
+		$proj->AddReference($libpgcommon);
+	}
 	if ($contrib_extralibs->{$n})
 	{
 		foreach my $l (@{ $contrib_extralibs->{$n} })
diff --git a/src/tools/msvc/Project.pm b/src/tools/msvc/Project.pm
index 0a47e40942f..4182871e88e 100644
--- a/src/tools/msvc/Project.pm
+++ b/src/tools/msvc/Project.pm
@@ -225,7 +225,7 @@ sub AddDir
 
 				if ($filter eq "LIBOBJS")
 				{
-					if (grep(/$p/, @main::pgportfiles) == 1)
+					if (grep(/$p/, @main::pgportfiles, @main::pgcommonfiles) == 1)
 					{
 						$p =~ s/\.c/\.o/;
 						$matches .= $p . " ";
-- 
GitLab