Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions ext/opcache/shared_alloc_shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
# define MIN(x, y) ((x) > (y)? (y) : (x))
#endif

#define SEG_ALLOC_SIZE_MAX 32*1024*1024
#define SEG_ALLOC_SIZE_MIN 2*1024*1024

typedef struct {
Expand All @@ -53,36 +52,38 @@ typedef struct {
static int create_segments(size_t requested_size, zend_shared_segment_shm ***shared_segments_p, int *shared_segments_count, const char **error_in)
{
int i;
size_t allocate_size = 0, remaining_bytes = requested_size, seg_allocate_size;
size_t allocate_size = 0, remaining_bytes, seg_allocate_size;
int first_segment_id = -1;
key_t first_segment_key = -1;
struct shmid_ds sds;
int shmget_flags;
zend_shared_segment_shm *shared_segments;

seg_allocate_size = SEG_ALLOC_SIZE_MAX;
/* determine segment size we _really_ need:
* no more than to include requested_size
*/
while (requested_size * 2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) {
seg_allocate_size >>= 1;
}

shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL;

/* try allocating this much, if not - try shrinking */
while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
allocate_size = MIN(requested_size, seg_allocate_size);
first_segment_id = shmget(first_segment_key, allocate_size, shmget_flags);
if (first_segment_id != -1) {
break;
/* Try contiguous allocation first. */
seg_allocate_size = requested_size;
first_segment_id = shmget(first_segment_key, seg_allocate_size, shmget_flags);
if (UNEXPECTED(first_segment_id == -1)) {
/* Search for biggest n^2 < requested_size. */
seg_allocate_size = SEG_ALLOC_SIZE_MIN;
while (seg_allocate_size < requested_size / 2) {
seg_allocate_size *= 2;
}
seg_allocate_size >>= 1; /* shrink the allocated block */
}

if (first_segment_id == -1) {
*error_in = "shmget";
return ALLOC_FAILURE;
/* try allocating this much, if not - try shrinking */
while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
first_segment_id = shmget(first_segment_key, seg_allocate_size, shmget_flags);
if (first_segment_id != -1) {
break;
}
seg_allocate_size >>= 1; /* shrink the allocated block */
}

if (first_segment_id == -1) {
*error_in = "shmget";
return ALLOC_FAILURE;
}
}

*shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1;
Expand Down
Loading