diff --git a/contrib/Makefile b/contrib/Makefile
index 25263c0..9739013 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -17,6 +17,7 @@ SUBDIRS = \
 		dblink		\
 		dict_int	\
 		dict_xsyn	\
+		dsm_demo	\
 		earthdistance	\
 		file_fdw	\
 		fuzzystrmatch	\
diff --git a/contrib/dsm_demo/Makefile b/contrib/dsm_demo/Makefile
new file mode 100644
index 0000000..dd9ea92
--- /dev/null
+++ b/contrib/dsm_demo/Makefile
@@ -0,0 +1,17 @@
+# contrib/dsm_demo/Makefile
+
+MODULES = dsm_demo
+
+EXTENSION = dsm_demo
+DATA = dsm_demo--1.0.sql
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/dsm_demo
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/dsm_demo/dsm_demo--1.0.sql b/contrib/dsm_demo/dsm_demo--1.0.sql
new file mode 100644
index 0000000..c0f1a99
--- /dev/null
+++ b/contrib/dsm_demo/dsm_demo--1.0.sql
@@ -0,0 +1,19 @@
+/* contrib/dsm_demo/dsm_demo--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION dsm_demo" to load this file. \quit
+
+CREATE FUNCTION dsm_demo_create(pg_catalog.text, pg_catalog.int4 default 0)
+RETURNS pg_catalog.int8 STRICT
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE FUNCTION dsm_demo_read(pg_catalog.int8)
+RETURNS pg_catalog.text STRICT
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE FUNCTION dsm_demo_unpin_segment(pg_catalog.int8)
+RETURNS pg_catalog.bool STRICT
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
\ No newline at end of file
diff --git a/contrib/dsm_demo/dsm_demo.c b/contrib/dsm_demo/dsm_demo.c
new file mode 100644
index 0000000..7b10972
--- /dev/null
+++ b/contrib/dsm_demo/dsm_demo.c
@@ -0,0 +1,150 @@
+/* -------------------------------------------------------------------------
+ *
+ * dsm_demo.c
+ *		Dynamic shared memory demonstration.
+ *
+ * Copyright (C) 2013, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/dsm_demo/dsm_demo.c
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "storage/dsm.h"
+#include "fmgr.h"
+
+PG_MODULE_MAGIC;
+
+void		_PG_init(void);
+Datum		dsm_demo_create(PG_FUNCTION_ARGS);
+Datum		dsm_demo_read(PG_FUNCTION_ARGS);
+Datum		dsm_demo_unpin_segment(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(dsm_demo_create);
+PG_FUNCTION_INFO_V1(dsm_demo_read);
+PG_FUNCTION_INFO_V1(dsm_demo_unpin_segment);
+
+#define		DSM_DEMO_MAGIC			0x44454D4F
+
+typedef struct
+{
+	uint32	magic;
+	int32	len;
+	char	data[FLEXIBLE_ARRAY_MEMBER];
+} dsm_demo_payload;
+
+/*
+ * dsm_demo_create(text, segment_lifetime int4)
+ *
+ * The first argument is the text data to be shared by using dsm, the second
+ * controls the life span of dsm segemnt. 0 indicates session lifetime, 1
+ * indicates postmaster lifetime.
+ */
+Datum
+dsm_demo_create(PG_FUNCTION_ARGS)
+{
+	text	   *txt = PG_GETARG_TEXT_PP(0);
+	int			len = VARSIZE_ANY(txt);
+	int		segment_life = PG_GETARG_INT32(1);
+	uint64		seglen;
+	dsm_segment *seg;
+	dsm_handle	h;
+	dsm_demo_payload *payload;
+
+	seglen = offsetof(dsm_demo_payload, data) + len;
+	seg = dsm_create(seglen, DSM_CREATE_NULL_IF_MAXSEGMENTS);
+
+	if (segment_life == 0)
+		dsm_pin_mapping(seg);
+	else if (segment_life == 1)
+		dsm_pin_segment(seg);
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 (errmsg("value of segment lifetime can be either 0 or 1"))));
+
+	payload = dsm_segment_address(seg);
+	payload->magic = DSM_DEMO_MAGIC;
+	payload->len = len;
+	memcpy(payload->data, txt, len);
+
+	h = dsm_segment_handle(seg);
+
+	dsm_detach(seg);
+
+	PG_RETURN_INT64(h);
+}
+
+Datum
+dsm_demo_read(PG_FUNCTION_ARGS)
+{
+	dsm_handle	h = PG_GETARG_INT64(0);
+	dsm_segment *seg;
+	bool		needs_detach = false;
+	text	   *txt = NULL;
+	dsm_demo_payload *payload;
+
+	/*
+	 * We could be called from the same sesion that called dsm_demo_create(),
+	 * so search for an existing mapping.  If we don't find one, attach the
+	 * segment.
+	 */
+	seg = dsm_find_mapping(h);
+	if (seg == NULL)
+	{
+		seg = dsm_attach(h);
+		if (!seg)
+			PG_RETURN_NULL();
+		needs_detach = true;
+	}
+
+	/* Extract data, after checking magic number. */
+	payload = dsm_segment_address(seg);
+	if (payload->magic == DSM_DEMO_MAGIC)
+	{
+		txt = palloc(payload->len);
+		memcpy(txt, payload->data, payload->len);
+	}
+
+	/* Detach, if there was no existing mapping. */
+	if (needs_detach)
+		dsm_detach(seg);
+
+	if (txt == NULL)
+		PG_RETURN_NULL();
+
+	PG_RETURN_TEXT_P(txt);
+}
+
+Datum
+dsm_demo_unpin_segment(PG_FUNCTION_ARGS)
+{
+	dsm_handle	h = PG_GETARG_INT64(0);
+	dsm_segment *seg;
+	bool		needs_detach = false;
+
+	/*
+	 * We could be called from the same sesion that called dsm_demo_create(),
+	 * so search for an existing mapping.  If we don't find one, attach the
+	 * segment.
+	 */
+	seg = dsm_find_mapping(h);
+	if (seg == NULL)
+	{
+		seg = dsm_attach(h);
+		if (!seg)
+			PG_RETURN_BOOL(false);
+		needs_detach = true;
+	}
+
+	dsm_unpin_segment(h);
+
+	/* Detach, if there was no existing mapping. */
+	if (needs_detach)
+		dsm_detach(seg);
+
+	PG_RETURN_BOOL(true);
+}
diff --git a/contrib/dsm_demo/dsm_demo.control b/contrib/dsm_demo/dsm_demo.control
new file mode 100644
index 0000000..4060791
--- /dev/null
+++ b/contrib/dsm_demo/dsm_demo.control
@@ -0,0 +1,5 @@
+# dsm_demo extension
+comment = 'Dynamic shared memory demonstration'
+default_version = '1.0'
+module_pathname = 'dsm_demo'
+relocatable = true
