Skip to content

Commit 7c6f089

Browse files
psumberailuuu1994
authored andcommitted
Improve shared_alloc_shm.c strategy to support OPcache JIT on Solaris
The SysV shared memory allocator in OPcache hardcodes a maximum segment size of 32MB (SEG_ALLOC_SIZE_MAX). If the JIT buffer exceeds this, which it does with the default 64MB size, startup will fail with "Insufficient shared memory!". The allocator will now try allocating a contiguous buffer first, and only then use segmentation by searching for continuously smaller powers of 2. Fixes GH-20718 Closes GH-20719
1 parent 2cabea6 commit 7c6f089

File tree

2 files changed

+26
-21
lines changed

2 files changed

+26
-21
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ PHP NEWS
2626
. Fixed bug GH-21097 (Accessing Dom\Node properties can can throw TypeError).
2727
(ndossche)
2828

29+
- Opcache:
30+
. Fixed bug GH-20718 ("Insufficient shared memory" when using JIT on Solaris).
31+
(Petr Sumbera)
32+
2933
- PDO_PGSQL:
3034
. Fixed bug GH-21055 (connection attribute status typo for GSS negotiation).
3135
(lsaos)

ext/opcache/shared_alloc_shm.c

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
# define MIN(x, y) ((x) > (y)? (y) : (x))
4343
#endif
4444

45-
#define SEG_ALLOC_SIZE_MAX 32*1024*1024
4645
#define SEG_ALLOC_SIZE_MIN 2*1024*1024
4746

4847
typedef struct {
@@ -53,36 +52,38 @@ typedef struct {
5352
static int create_segments(size_t requested_size, zend_shared_segment_shm ***shared_segments_p, int *shared_segments_count, const char **error_in)
5453
{
5554
int i;
56-
size_t allocate_size = 0, remaining_bytes = requested_size, seg_allocate_size;
55+
size_t allocate_size = 0, remaining_bytes, seg_allocate_size;
5756
int first_segment_id = -1;
5857
key_t first_segment_key = -1;
5958
struct shmid_ds sds;
6059
int shmget_flags;
6160
zend_shared_segment_shm *shared_segments;
6261

63-
seg_allocate_size = SEG_ALLOC_SIZE_MAX;
64-
/* determine segment size we _really_ need:
65-
* no more than to include requested_size
66-
*/
67-
while (requested_size * 2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) {
68-
seg_allocate_size >>= 1;
69-
}
70-
7162
shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL;
7263

73-
/* try allocating this much, if not - try shrinking */
74-
while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
75-
allocate_size = MIN(requested_size, seg_allocate_size);
76-
first_segment_id = shmget(first_segment_key, allocate_size, shmget_flags);
77-
if (first_segment_id != -1) {
78-
break;
64+
/* Try contiguous allocation first. */
65+
seg_allocate_size = requested_size;
66+
first_segment_id = shmget(first_segment_key, seg_allocate_size, shmget_flags);
67+
if (UNEXPECTED(first_segment_id == -1)) {
68+
/* Search for biggest n^2 < requested_size. */
69+
seg_allocate_size = SEG_ALLOC_SIZE_MIN;
70+
while (seg_allocate_size < requested_size / 2) {
71+
seg_allocate_size *= 2;
7972
}
80-
seg_allocate_size >>= 1; /* shrink the allocated block */
81-
}
8273

83-
if (first_segment_id == -1) {
84-
*error_in = "shmget";
85-
return ALLOC_FAILURE;
74+
/* try allocating this much, if not - try shrinking */
75+
while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
76+
first_segment_id = shmget(first_segment_key, seg_allocate_size, shmget_flags);
77+
if (first_segment_id != -1) {
78+
break;
79+
}
80+
seg_allocate_size >>= 1; /* shrink the allocated block */
81+
}
82+
83+
if (first_segment_id == -1) {
84+
*error_in = "shmget";
85+
return ALLOC_FAILURE;
86+
}
8687
}
8788

8889
*shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1;

0 commit comments

Comments
 (0)