Skip to content

Commit 09d0e9a

Browse files
committed
PHPC-2470: Vendor bson-atomic as phongo_atomic
libmongoc 1.29.0 deprecated bson-atomic.h, so this vendors the necessary functionality into PHPC.
1 parent 21fba20 commit 09d0e9a

File tree

5 files changed

+499
-3
lines changed

5 files changed

+499
-3
lines changed

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ if test "$PHP_MONGODB" != "no"; then
127127
PHP_MONGODB_SOURCES="\
128128
php_phongo.c \
129129
src/phongo_apm.c \
130+
src/phongo_atomic.c \
130131
src/phongo_bson.c \
131132
src/phongo_bson_encode.c \
132133
src/phongo_client.c \

config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ if (PHP_MONGODB != "no") {
114114
var PHP_MONGODB_UTF8PROC_SOURCES="utf8proc.c";
115115

116116
EXTENSION("mongodb", "php_phongo.c", null, PHP_MONGODB_CFLAGS);
117-
MONGODB_ADD_SOURCES("/src", "phongo_apm.c phongo_bson.c phongo_bson_encode.c phongo_client.c phongo_compat.c phongo_error.c phongo_execute.c phongo_ini.c phongo_log.c phongo_util.c");
117+
MONGODB_ADD_SOURCES("/src", "phongo_apm.c phongo_atomic.c phongo_bson.c phongo_bson_encode.c phongo_client.c phongo_compat.c phongo_error.c phongo_execute.c phongo_ini.c phongo_log.c phongo_util.c");
118118
MONGODB_ADD_SOURCES("/src/BSON", "Binary.c BinaryInterface.c Document.c Iterator.c DBPointer.c Decimal128.c Decimal128Interface.c Int64.c Javascript.c JavascriptInterface.c MaxKey.c MaxKeyInterface.c MinKey.c MinKeyInterface.c ObjectId.c ObjectIdInterface.c PackedArray.c Persistable.c Regex.c RegexInterface.c Serializable.c Symbol.c Timestamp.c TimestampInterface.c Type.c Undefined.c Unserializable.c UTCDateTime.c UTCDateTimeInterface.c functions.c");
119119
MONGODB_ADD_SOURCES("/src/MongoDB", "BulkWrite.c ClientEncryption.c Command.c Cursor.c CursorId.c CursorInterface.c Manager.c Query.c ReadConcern.c ReadPreference.c Server.c ServerApi.c ServerDescription.c Session.c TopologyDescription.c WriteConcern.c WriteConcernError.c WriteError.c WriteResult.c");
120120
MONGODB_ADD_SOURCES("/src/MongoDB/Exception", "AuthenticationException.c BulkWriteException.c CommandException.c ConnectionException.c ConnectionTimeoutException.c EncryptionException.c Exception.c ExecutionTimeoutException.c InvalidArgumentException.c LogicException.c RuntimeException.c ServerException.c SSLConnectionException.c UnexpectedValueException.c WriteException.c");

php_phongo.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <ext/standard/info.h>
2626

2727
#include "php_phongo.h"
28+
#include "src/phongo_atomic.h"
2829
#include "src/phongo_client.h"
2930
#include "src/phongo_error.h"
3031
#include "src/phongo_ini.h"
@@ -130,7 +131,7 @@ PHP_GINIT_FUNCTION(mongodb) /* {{{ */
130131
#endif
131132

132133
/* Increment the thread counter. */
133-
bson_atomic_int32_fetch_add(&phongo_num_threads, 1, bson_memory_order_seq_cst);
134+
phongo_atomic_int32_fetch_add(&phongo_num_threads, 1, phongo_memory_order_seq_cst);
134135

135136
/* Clear extension globals */
136137
memset(mongodb_globals, 0, sizeof(zend_mongodb_globals));
@@ -375,7 +376,7 @@ PHP_GSHUTDOWN_FUNCTION(mongodb) /* {{{ */
375376
* is the last thread, MSHUTDOWN has been called, persistent clients from
376377
* all threads have been destroyed, and it is now safe to shutdown libmongoc
377378
* and restore libbson's original vtable. */
378-
if (bson_atomic_int32_fetch_sub(&phongo_num_threads, 1, bson_memory_order_seq_cst) - 1 == 0) {
379+
if (phongo_atomic_int32_fetch_sub(&phongo_num_threads, 1, phongo_memory_order_seq_cst) - 1 == 0) {
379380
mongoc_cleanup();
380381
bson_mem_restore_vtable();
381382
}

src/phongo_atomic.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright 2024-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/* Note: this file was derived from libbson's bson-atomic.c */
18+
19+
#include "bson/bson.h"
20+
21+
#include "phongo_atomic.h"
22+
23+
#ifdef BSON_OS_UNIX
24+
/* For sched_yield() */
25+
#include <sched.h>
26+
#endif
27+
28+
static void
29+
_thrd_yield (void)
30+
{
31+
BSON_IF_WINDOWS (SwitchToThread ();)
32+
BSON_IF_POSIX (sched_yield ();)
33+
}
34+
35+
/**
36+
* Some platforms do not support compiler intrinsics for atomic operations.
37+
* We emulate that here using a spin lock and regular arithmetic operations
38+
*/
39+
static int8_t gEmulAtomicLock = 0;
40+
41+
static void
42+
_lock_emul_atomic (void)
43+
{
44+
int i;
45+
if (phongo_atomic_int8_compare_exchange_weak (&gEmulAtomicLock, 0, 1, phongo_memory_order_acquire) == 0) {
46+
/* Successfully took the spinlock */
47+
return;
48+
}
49+
/* Failed. Try taking ten more times, then begin sleeping. */
50+
for (i = 0; i < 10; ++i) {
51+
if (phongo_atomic_int8_compare_exchange_weak (&gEmulAtomicLock, 0, 1, phongo_memory_order_acquire) == 0) {
52+
/* Succeeded in taking the lock */
53+
return;
54+
}
55+
}
56+
/* Still don't have the lock. Spin and yield */
57+
while (phongo_atomic_int8_compare_exchange_weak (&gEmulAtomicLock, 0, 1, phongo_memory_order_acquire) != 0) {
58+
_thrd_yield ();
59+
}
60+
}
61+
62+
static void
63+
_unlock_emul_atomic (void)
64+
{
65+
int64_t rv = phongo_atomic_int8_exchange (&gEmulAtomicLock, 0, phongo_memory_order_release);
66+
BSON_ASSERT (rv == 1 && "Released atomic lock while not holding it");
67+
}
68+
69+
int32_t
70+
_phongo_emul_atomic_int32_fetch_add (volatile int32_t *p, int32_t n, enum phongo_memory_order _unused)
71+
{
72+
int32_t ret;
73+
74+
BSON_UNUSED (_unused);
75+
76+
_lock_emul_atomic ();
77+
ret = *p;
78+
*p += n;
79+
_unlock_emul_atomic ();
80+
return ret;
81+
}
82+
83+
int32_t
84+
_phongo_emul_atomic_int32_exchange (volatile int32_t *p, int32_t n, enum phongo_memory_order _unused)
85+
{
86+
int32_t ret;
87+
88+
BSON_UNUSED (_unused);
89+
90+
_lock_emul_atomic ();
91+
ret = *p;
92+
*p = n;
93+
_unlock_emul_atomic ();
94+
return ret;
95+
}
96+
97+
int32_t
98+
_phongo_emul_atomic_int32_compare_exchange_strong (volatile int32_t *p,
99+
int32_t expect_value,
100+
int32_t new_value,
101+
enum phongo_memory_order _unused)
102+
{
103+
int32_t ret;
104+
105+
BSON_UNUSED (_unused);
106+
107+
_lock_emul_atomic ();
108+
ret = *p;
109+
if (ret == expect_value) {
110+
*p = new_value;
111+
}
112+
_unlock_emul_atomic ();
113+
return ret;
114+
}
115+
116+
int32_t
117+
_phongo_emul_atomic_int32_compare_exchange_weak (volatile int32_t *p,
118+
int32_t expect_value,
119+
int32_t new_value,
120+
enum phongo_memory_order order)
121+
{
122+
/* We're emulating. We can't do a weak version. */
123+
return _phongo_emul_atomic_int32_compare_exchange_strong (p, expect_value, new_value, order);
124+
}

0 commit comments

Comments
 (0)