LCOV - code coverage report
Current view: top level - ext - shared_memory.c (source / functions) Coverage Total Hit
Test: Extension code coverage Lines: 66.0 % 53 35
Test Date: 2026-09-01 07:24:29 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /*
       2              :   +----------------------------------------------------------------------+
       3              :   | COLOPL PHP TimeShifter.                                              |
       4              :   +----------------------------------------------------------------------+
       5              :   | Copyright (c) COLOPL, Inc.                                           |
       6              :   +----------------------------------------------------------------------+
       7              :   | This source file is subject to the BSD-3-Clause license that is      |
       8              :   | bundled with this package in the file LICENSE.                       |
       9              :   +----------------------------------------------------------------------+
      10              :   | Author: Go Kudo <g-kudo@colopl.co.jp>                                |
      11              :   +----------------------------------------------------------------------+
      12              : */
      13              : 
      14              : #ifndef PHP_WIN32
      15              : # include <errno.h>
      16              : # include <fcntl.h>
      17              : # include <stdio.h>
      18              : # include <unistd.h>
      19              : #endif
      20              : #include <stdint.h>
      21              : 
      22              : #include "php.h"
      23              : #include "shared_memory.h"
      24              : 
      25              : #ifndef PHP_WIN32
      26              : # ifdef MAP_ANONYMOUS
      27              : #  define COLOPL_TS_MAP_ANONYMOUS MAP_ANONYMOUS
      28              : # elif defined(MAP_ANON)
      29              : #  define COLOPL_TS_MAP_ANONYMOUS MAP_ANON
      30              : # else
      31              : #  error "Neither MAP_ANONYMOUS nor MAP_ANON is available"
      32              : # endif
      33              : 
      34        11714 : static inline sem_t *sm_semaphore(sm_t *sm)
      35              : {
      36              : # ifdef __APPLE__
      37              :         return sm->semaphore;
      38              : # else
      39        11714 :         return &sm->semaphore;
      40              : # endif
      41              : }
      42              : #endif
      43              : 
      44         5857 : static inline bool sm_lock(sm_t *sm)
      45              : {
      46              : #ifdef PHP_WIN32
      47              :         DWORD wait_result;
      48              : 
      49              :         if (!sm->mutex) {
      50              :                 return false;
      51              :         }
      52              : 
      53              :         wait_result = WaitForSingleObject(sm->mutex, INFINITE);
      54              :         return wait_result == WAIT_OBJECT_0 || wait_result == WAIT_ABANDONED;
      55              : #else
      56         5857 :         sem_t *semaphore = sm_semaphore(sm);
      57              : 
      58         5857 :         if (!semaphore) {
      59            0 :                 return false;
      60              :         }
      61              : 
      62         5857 :         while (sem_wait(semaphore) != 0) {
      63            0 :                 if (errno != EINTR) {
      64            0 :                         return false;
      65              :                 }
      66              :         }
      67         5857 :         return true;
      68              : #endif
      69              : }
      70              : 
      71         5857 : static inline bool sm_unlock(sm_t *sm)
      72              : {
      73              : #ifdef PHP_WIN32
      74              :         return sm->mutex && ReleaseMutex(sm->mutex);
      75              : #else
      76         5857 :         sem_t *semaphore = sm_semaphore(sm);
      77              : 
      78         5857 :         return semaphore && sem_post(semaphore) == 0;
      79              : #endif
      80              : }
      81              : 
      82              : #if defined(__APPLE__) && !defined(PHP_WIN32)
      83              : static bool sm_init_semaphore(sm_t *sm)
      84              : {
      85              :         static unsigned long semaphore_counter;
      86              :         unsigned int attempts;
      87              : 
      88              :         for (attempts = 0; attempts < 16; attempts++) {
      89              :                 snprintf(
      90              :                         sm->semaphore_name,
      91              :                         sizeof(sm->semaphore_name),
      92              :                         "/cts%05lx%05lx",
      93              :                         (unsigned long) getpid() & 0xfffff,
      94              :                         semaphore_counter++ & 0xfffff
      95              :                 );
      96              : 
      97              :                 sm->semaphore = sem_open(sm->semaphore_name, O_CREAT | O_EXCL, 0600, 1);
      98              :                 if (sm->semaphore != SEM_FAILED) {
      99              :                         if (sem_unlink(sm->semaphore_name) != 0) {
     100              :                                 sem_close(sm->semaphore);
     101              :                                 sm->semaphore = NULL;
     102              :                                 sm->semaphore_name[0] = '\0';
     103              :                                 return false;
     104              :                         }
     105              :                         return true;
     106              :                 }
     107              : 
     108              :                 if (errno != EEXIST) {
     109              :                         break;
     110              :                 }
     111              :         }
     112              : 
     113              :         sm->semaphore = NULL;
     114              :         sm->semaphore_name[0] = '\0';
     115              :         return false;
     116              : }
     117              : #endif
     118              : 
     119          274 : bool sm_init(sm_t *sm, size_t size)
     120              : {
     121          274 :         memset(sm, 0, sizeof(sm_t));
     122          274 :         sm->size = size;
     123              : 
     124              : #ifdef PHP_WIN32
     125              :         sm->mapping = CreateFileMapping(
     126              :                 INVALID_HANDLE_VALUE,
     127              :                 NULL,
     128              :                 PAGE_READWRITE,
     129              :                 (DWORD) (((uint64_t) sm->size) >> 32),
     130              :                 (DWORD) (((uint64_t) sm->size) & 0xffffffff),
     131              :                 NULL
     132              :         );
     133              :         if (!sm->mapping) {
     134              :                 return false;
     135              :         }
     136              : 
     137              :         sm->data = MapViewOfFile(sm->mapping, FILE_MAP_ALL_ACCESS, 0, 0, sm->size);
     138              :         if (!sm->data) {
     139              :                 CloseHandle(sm->mapping);
     140              :                 sm->mapping = NULL;
     141              :                 return false;
     142              :         }
     143              : 
     144              :         sm->mutex = CreateMutex(NULL, FALSE, NULL);
     145              :         if (!sm->mutex) {
     146              :                 UnmapViewOfFile(sm->data);
     147              :                 CloseHandle(sm->mapping);
     148              :                 sm->data = NULL;
     149              :                 sm->mapping = NULL;
     150              :                 return false;
     151              :         }
     152              : #else
     153          274 :         sm->data = mmap(NULL, sm->size, PROT_READ | PROT_WRITE, MAP_SHARED | COLOPL_TS_MAP_ANONYMOUS, -1, 0);
     154          274 :         if (sm->data == MAP_FAILED) {
     155            0 :                 sm->data = NULL;
     156            0 :                 return false;
     157              :         }
     158              : 
     159              : #ifdef __APPLE__
     160              :         if (!sm_init_semaphore(sm)) {
     161              :                 munmap(sm->data, sm->size);
     162              :                 sm->data = NULL;
     163              :                 return false;
     164              :         }
     165              : #else
     166          274 :         if (sem_init(&sm->semaphore, 1, 1) != 0) {
     167            0 :                 munmap(sm->data, sm->size);
     168            0 :                 sm->data = NULL;
     169            0 :                 return false;
     170              :         }
     171              : #endif
     172              : #endif
     173              : 
     174          274 :         return true;
     175              : }
     176              : 
     177         5281 : void sm_read(sm_t *sm, void *dest)
     178              : {
     179         5281 :         if (!sm->data) {
     180            0 :                 memset(dest, 0, sm->size);
     181            0 :                 return;
     182              :         }
     183              : 
     184         5281 :         if (!sm_lock(sm)) {
     185            0 :                 memset(dest, 0, sm->size);
     186            0 :                 return;
     187              :         }
     188              : 
     189         5281 :         memcpy(dest, sm->data, sm->size);
     190              : 
     191         5281 :         sm_unlock(sm);
     192              : }
     193              : 
     194          576 : bool sm_write(sm_t *sm, void *src)
     195              : {
     196          576 :         if (!sm->data) {
     197            0 :                 return false;
     198              :         }
     199              : 
     200          576 :         if (!sm_lock(sm)) {
     201            0 :                 return false;
     202              :         }
     203              : 
     204          576 :         memcpy(sm->data, src, sm->size);
     205              : 
     206          576 :         if (!sm_unlock(sm)) {
     207            0 :                 return false;
     208              :         }
     209              : 
     210          576 :         return true;
     211              : }
     212              : 
     213          274 : bool sm_free(sm_t *sm)
     214              : {
     215          274 :         bool result = true;
     216              : 
     217          274 :         if (!sm->data) {
     218            0 :                 return false;
     219              :         }
     220              : 
     221              : #ifdef PHP_WIN32
     222              :         if (!UnmapViewOfFile(sm->data)) {
     223              :                 result = false;
     224              :         }
     225              :         sm->data = NULL;
     226              : 
     227              :         if (sm->mapping && !CloseHandle(sm->mapping)) {
     228              :                 result = false;
     229              :         }
     230              :         sm->mapping = NULL;
     231              : 
     232              :         if (sm->mutex && !CloseHandle(sm->mutex)) {
     233              :                 result = false;
     234              :         }
     235              :         sm->mutex = NULL;
     236              : #else
     237          274 :         if (munmap(sm->data, sm->size) != 0) {
     238            0 :                 result = false;
     239              :         }
     240          274 :         sm->data = NULL;
     241              : 
     242              : # ifdef __APPLE__
     243              :         if (sm->semaphore && sem_close(sm->semaphore) != 0) {
     244              :                 result = false;
     245              :         }
     246              :         sm->semaphore = NULL;
     247              :         sm->semaphore_name[0] = '\0';
     248              : # else
     249          274 :         if (sem_destroy(&sm->semaphore) != 0) {
     250            0 :                 result = false;
     251              :         }
     252              : # endif
     253              : #endif
     254              : 
     255          274 :         return result;
     256              : }
        

Generated by: LCOV version 2.0-1