static ps_sd *ps_sd_new(ps_mm *data, const char *key) { php_uint32 hv, slot; ps_sd *sd; int keylen; keylen = strlen(key); sd = mm_malloc(data->mm, sizeof(ps_sd) + keylen); if (!sd) { TSRMLS_FETCH(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "mm_malloc failed, avail %d, err %s", mm_available(data->mm), mm_error()); return NULL; } hv = ps_sd_hash(key, keylen); slot = hv & data->hash_max; sd->ctime = 0; sd->hv = hv; sd->data = NULL; sd->alloclen = sd->datalen = 0; memcpy(sd->key, key, keylen + 1); sd->next = data->hash[slot]; data->hash[slot] = sd; data->hash_cnt++; if (!sd->next) { if (data->hash_cnt >= data->hash_max) { hash_split(data); } } ps_mm_debug(("inserting %s(%p) into slot %d\n", key, sd, slot)); return sd; }
size_t MM_available(void) { if (mm_global == NULL) return -1; return mm_available(mm_global); }
inline uint32 Avaliable() { return mm_available(m_raw_pool); }
API_EXPORT(void *) ap_mm_malloc(AP_MM *mm, size_t size) STUB(mm_malloc(mm, size), NULL) API_EXPORT(void *) ap_mm_realloc(AP_MM *mm, void *ptr, size_t size) STUB(mm_realloc(mm, ptr, size), NULL) API_EXPORT(void) ap_mm_free(AP_MM *mm, void *ptr) STUB_STMT(mm_free(mm, ptr)) API_EXPORT(void *) ap_mm_calloc(AP_MM *mm, size_t number, size_t size) STUB(mm_calloc(mm, number, size), NULL) API_EXPORT(char *) ap_mm_strdup(AP_MM *mm, const char *str) STUB(mm_strdup(mm, str), NULL) API_EXPORT(size_t) ap_mm_sizeof(AP_MM *mm, void *ptr) STUB(mm_sizeof(mm, ptr), 0) API_EXPORT(size_t) ap_mm_maxsize(void) STUB(mm_maxsize(), 0) API_EXPORT(size_t) ap_mm_available(AP_MM *mm) STUB(mm_available(mm), 0) API_EXPORT(char *) ap_mm_error(void) STUB(mm_error(), NULL) API_EXPORT(void) ap_mm_display_info(AP_MM *mm) STUB_STMT(mm_display_info(mm)) API_EXPORT(void *) ap_mm_core_create(size_t size, char *file) STUB(mm_core_create(size, file), NULL) API_EXPORT(int) ap_mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group) STUB(mm_core_permission(core, mode, owner, group), -1) API_EXPORT(void) ap_mm_core_delete(void *core) STUB_STMT(mm_core_delete(core)) API_EXPORT(size_t) ap_mm_core_size(void *core) STUB(mm_core_size(core), 0) API_EXPORT(int) ap_mm_core_lock(void *core, ap_mm_lock_mode mode) STUB(mm_core_lock(core, mode), FALSE)
int main(int argc, char *argv[]) { unsigned char *core; int i; size_t s, s2; pid_t pid; int size; MM *mm; int n; char *cp[1025]; int version; struct count_test { int count; int prev; } *ct; setbuf(stderr, NULL); /* ** ** Test Global Library API ** */ fprintf(stderr, "\n*** TESTING GLOBAL LIBRARY API ***\n\n"); fprintf(stderr, "Fetching library version\n"); version = mm_lib_version(); FAILED_IF(version == 0x0); fprintf(stderr, "version = 0x%X\n", version); /* ** ** Test Low-Level Shared Memory API ** */ fprintf(stderr, "\n*** TESTING LOW-LEVEL SHARED MEMORY API ***\n"); fprintf(stderr, "\n=== Testing Memory Segment Access ===\n"); fprintf(stderr, "Creating 16KB shared memory core area\n"); core = mm_core_create(1024*16, NULL); FAILED_IF(core == NULL); s = mm_core_size(core); FAILED_IF(s == 0); fprintf(stderr, "actually allocated core size = %d\n", s); fprintf(stderr, "Writing 0xF5 bytes to shared memory core area\n"); for (i = 0; i < s; i++) { fprintf(stderr, "write to core[%06d]\r", i); core[i] = 0xF5; } fprintf(stderr, "\n"); fprintf(stderr, "Reading back 0xF5 bytes from shared memory core area\n"); for (i = 0; i < s; i++) { fprintf(stderr, "read from core[%06d]\r", i); if (core[i] != 0xF5) { fprintf(stderr, "Offset %d: 0xF5 not found (found 0x%X\n", i, core[i]); exit(0); } } fprintf(stderr, "\n"); fprintf(stderr, "Destroying shared memory core area\n"); mm_core_delete(core); fprintf(stderr, "\n=== Testing Memory Locking ===\n"); fprintf(stderr, "Creating small shared memory core area\n"); ct = mm_core_create(sizeof(struct count_test), NULL); FAILED_IF(ct == NULL); s = mm_core_size(ct); FAILED_IF(s == 0); fprintf(stderr, "actually allocated core size = %d\n", s); ct->prev = 0; ct->count = 1; if ((pid = fork()) == 0) { /* child */ while (ct->count < 32768) { if (!mm_core_lock(ct, MM_LOCK_RW)) { fprintf(stderr, "locking failed (child)\n"); FAILED_IF(1); } if (ct->prev != (ct->count-1)) { fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count); exit(1); } ct->count += 1; fprintf(stderr, "count=%06d (child )\r", ct->count); ct->prev += 1; if (!mm_core_unlock(ct)) { fprintf(stderr, "locking failed (child)\n"); FAILED_IF(1); } } exit(0); } /* parent ... */ while (ct->count < 32768) { if (!mm_core_lock(ct, MM_LOCK_RW)) { fprintf(stderr, "locking failed (parent)\n"); FAILED_IF(1); } if (ct->prev != (ct->count-1)) { fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count); exit(1); } ct->count += 1; fprintf(stderr, "count=%06d (parent)\r", ct->count); ct->prev += 1; if (!mm_core_unlock(ct)) { fprintf(stderr, "locking failed (parent)\n"); kill(pid, SIGTERM); FAILED_IF(1); } } waitpid(pid, NULL, 0); fprintf(stderr, "\n"); fprintf(stderr, "Destroying shared memory core area\n"); mm_core_delete(ct); /* ** ** Test Standard Malloc-style API ** */ fprintf(stderr, "\n*** TESTING STANDARD MALLOC-STYLE API ***\n"); fprintf(stderr, "\n=== Testing Allocation ===\n"); fprintf(stderr, "Creating MM object\n"); size = mm_maxsize(); if (size > 1024*1024*1) size = 1024*1024*1; mm = mm_create(size, NULL); FAILED_IF(mm == NULL) mm_display_info(mm); s = mm_available(mm); FAILED_IF(s == 0); fprintf(stderr, "actually available bytes = %d\n", s); fprintf(stderr, "Allocating areas inside MM\n"); n = 0; for (i = 0; i < 1024; i++) cp[i] = NULL; for (i = 0; i < 1024; i++) { fprintf(stderr, "total=%09d allocated=%09d add=%06d\r", s, n, (i+1)*(i+1)); s2 = mm_available(mm); if ((i+1)*(i+1) > s2) { cp[i] = mm_malloc(mm, (i+1)*(i+1)); if (cp[i] != NULL) { fprintf(stderr, "\nExpected an out of memory situation. Hmmmmm\n"); FAILED_IF(1); } break; } cp[i] = mm_malloc(mm, (i+1)*(i+1)); n += (i+1)*(i+1); FAILED_IF(cp[i] == NULL) memset(cp[i], 0xF5, (i+1)*(i+1)); } mm_display_info(mm); fprintf(stderr, "\n=== Testing Defragmentation ===\n"); fprintf(stderr, "Fragmenting memory area by freeing some selected areas\n"); for (i = 0; i < 1024; i++) { if (i % 2 == 0) continue; if (cp[i] != NULL) mm_free(mm, cp[i]); cp[i] = NULL; } mm_display_info(mm); fprintf(stderr, "Freeing all areas\n"); for (i = 0; i < 1024; i++) { mm_free(mm, cp[i]); } mm_display_info(mm); fprintf(stderr, "Checking for memory leaks\n"); s2 = mm_available(mm); if (s != s2) { fprintf(stderr, "Something is leaking, we've lost %d bytes\n", s - s2); FAILED_IF(1); } else { fprintf(stderr, "Fine, we have again %d bytes available\n", s2); } fprintf(stderr, "Destroying MM object\n"); mm_destroy(mm); /******/ fprintf(stderr, "\nOK - ALL TESTS SUCCESSFULLY PASSED.\n\n"); exit(0); }