svn_stringbuf_t * svn_stringbuf_create_ensure(apr_size_t blocksize, apr_pool_t *pool) { void *mem; svn_stringbuf_t *new_string; /* apr_palloc will allocate multiples of 8. * Thus, we would waste some of that memory if we stuck to the * smaller size. Note that this is safe even if apr_palloc would * use some other aligment or none at all. */ ++blocksize; /* + space for '\0' */ blocksize = APR_ALIGN_DEFAULT(blocksize); /* Allocate memory for svn_string_t and data in one chunk. */ mem = apr_palloc(pool, sizeof(*new_string) + blocksize); /* Initialize header and string */ new_string = mem; new_string->data = (char*)mem + sizeof(*new_string); new_string->data[0] = '\0'; new_string->len = 0; new_string->blocksize = blocksize; new_string->pool = pool; return new_string; }
void svn_stringbuf_ensure(svn_stringbuf_t *str, apr_size_t minimum_size) { /* Keep doubling capacity until have enough. */ if (str->blocksize < minimum_size) { if (str->blocksize == 0) /* APR will increase odd allocation sizes to the next * multiple for 8, for instance. Take advantage of that * knowledge and allow for the extra size to be used. */ str->blocksize = APR_ALIGN_DEFAULT(minimum_size); else while (str->blocksize < minimum_size) { /* str->blocksize is aligned; * doubling it should keep it aligned */ apr_size_t prev_size = str->blocksize; str->blocksize *= 2; /* check for apr_size_t overflow */ if (prev_size > str->blocksize) { str->blocksize = minimum_size; break; } } str->data = (char *) my__realloc(str->data, str->len + 1, /* We need to maintain (and thus copy) the trailing nul */ str->blocksize, str->pool); } }
/* Allocate the space for a memory buffer from POOL. * Return a pointer to the new buffer in *DATA and its size in *SIZE. * The buffer size will be at least MINIMUM_SIZE. * * N.B.: The stringbuf creation functions use this, but since stringbufs * always consume at least 1 byte for the NUL terminator, the * resulting data pointers will never be NULL. */ static APR_INLINE void membuf_create(void **data, apr_size_t *size, apr_size_t minimum_size, apr_pool_t *pool) { /* apr_palloc will allocate multiples of 8. * Thus, we would waste some of that memory if we stuck to the * smaller size. Note that this is safe even if apr_palloc would * use some other aligment or none at all. */ minimum_size = APR_ALIGN_DEFAULT(minimum_size); *data = (!minimum_size ? NULL : apr_palloc(pool, minimum_size)); *size = minimum_size; }
apr_byte_t *heap_alloc(heap_t *hp, int size) { apr_byte_t *mem; size = APR_ALIGN_DEFAULT(size); heap_secure_space(hp, size); mem = (apr_byte_t *)heap_htop(hp); heap_htop(hp) += size; hp->alloc_size += size; return mem; }
apr_status_t upload_progress_cache_init(apr_pool_t *pool, ServerConfig *config) { #if APR_HAS_SHARED_MEMORY apr_status_t result; apr_size_t size; upload_progress_cache_t *cache; apr_rmm_off_t block; if (config->cache_file) { /* Remove any existing shm segment with this name. */ apr_shm_remove(config->cache_file, config->pool); } size = APR_ALIGN_DEFAULT(config->cache_bytes); result = apr_shm_create(&config->cache_shm, size, config->cache_file, config->pool); if (result != APR_SUCCESS) { return result; } /* Determine the usable size of the shm segment. */ size = apr_shm_size_get(config->cache_shm); /* This will create a rmm "handler" to get into the shared memory area */ result = apr_rmm_init(&config->cache_rmm, NULL, apr_shm_baseaddr_get(config->cache_shm), size, config->pool); if (result != APR_SUCCESS) { return result; } apr_pool_cleanup_register(config->pool, config , upload_progress_cache_module_kill, apr_pool_cleanup_null); /* init cache object */ CACHE_LOCK(); block = apr_rmm_calloc(config->cache_rmm, sizeof(upload_progress_cache_t)); cache = block ? (upload_progress_cache_t *)apr_rmm_addr_get(config->cache_rmm, block) : NULL; if(cache == NULL) { CACHE_UNLOCK(); return 0; } cache->head = NULL; config->cache_offset = block; config->cache = cache; CACHE_UNLOCK(); #endif return APR_SUCCESS; }
/* Ensure that BUF has enough space for VIEW_LEN bytes. */ static APR_INLINE svn_error_t * size_buffer(char **buf, apr_size_t *buf_size, apr_size_t view_len, apr_pool_t *pool) { if (view_len > *buf_size) { *buf_size *= 2; if (*buf_size < view_len) *buf_size = view_len; SVN_ERR_ASSERT(APR_ALIGN_DEFAULT(*buf_size) >= *buf_size); *buf = apr_palloc(pool, *buf_size); } return SVN_NO_ERROR; }
term_t heap_binary0(heap_t *hp, int bit_size) { apr_byte_t *data; binary_t *bin; int bin_size = APR_ALIGN_DEFAULT(sizeof(*bin)); int data_size = BIN_BYTE_SIZE(bit_size); int gap = bin_size + data_size; bin = (binary_t *)heap_alloc(hp, gap); data = (apr_byte_t *)bin + bin_size; bin->bit_size = bit_size; bin->data = data; bin->parent = noval; bin->offset = 0; return tag_binary(bin); }
apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st) { #if APR_HAS_SHARED_MEMORY apr_status_t result; apr_size_t size; if (st->cache_bytes > 0) { if (st->cache_file) { /* Remove any existing shm segment with this name. */ apr_shm_remove(st->cache_file, st->pool); } size = APR_ALIGN_DEFAULT(st->cache_bytes); result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool); if (result != APR_SUCCESS) { return result; } /* Determine the usable size of the shm segment. */ size = apr_shm_size_get(st->cache_shm); /* This will create a rmm "handler" to get into the shared memory area */ result = apr_rmm_init(&st->cache_rmm, NULL, apr_shm_baseaddr_get(st->cache_shm), size, st->pool); if (result != APR_SUCCESS) { return result; } } #endif apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null); st->util_ldap_cache = util_ald_create_cache(st, st->search_cache_size, st->search_cache_ttl, util_ldap_url_node_hash, util_ldap_url_node_compare, util_ldap_url_node_copy, util_ldap_url_node_free, util_ldap_url_node_display); return APR_SUCCESS; }
apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st) { #if APR_HAS_SHARED_MEMORY apr_status_t result; apr_size_t size; size = APR_ALIGN_DEFAULT(st->cache_bytes); result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool); if (result == APR_EEXIST) { /* * The cache could have already been created (i.e. we may be a child process). See * if we can attach to the existing shared memory */ result = apr_shm_attach(&st->cache_shm, st->cache_file, st->pool); } if (result != APR_SUCCESS) { return result; } /* Determine the usable size of the shm segment. */ size = apr_shm_size_get(st->cache_shm); /* This will create a rmm "handler" to get into the shared memory area */ result = apr_rmm_init(&st->cache_rmm, NULL, apr_shm_baseaddr_get(st->cache_shm), size, st->pool); if (result != APR_SUCCESS) { return result; } #endif apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null); st->util_ldap_cache = util_ald_create_cache(st, util_ldap_url_node_hash, util_ldap_url_node_compare, util_ldap_url_node_copy, util_ldap_url_node_free, util_ldap_url_node_display); return APR_SUCCESS; }
APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex( apr_allocator_t *allocator) { apr_bucket_alloc_t *list; apr_memnode_t *block; block = apr_allocator_alloc(allocator, ALLOC_AMT); if (!block) { return NULL; } list = (apr_bucket_alloc_t *)block->first_avail; list->pool = NULL; list->allocator = allocator; list->freelist = NULL; list->blocks = block; block->first_avail += APR_ALIGN_DEFAULT(sizeof(*list)); return list; }
APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, const char *filename, apr_pool_t *pool) { if (filename == NULL) { /* It doesn't make sense to attach to a segment if you don't know * the filename. */ return APR_EINVAL; } else { #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM apr_shm_t *new_m; apr_status_t status; int tmpfd; apr_file_t *file; /* file where metadata is stored */ apr_size_t nbytes; new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->filename = apr_pstrdup(pool, filename); #if APR_USE_SHMEM_MMAP_SHM const char *shm_name = make_shm_open_safe_name(filename, pool); /* FIXME: SysV uses 0600... should we? */ tmpfd = shm_open(shm_name, O_RDWR, 0644); if (tmpfd == -1) { return errno; } status = apr_os_file_put(&file, &tmpfd, APR_READ | APR_WRITE, pool); if (status != APR_SUCCESS) { return status; } #elif APR_USE_SHMEM_MMAP_TMP status = apr_file_open(&file, filename, APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } status = apr_os_file_get(&tmpfd, file); if (status != APR_SUCCESS) { return status; } #else return APR_ENOTIMPL; #endif nbytes = sizeof(new_m->realsize); status = apr_file_read(file, (void *)&(new_m->realsize), &nbytes); if (status != APR_SUCCESS) { return status; } status = apr_os_file_get(&tmpfd, file); if (status != APR_SUCCESS) { apr_file_close(file); /* ignore errors, we're failing */ apr_file_remove(new_m->filename, new_m->pool); return status; } new_m->reqsize = new_m->realsize - sizeof(apr_size_t); new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, MAP_SHARED, tmpfd, 0); /* FIXME: check for errors */ status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } /* metadata isn't part of the usable segment */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #elif APR_USE_SHMEM_SHMGET apr_shm_t *new_m; apr_status_t status; apr_file_t *file; /* file where metadata is stored */ apr_size_t nbytes; new_m = apr_palloc(pool, sizeof(apr_shm_t)); status = apr_file_open(&file, filename, APR_FOPEN_READ, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } nbytes = sizeof(new_m->reqsize); status = apr_file_read(file, (void *)&(new_m->reqsize), &nbytes); if (status != APR_SUCCESS) { return status; } status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } new_m->filename = apr_pstrdup(pool, filename); new_m->pool = pool; new_m->shmkey = our_ftok(filename); if (new_m->shmkey == (key_t)-1) { return errno; } if ((new_m->shmid = shmget(new_m->shmkey, 0, SHM_R | SHM_W)) == -1) { return errno; } if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { return errno; } new_m->usable = new_m->base; new_m->realsize = new_m->reqsize; apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #else return APR_ENOTIMPL; #endif } }
APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, apr_size_t reqsize, const char *filename, apr_pool_t *pool) { apr_shm_t *new_m; apr_status_t status; #if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON struct shmid_ds shmbuf; apr_uid_t uid; apr_gid_t gid; #endif #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \ APR_USE_SHMEM_MMAP_ZERO int tmpfd; #endif #if APR_USE_SHMEM_SHMGET apr_size_t nbytes; #endif #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET || \ APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM apr_file_t *file; /* file where metadata is stored */ #endif /* Check if they want anonymous or name-based shared memory */ if (filename == NULL) { #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->reqsize = reqsize; new_m->realsize = reqsize + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */ new_m->filename = NULL; #if APR_USE_SHMEM_MMAP_ZERO status = apr_file_open(&file, "/dev/zero", APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } status = apr_os_file_get(&tmpfd, file); if (status != APR_SUCCESS) { return status; } new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE, MAP_SHARED, tmpfd, 0); if (new_m->base == (void *)MAP_FAILED) { return errno; } status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } /* store the real size in the metadata */ *(apr_size_t*)(new_m->base) = new_m->realsize; /* metadata isn't usable */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #elif APR_USE_SHMEM_MMAP_ANON new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); if (new_m->base == (void *)MAP_FAILED) { return errno; } /* store the real size in the metadata */ *(apr_size_t*)(new_m->base) = new_m->realsize; /* metadata isn't usable */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #endif /* APR_USE_SHMEM_MMAP_ZERO */ #elif APR_USE_SHMEM_SHMGET_ANON new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->reqsize = reqsize; new_m->realsize = reqsize; new_m->filename = NULL; new_m->shmkey = IPC_PRIVATE; if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize, SHM_R | SHM_W | IPC_CREAT)) < 0) { return errno; } if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { return errno; } new_m->usable = new_m->base; if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) { return errno; } apr_uid_current(&uid, &gid, pool); shmbuf.shm_perm.uid = uid; shmbuf.shm_perm.gid = gid; if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) { return errno; } /* Remove the segment once use count hits zero. * We will not attach to this segment again, since it is * anonymous memory, so it is ok to mark it for deletion. */ if (shmctl(new_m->shmid, IPC_RMID, NULL) == -1) { return errno; } apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #else /* It is an error if they want anonymous memory but we don't have it. */ return APR_ENOTIMPL; /* requested anonymous but we don't have it */ #endif } /* Name-based shared memory */ else { new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->reqsize = reqsize; new_m->filename = apr_pstrdup(pool, filename); #if APR_USE_SHMEM_MMAP_SHM const char *shm_name = make_shm_open_safe_name(filename, pool); #endif #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM new_m->realsize = reqsize + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */ /* FIXME: Ignore error for now. * * status = apr_file_remove(file, pool);*/ status = APR_SUCCESS; #if APR_USE_SHMEM_MMAP_TMP /* FIXME: Is APR_OS_DEFAULT sufficient? */ status = apr_file_open(&file, filename, APR_READ | APR_WRITE | APR_CREATE | APR_EXCL, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } status = apr_os_file_get(&tmpfd, file); if (status != APR_SUCCESS) { apr_file_close(file); /* ignore errors, we're failing */ apr_file_remove(new_m->filename, new_m->pool); return status; } status = apr_file_trunc(file, new_m->realsize); if (status != APR_SUCCESS && status != APR_ESPIPE) { apr_file_close(file); /* ignore errors, we're failing */ apr_file_remove(new_m->filename, new_m->pool); return status; } new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, MAP_SHARED, tmpfd, 0); /* FIXME: check for errors */ status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } #endif /* APR_USE_SHMEM_MMAP_TMP */ #if APR_USE_SHMEM_MMAP_SHM /* FIXME: SysV uses 0600... should we? */ tmpfd = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0644); if (tmpfd == -1) { return errno; } status = apr_os_file_put(&file, &tmpfd, APR_READ | APR_WRITE | APR_CREATE | APR_EXCL, pool); if (status != APR_SUCCESS) { return status; } status = apr_file_trunc(file, new_m->realsize); if (status != APR_SUCCESS && status != APR_ESPIPE) { shm_unlink(shm_name); /* we're failing, remove the object */ return status; } new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, MAP_SHARED, tmpfd, 0); /* FIXME: check for errors */ status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } #endif /* APR_USE_SHMEM_MMAP_SHM */ /* store the real size in the metadata */ *(apr_size_t*)(new_m->base) = new_m->realsize; /* metadata isn't usable */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #elif APR_USE_SHMEM_SHMGET new_m->realsize = reqsize; /* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think. */ status = apr_file_open(&file, filename, APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } /* ftok() (on solaris at least) requires that the file actually * exist before calling ftok(). */ new_m->shmkey = our_ftok(filename); if (new_m->shmkey == (key_t)-1) { apr_file_close(file); return errno; } if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize, SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) { apr_file_close(file); return errno; } if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { apr_file_close(file); return errno; } new_m->usable = new_m->base; if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) { apr_file_close(file); return errno; } apr_uid_current(&uid, &gid, pool); shmbuf.shm_perm.uid = uid; shmbuf.shm_perm.gid = gid; if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) { apr_file_close(file); return errno; } nbytes = sizeof(reqsize); status = apr_file_write(file, (const void *)&reqsize, &nbytes); if (status != APR_SUCCESS) { apr_file_close(file); return status; } status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #else return APR_ENOTIMPL; #endif } }
static apr_status_t test_rmm(apr_pool_t *parpool) { apr_status_t rv; apr_pool_t *pool; apr_shm_t *shm; apr_rmm_t *rmm; apr_size_t size, fragsize; apr_rmm_off_t *off; int i; void *entity; rv = apr_pool_create(&pool, parpool); if (rv != APR_SUCCESS) { fprintf(stderr, "Error creating child pool\n"); return rv; } /* We're going to want 10 blocks of data from our target rmm. */ size = SHARED_SIZE + apr_rmm_overhead_get(FRAG_COUNT + 1); printf("Creating anonymous shared memory (%" APR_SIZE_T_FMT " bytes).....", size); rv = apr_shm_create(&shm, size, NULL, pool); if (rv != APR_SUCCESS) { fprintf(stderr, "Error allocating shared memory block\n"); return rv; } fprintf(stdout, "OK\n"); printf("Creating rmm segment............................."); rv = apr_rmm_init(&rmm, NULL, apr_shm_baseaddr_get(shm), size, pool); if (rv != APR_SUCCESS) { fprintf(stderr, "Error allocating rmm..............\n"); return rv; } fprintf(stdout, "OK\n"); fragsize = SHARED_SIZE / FRAG_COUNT; printf("Creating each fragment of size %" APR_SIZE_T_FMT "................", fragsize); off = apr_palloc(pool, FRAG_COUNT * sizeof(apr_rmm_off_t)); for (i = 0; i < FRAG_COUNT; i++) { off[i] = apr_rmm_malloc(rmm, fragsize); } fprintf(stdout, "OK\n"); printf("Checking for out of memory allocation............"); if (apr_rmm_malloc(rmm, FRAG_SIZE * FRAG_COUNT) == 0) { fprintf(stdout, "OK\n"); } else { return APR_EGENERAL; } printf("Checking each fragment for address alignment....."); for (i = 0; i < FRAG_COUNT; i++) { char *c = apr_rmm_addr_get(rmm, off[i]); apr_size_t sc = (apr_size_t)c; if (off[i] == 0) { printf("allocation failed for offset %d\n", i); return APR_ENOMEM; } if (sc & 7) { printf("Bad alignment for fragment %d; %p not %p!\n", i, c, (void *)APR_ALIGN_DEFAULT((apr_size_t)c)); return APR_EGENERAL; } } fprintf(stdout, "OK\n"); printf("Setting each fragment to a unique value.........."); for (i = 0; i < FRAG_COUNT; i++) { int j; char **c = apr_rmm_addr_get(rmm, off[i]); for (j = 0; j < FRAG_SIZE; j++, c++) { *c = apr_itoa(pool, i + j); } } fprintf(stdout, "OK\n"); printf("Checking each fragment for its unique value......"); for (i = 0; i < FRAG_COUNT; i++) { int j; char **c = apr_rmm_addr_get(rmm, off[i]); for (j = 0; j < FRAG_SIZE; j++, c++) { char *d = apr_itoa(pool, i + j); if (strcmp(*c, d) != 0) { return APR_EGENERAL; } } } fprintf(stdout, "OK\n"); printf("Freeing each fragment............................"); for (i = 0; i < FRAG_COUNT; i++) { rv = apr_rmm_free(rmm, off[i]); if (rv != APR_SUCCESS) { return rv; } } fprintf(stdout, "OK\n"); printf("Creating one large segment......................."); off[0] = apr_rmm_calloc(rmm, SHARED_SIZE); fprintf(stdout, "OK\n"); printf("Setting large segment............................"); for (i = 0; i < FRAG_COUNT * FRAG_SIZE; i++) { char **c = apr_rmm_addr_get(rmm, off[0]); c[i] = apr_itoa(pool, i); } fprintf(stdout, "OK\n"); printf("Freeing large segment............................"); apr_rmm_free(rmm, off[0]); fprintf(stdout, "OK\n"); printf("Creating each fragment of size %" APR_SIZE_T_FMT " (again)........", fragsize); for (i = 0; i < FRAG_COUNT; i++) { off[i] = apr_rmm_malloc(rmm, fragsize); } fprintf(stdout, "OK\n"); printf("Freeing each fragment backwards.................."); for (i = FRAG_COUNT - 1; i >= 0; i--) { rv = apr_rmm_free(rmm, off[i]); if (rv != APR_SUCCESS) { return rv; } } fprintf(stdout, "OK\n"); printf("Creating one large segment (again)..............."); off[0] = apr_rmm_calloc(rmm, SHARED_SIZE); fprintf(stdout, "OK\n"); printf("Freeing large segment............................"); apr_rmm_free(rmm, off[0]); fprintf(stdout, "OK\n"); printf("Checking realloc................................."); off[0] = apr_rmm_calloc(rmm, SHARED_SIZE - 100); off[1] = apr_rmm_calloc(rmm, 100); if (off[0] == 0 || off[1] == 0) { printf("FAILED\n"); return APR_EINVAL; } entity = apr_rmm_addr_get(rmm, off[1]); rv = apr_rmm_free(rmm, off[0]); if (rv != APR_SUCCESS) { printf("FAILED\n"); return rv; } { unsigned char *c = entity; /* Fill in the region; the first half with zereos, which will * likely catch the apr_rmm_realloc offset calculation bug by * making it think the old region was zero length. */ for (i = 0; i < 100; i++) { c[i] = (i < 50) ? 0 : i; } } /* now we can realloc off[1] and get many more bytes */ off[0] = apr_rmm_realloc(rmm, entity, SHARED_SIZE - 100); if (off[0] == 0) { printf("FAILED\n"); return APR_EINVAL; } { unsigned char *c = apr_rmm_addr_get(rmm, off[0]); /* fill in the region */ for (i = 0; i < 100; i++) { if (c[i] != (i < 50 ? 0 : i)) { printf("FAILED at offset %d: %hx\n", i, c[i]); return APR_EGENERAL; } } } fprintf(stdout, "OK\n"); printf("Destroying rmm segment..........................."); rv = apr_rmm_destroy(rmm); if (rv != APR_SUCCESS) { printf("FAILED\n"); return rv; } printf("OK\n"); printf("Destroying shared memory segment................."); rv = apr_shm_destroy(shm); if (rv != APR_SUCCESS) { printf("FAILED\n"); return rv; } printf("OK\n"); apr_pool_destroy(pool); return APR_SUCCESS; }
void heap_anticipate_need(heap_t *hp, int size) { size = APR_ALIGN_DEFAULT(size); heap_secure_space(hp, size); }