aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2016-02-19 22:47:50 -0500
committerNoah Misch <noah@leadboat.com>2016-02-19 22:48:04 -0500
commit377a1af56a5ad6e5c47e0a5141abbd912169f750 (patch)
treee982975c4b5cc920213f4882c999013960c66dd7 /src
parentc479024d325a02e0eb352e5b7f1873b4c51a5205 (diff)
downloadpostgresql-377a1af56a5ad6e5c47e0a5141abbd912169f750.tar.gz
postgresql-377a1af56a5ad6e5c47e0a5141abbd912169f750.zip
Call xlc __isync() after, not before, associated compare-and-swap.
Architecture reference material specifies this order, and s_lock.h inline assembly agrees. The former order failed to provide mutual exclusion to lwlock.c and perhaps to other clients. The two xlc buildfarm members, hornet and mandrill, have failed sixteen times with duplicate key errors involving pg_class_oid_index or pg_type_oid_index. Back-patch to 9.5, where commit b64d92f1a5602c55ee8b27a7ac474f03b7aee340 introduced atomics. Reviewed by Andres Freund and Tom Lane.
Diffstat (limited to 'src')
-rw-r--r--src/bin/pgbench/.gitignore1
-rw-r--r--src/bin/pgbench/Makefile6
-rw-r--r--src/bin/pgbench/t/001_pgbench.pl24
-rw-r--r--src/include/port/atomics/generic-xlc.h22
-rwxr-xr-xsrc/tools/msvc/clean.bat1
5 files changed, 46 insertions, 8 deletions
diff --git a/src/bin/pgbench/.gitignore b/src/bin/pgbench/.gitignore
index aae819ed70f..983a3cd7a6d 100644
--- a/src/bin/pgbench/.gitignore
+++ b/src/bin/pgbench/.gitignore
@@ -1,3 +1,4 @@
/exprparse.c
/exprscan.c
/pgbench
+/tmp_check/
diff --git a/src/bin/pgbench/Makefile b/src/bin/pgbench/Makefile
index 18fdf58d13e..e9b1b74abfa 100644
--- a/src/bin/pgbench/Makefile
+++ b/src/bin/pgbench/Makefile
@@ -40,3 +40,9 @@ clean distclean:
maintainer-clean: distclean
rm -f exprparse.c exprscan.c
+
+check:
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
diff --git a/src/bin/pgbench/t/001_pgbench.pl b/src/bin/pgbench/t/001_pgbench.pl
new file mode 100644
index 00000000000..14cbc539834
--- /dev/null
+++ b/src/bin/pgbench/t/001_pgbench.pl
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+
+use TestLib;
+use Test::More tests => 3;
+
+# Test concurrent insertion into table with UNIQUE oid column. DDL expects
+# GetNewOidWithIndex() to successfully avoid violating uniqueness for indexes
+# like pg_class_oid_index and pg_proc_oid_index. This indirectly exercises
+# LWLock and spinlock concurrency. This test makes a 5-MiB table.
+my $tempdir = tempdir;
+start_test_server $tempdir;
+psql('postgres',
+ 'CREATE UNLOGGED TABLE oid_tbl () WITH OIDS; '
+ . 'ALTER TABLE oid_tbl ADD UNIQUE (oid);');
+my $script = "$tempdir/pgbench_script";
+open my $fh, ">", $script or die "could not open file $script";
+print $fh 'INSERT INTO oid_tbl SELECT FROM generate_series(1,1000);';
+close $fh;
+command_like(
+ [ qw(pgbench --no-vacuum --client=5 --protocol=prepared
+ --transactions=25 --file), $script, 'postgres' ],
+ qr{processed: 125/125},
+ 'concurrent OID generation');
diff --git a/src/include/port/atomics/generic-xlc.h b/src/include/port/atomics/generic-xlc.h
index 0ad9168ed28..394a8e83ca9 100644
--- a/src/include/port/atomics/generic-xlc.h
+++ b/src/include/port/atomics/generic-xlc.h
@@ -47,18 +47,22 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
uint32 *expected, uint32 newval)
{
/*
+ * XXX: __compare_and_swap is defined to take signed parameters, but that
+ * shouldn't matter since we don't perform any arithmetic operations.
+ */
+ bool ret = __compare_and_swap((volatile int*)&ptr->value,
+ (int *)expected, (int)newval);
+
+ /*
* xlc's documentation tells us:
* "If __compare_and_swap is used as a locking primitive, insert a call to
* the __isync built-in function at the start of any critical sections."
+ *
+ * The critical section begins immediately after __compare_and_swap().
*/
__isync();
- /*
- * XXX: __compare_and_swap is defined to take signed parameters, but that
- * shouldn't matter since we don't perform any arithmetic operations.
- */
- return __compare_and_swap((volatile int*)&ptr->value,
- (int *)expected, (int)newval);
+ return ret;
}
#define PG_HAVE_ATOMIC_FETCH_ADD_U32
@@ -75,10 +79,12 @@ static inline bool
pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
uint64 *expected, uint64 newval)
{
+ bool ret = __compare_and_swaplp((volatile long*)&ptr->value,
+ (long *)expected, (long)newval);
+
__isync();
- return __compare_and_swaplp((volatile long*)&ptr->value,
- (long *)expected, (long)newval);;
+ return ret;
}
#define PG_HAVE_ATOMIC_FETCH_ADD_U64
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
index feb0fe5b85e..d21692ffc9b 100755
--- a/src/tools/msvc/clean.bat
+++ b/src/tools/msvc/clean.bat
@@ -94,6 +94,7 @@ if exist src\bin\pg_basebackup\tmp_check rd /s /q src\bin\pg_basebackup\tmp_chec
if exist src\bin\pg_config\tmp_check rd /s /q src\bin\pg_config\tmp_check
if exist src\bin\pg_ctl\tmp_check rd /s /q src\bin\pg_ctl\tmp_check
if exist src\bin\pg_rewind\tmp_check rd /s /q src\bin\pg_rewind\tmp_check
+if exist src\bin\pgbench\tmp_check rd /s /q src\bin\pgbench\tmp_check
if exist src\bin\scripts\tmp_check rd /s /q src\bin\scripts\tmp_check
REM Clean up datafiles built with contrib