Return-Path: Delivered-To: apmail-apr-dev-archive@apr.apache.org Received: (qmail 26274 invoked by uid 500); 12 Sep 2001 21:22:53 -0000 Mailing-List: contact dev-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Delivered-To: mailing list dev@apr.apache.org Received: (qmail 26260 invoked from network); 12 Sep 2001 21:22:53 -0000 Message-ID: From: "MATHIHALLI,MADHUSUDAN (HP-Cupertino,ex1)" To: dev@httpd.apache.org, "'dev@apr.apache.org'" Subject: [PATCH] shmem.c - again Date: Wed, 12 Sep 2001 14:22:08 -0700 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2653.19) Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01C13BD0.FA843810" X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01C13BD0.FA843810 Content-Type: text/plain; charset="iso-8859-1" Hi, I've modified the shmem.c to have a another shared memory segment for storing the allocation details. I've also tried to ensure that all the computation is based on offsets (stored in the shared memory again) - so that if different processes map the shared memory at different addresses, the memory mgmt should still work. As regards testing, I've done some minimal testing (testshmem, shmcb, shmht) - but there may be lots of problems.. Also, the code may require perf. tuning - I haven't yet looked into those aspects.. Pl. let me know for any clarifications.. 'waiting for your feedback / suggestions.. Thanks -Madhu -----Original Message----- From: Ryan Bloom [mailto:rbb@covalent.net] Sent: Sunday, September 09, 2001 5:39 PM To: dev@httpd.apache.org; MATHIHALLI,MADHUSUDAN (HP-Cupertino,ex1); 'dev@httpd.apache.org' Subject: Re: FW: [PATCH] shmem.c On Sunday 09 September 2001 17:23, MATHIHALLI,MADHUSUDAN (HP-Cupertino,ex1) wrote: > Hi Ian, > Thanks for the suggestion.. I certainly like the first idea (infact, that > was also one of the idea I'd proposed earlier). But, I'm not sure how > *open* are others to create a seperate shared memory just for maintaining > the allocation table.. The only problem is going to be ensuring that the platform has enough shared memory to handle both segments. I think we can just return an error if we run out of shared memory though. IOW, +1 for having a second shared memory segment for the control data. Ryan > > As regards your second idea, I'm not comfortable with it - it'd introduce a > lot of performance overhead - especially with IPC's around.. > > Thanks for your suggestions.. > -Madhu > > > -----Original Message----- > From: Ian Holsman [mailto:ianh@cnet.com] > Sent: Sunday, September 09, 2001 3:54 PM > To: dev@httpd.apache.org > Subject: Re: FW: [PATCH] shmem.c > > > Hi Madhu. > the only way I can think of handling this is to store the memory > block list in another piece of shared memory/mmap (allocated seperatly) > > The other method I can think of is to spawn a seperate process which > would hold all the memory list information, and it would do all the memory > management > and the other processes would communicate it via some IPC. > > the problem is that shared memory is NOT guarnteed to be in the same space > for > each process. > > ..Ian > ------_=_NextPart_000_01C13BD0.FA843810 Content-Type: text/plain; name="patch_shmem_1.txt" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="patch_shmem_1.txt" Index: shmem.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvspublic/apr/shmem/unix/shmem.c,v retrieving revision 1.33 diff -u -r1.33 shmem.c --- shmem.c 2001/08/30 17:11:04 1.33 +++ shmem.c 2001/09/12 21:07:29 @@ -89,182 +89,593 @@ #include #endif =20 +#define MIN_BLK_SIZE 200 + +/**********************************************************************= ***** +The Shared Memory - Management Architecture : + +List Memory (Shared Memory - 1) + ____________________________________________ + | Memory Offsets for the List and | + | for the Shared Memory | + |------------------------------------------| +L1 | MemChunk(MC1) |Next| MemChunk(MC2) |Next | + |------------------------------------------| + |------------------------------------------| +L2 | MemChunk(MC3) |Next| MemChunk(MC4) |Next | + |------------------------------------------| + ______| . . . . . . . + | . . . . . . . . + | . . . . . . . . + | |------------------------------------------| +Ln | | MemChunk(MCm) |Next| ...... | + | |------------------------------------------| + | | + | |________________________________________ + V | (offset from = shm_base) +Chunk Memory (Shared Memory - 2) V +-----------------------------------------------------------------------= -- +| | | | | | = | +| C1 | C2 | C3 | C4 | C5 |.... = | +| | | | | | = | +-----------------------------------------------------------------------= -- + +***********************************************************************= ****/ + + +typedef struct memoffsets_t { + apr_off_t l_used; /* Starting of the Used list elements = */ + apr_off_t l_free; /* Starting of the Freed list elements = */ + apr_off_t l_usedlast; /* Last element of the Used list */ + apr_off_t l_freelast; /* Last element of the Freed list */ + apr_off_t c_used; /* Begining of the used chunk list */ + apr_off_t c_free; /* Begining of the freed chunk list */ + apr_off_t shm_offset; /* The current offset of the shared = memory */ + apr_off_t shm_length; /* Total length of shared memory = available */ +} memoffsets_t; + +typedef struct memchunk_t { + apr_off_t offset; /* Offset of the chunk - from = m->shm_base */ + apr_size_t size; /* Size of the chunk */ + apr_off_t next; /* Next chunk - from m->list_base) */ + apr_off_t prev; /* Previous chunk - from m->list_base) = */ +} memchunk_t; + +typedef struct memlist_t { + struct memchunk_t chunk; + apr_off_t next; +} memlist_t; + struct shmem_t { - void *mem; - void *curmem; - apr_size_t length; - apr_lock_t *lock; - char *filename; + apr_pool_t *p; + void *shm_base; /* Starting address of the shared = memory */ + memoffsets_t *offsets; /* Begining of the set of offsets */ + memlist_t *list_base; /* Begining of the list elements */ + + apr_lock_t *lock; + char *filename; #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || = APR_USE_SHMEM_MMAP_ZERO - apr_file_t *file;=20 -#elif APR_USE_SHMEM_MMAP_ANON - /* Nothing else. */ + apr_file_t *file;=20 #elif APR_USE_SHMEM_SHMGET - apr_os_file_t file; + apr_os_file_t file; + apr_os_file_t listfd; #elif APR_USE_SHMEM_BEOS - area_id areaid;=20 + area_id areaid;=20 #endif }; =20 +#define SHM_ADDR(offset) ((offset < 0) ? (void *)NULL : \ + (void *)((unsigned char *)m->shm_base + offset)) + +#define CHUNK_OFFSET(ptr) ((ptr =3D=3D (memchunk_t *)NULL) ? 0 : \ + ((unsigned char *)ptr - (unsigned char *)m->list_base)) + +#define CHUNK_ADDR(offset) ((offset < 0) ? (memchunk_t *)NULL : \ + (memchunk_t *)((unsigned char *)m->list_base + offset)) + +#define LIST_OFFSET(ptr) ((ptr =3D=3D (memlist_t *)NULL) ? 0 : \ + ((unsigned char *)ptr - (unsigned char *)m->list_base) + +#define LIST_INDEX(ptr) ((ptr =3D=3D (memlist_t *)NULL) ? -1 : \ + (((unsigned char *)ptr - (unsigned char = *)m->list_base)/sizeof(memlist_t))) + +#define LIST_ADDR(idx) ((idx < 0) ? (memlist_t *)NULL : \ + (memlist_t *)((unsigned char *)m->list_base + (idx * = sizeof(memlist_t)))) + +static memchunk_t *list_malloc (apr_shmem_t *m) +{ + apr_off_t index; + memlist_t *elem, *last; + + /* Find the first free list element */ + if ((elem =3D LIST_ADDR(m->offsets->l_free)) =3D=3D (memlist_t = *)NULL) + return (memchunk_t *)NULL; + else { + index =3D m->offsets->l_free; + m->offsets->l_free =3D elem->next; + } + + elem->next =3D -1; + + if (m->offsets->l_used =3D=3D -1) + m->offsets->l_used =3D index; + else { + last =3D LIST_ADDR(m->offsets->l_usedlast); + last->next =3D index; + } + + m->offsets->l_usedlast =3D index; + + return (&(elem->chunk)); +} + +static apr_status_t list_free (apr_shmem_t *m, memchunk_t *chunk) +{ + apr_off_t index; + memlist_t *elem, *iter; + + /* Find the required element in the allocated list */ + iter =3D LIST_ADDR(m->offsets->l_used); + while (iter && (&(iter->chunk) !=3D chunk)) { + elem =3D iter; + index =3D iter->next; + iter =3D LIST_ADDR(iter->next); + } + =20 + if ((!iter) || (&(iter->chunk) !=3D chunk)) + return -1; + else + elem->next =3D iter->next; + + iter->next =3D -1; + + if (m->offsets->l_free =3D=3D -1) + m->offsets->l_free =3D index; + else { + elem =3D LIST_ADDR(m->offsets->l_freelast); + elem->next =3D index; + } + + m->offsets->l_freelast =3D index; + + return APR_SUCCESS; +} + +static void add_chunk (apr_shmem_t *m, apr_off_t *list, memchunk_t = *blk) +{ + memchunk_t *elem; + if (*list =3D=3D -1) + *list =3D CHUNK_OFFSET(blk); + + elem =3D CHUNK_ADDR(*list); + + if (blk =3D=3D elem){ + blk->prev =3D CHUNK_OFFSET(blk); + blk->next =3D CHUNK_OFFSET(blk); + } else { + (CHUNK_ADDR(elem->prev))->next =3D CHUNK_OFFSET(blk); + blk->prev =3D elem->prev; + blk->next =3D CHUNK_OFFSET(elem); + elem->prev =3D CHUNK_OFFSET(blk); + } +} + +static void remove_chunk(apr_shmem_t *m, apr_off_t *list, memchunk_t = *blk) +{ + memchunk_t *elem; + + elem =3D CHUNK_ADDR(*list); + + if ((elem =3D=3D blk) + && (CHUNK_ADDR(blk->next) =3D=3D blk) && (blk =3D=3D = CHUNK_ADDR(blk->prev))) { + *list =3D -1; + } else { + (CHUNK_ADDR(blk->next))->prev =3D blk->prev; + (CHUNK_ADDR(blk->prev))->next =3D blk->next; + if (elem =3D=3D blk) + *list =3D blk->next; + } + blk->next =3D -1; + blk->prev =3D -1; +} + +static void split_chunk( + apr_shmem_t *m, apr_off_t *list, memchunk_t *blk, apr_size_t = size) +{ + memchunk_t *b; + + b =3D list_malloc (m); + if (b !=3D (memchunk_t *)NULL) { + b->size =3D blk->size - size; + b->offset =3D blk->offset + size; + blk->size =3D size; + add_chunk(m, list, b); + } +} + +static memchunk_t *find_chunk_by_addr( + apr_shmem_t *m, apr_off_t *list, void *addr) +{ + memchunk_t *iter =3D CHUNK_ADDR(*list); + + if (!iter) return NULL; + + do { + if (SHM_ADDR(iter->offset) =3D=3D addr) + return iter; + } while (iter && ((iter =3D CHUNK_ADDR(iter->next)) !=3D = CHUNK_ADDR(*list))); + + return NULL; +} + +static memchunk_t *find_chunk_by_size( + apr_shmem_t *m, apr_off_t *list, apr_size_t size) +{ + apr_size_t diff =3D -1; + memchunk_t *iter =3D CHUNK_ADDR(*list), *found =3D NULL; + + if (!iter) return NULL; + + do { + if (iter->size =3D=3D size) + return iter; + if (iter->size > size) { + if (diff =3D=3D -1) + diff =3D iter->size; + if ((iter->size - size) < diff) { + diff =3D iter->size - size; + found =3D iter; + } + } + } while ((iter =3D CHUNK_ADDR(iter->next)) !=3D = CHUNK_ADDR(*list)); + + if (diff > MIN_BLK_SIZE) + split_chunk(m, list, found, size); + + return found; +} + +static void display_shm_snapshot(apr_shmem_t *m) +{ +#if 0 + memchunk_t *iter; + + extern ap_log_error (); + if (!m) return; + + if ((iter =3D CHUNK_ADDR(m->offsets->c_used)) !=3D NULL) { + ap_log_error(__FILE__, __LINE__, 3, 0, NULL, "USELIST :"); + do { + ap_log_error(__FILE__, __LINE__, 3, 0, NULL,"[%ld] [%ld] = [%ld]", + iter->offset, iter->next, iter->size); + } while (iter && + ((iter =3D CHUNK_ADDR(iter->next)) !=3D = CHUNK_ADDR(m->offsets->c_used))); + } + + if ((iter =3D CHUNK_ADDR(m->offsets->c_free)) !=3D NULL) { + ap_log_error(__FILE__, __LINE__, 3, 0, NULL,"FREELIST :"); + do { + ap_log_error(__FILE__, __LINE__, 3, 0, NULL,"[%ld] [%ld] = [%ld]", + iter->offset, iter->next, iter->size); + } while (iter && + ((iter =3D CHUNK_ADDR(iter->next)) !=3D = CHUNK_ADDR(m->offsets->c_free))); + } + ap_log_error(__FILE__, __LINE__, 3, 0, NULL,""); +#endif + return; +} + +static memchunk_t *alloc_chunk(apr_shmem_t *m, apr_size_t size) +{ + memchunk_t *b =3D NULL; + + /* Align size to a word boundary */ + if (size < MIN_BLK_SIZE) + size =3D MIN_BLK_SIZE; + size =3D ((1 + ((size - 1) / sizeof (void *))) * sizeof (void *)); + + if (m->offsets->shm_length < size) + return NULL; + + b =3D find_chunk_by_size (m, &(m->offsets->c_free), size); + + if (b !=3D (memchunk_t *)NULL) + remove_chunk (m, &(m->offsets->c_free), b); + else { + b =3D list_malloc(m); + if (b =3D=3D (memchunk_t *)NULL) + return (memchunk_t *)NULL; + b->offset =3D m->offsets->shm_offset; + b->size =3D size; + m->offsets->shm_offset +=3D b->size; + } + + m->offsets->shm_length -=3D b->size; + add_chunk(m, &(m->offsets->c_used), b); + + display_shm_snapshot (m); + + return b; +} + +static void free_chunk(apr_shmem_t *m, void *entity) +{ + memchunk_t *b; + + if (entity =3D=3D NULL) + return; + + b =3D find_chunk_by_addr (m, &(m->offsets->c_used), entity); + if (b !=3D (memchunk_t *)NULL) { + remove_chunk(m, &(m->offsets->c_used), b); + add_chunk(m, &(m->offsets->c_free), b); + m->offsets->shm_length +=3D b->size; + } + + display_shm_snapshot (m); +} + +static memchunk_t *realloc_chunk(apr_shmem_t *m, void *entity, = apr_size_t size) +{ + memchunk_t *b, *new_b; + + /* Align size to a word boundary */ + size =3D ((1 + ((size - 1) / sizeof (void *))) * sizeof (void *)); + + b =3D find_chunk_by_addr(m, &(m->offsets->c_used), entity); + + if (b !=3D (memchunk_t *)NULL) { + if (b->size > size) + split_chunk (m, &(m->offsets->c_used), b, size); + else + if ((b->size < size) && (size < m->offsets->shm_length)) { + new_b =3D alloc_chunk (m, size); + memcpy (SHM_ADDR(new_b->offset), SHM_ADDR(b->offset), = b->size); + free_chunk (m, entity); + b =3D new_b; + } + } + return b; +} + +/*=20 + * FIXME:=20 + * 1. Is APR_OS_DEFAULT sufficient?=20 + * 2. status =3D apr_file_remove(filename, p); + * 3. Handle errors from return values of system calls. + */ APR_DECLARE(apr_status_t) apr_shm_init(apr_shmem_t **m, apr_size_t = reqsize,=20 - const char *filename, = apr_pool_t *pool) + const char *filename, apr_pool_t= *p) { - apr_shmem_t *new_m; - void *mem; #if APR_USE_SHMEM_SHMGET struct shmid_ds shmbuf; apr_uid_t uid; apr_gid_t gid; + int i, listsize; + memlist_t *iter, *piter; + void *addr; #endif + #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || = APR_USE_SHMEM_MMAP_ZERO apr_status_t status; + status =3D APR_SUCCESS; #endif + #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \ APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET int tmpfd; #endif =20 - new_m =3D apr_palloc(pool, sizeof(apr_shmem_t)); - if (!new_m) + (*m) =3D (apr_shmem_t *)apr_palloc(p, sizeof(apr_shmem_t)); + if (!(*m)) return APR_ENOMEM; =20 -/* These implementations are very similar except for opening the file. = */ #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || = APR_USE_SHMEM_MMAP_ZERO - /* FIXME: Ignore error for now. * - * status =3D apr_file_remove(filename, pool);*/ - status =3D APR_SUCCESS; =20 #if APR_USE_SHMEM_MMAP_TMP - /* FIXME: Is APR_OS_DEFAULT sufficient? */ - status =3D apr_file_open(&new_m->file, filename,=20 - APR_READ | APR_WRITE | APR_CREATE, = APR_OS_DEFAULT, - pool); + status =3D apr_file_open(&(*m)->file, filename,=20 + APR_READ | APR_WRITE | APR_CREATE, = APR_OS_DEFAULT, p); if (status !=3D APR_SUCCESS) return APR_EGENERAL; =20 - status =3D apr_os_file_get(&tmpfd, new_m->file); - status =3D apr_file_trunc(new_m->file, reqsize); + status =3D apr_os_file_get(&tmpfd, (*m)->file); + status =3D apr_file_trunc((*m)->file, reqsize); if (status !=3D APR_SUCCESS) return APR_EGENERAL; =20 #elif APR_USE_SHMEM_MMAP_SHM - /* FIXME: Is APR_OS_DEFAULT sufficient? */ tmpfd =3D shm_open(filename, O_RDWR | O_CREAT, APR_OS_DEFAULT); if (tmpfd =3D=3D -1) return errno; =20 - apr_os_file_put(&new_m->file, &tmpfd, pool);=20 - status =3D apr_file_trunc(new_m->file, reqsize); + apr_os_file_put(&(*m)->file, &tmpfd, p);=20 + status =3D apr_file_trunc((*m)->file, reqsize); if (status !=3D APR_SUCCESS) { shm_unlink(filename); return APR_EGENERAL; } #elif APR_USE_SHMEM_MMAP_ZERO - status =3D apr_file_open(&new_m->file, "/dev/zero", APR_READ | = APR_WRITE,=20 - APR_OS_DEFAULT, pool); + status =3D apr_file_open(&(*m)->file, "/dev/zero", APR_READ | = APR_WRITE,=20 + APR_OS_DEFAULT, p); if (status !=3D APR_SUCCESS) return APR_EGENERAL; - status =3D apr_os_file_get(&tmpfd, new_m->file); + status =3D apr_os_file_get(&tmpfd, (*m)->file); #endif =20 - mem =3D mmap(NULL, reqsize, PROT_READ|PROT_WRITE, MAP_SHARED, = tmpfd, 0); + (*m)->shm_base =3D mmap(NULL, reqsize, PROT_READ|PROT_WRITE, + MAP_SHARED, tmpfd, = 0); =20 #elif APR_USE_SHMEM_MMAP_ANON - mem =3D mmap(NULL, reqsize, PROT_READ|PROT_WRITE, = MAP_ANON|MAP_SHARED, -1, 0); + (*m)->shm_base =3D mmap(NULL, reqsize, PROT_READ|PROT_WRITE, + = MAP_ANON|MAP_SHARED,-1, 0); #elif APR_USE_SHMEM_SHMGET - tmpfd =3D shmget(IPC_PRIVATE, reqsize, (SHM_R|SHM_W|IPC_CREAT)); - if (tmpfd =3D=3D -1) - return errno; =20 - new_m->file =3D tmpfd; + listsize =3D (reqsize/MIN_BLK_SIZE + 1) * sizeof(memlist_t)=20 + + sizeof (memoffsets_t); + (*m)->listfd =3D shmget(IPC_PRIVATE, listsize, = (SHM_R|SHM_W|IPC_CREAT)); + if ((*m)->listfd =3D=3D -1) + return errno + APR_OS_START_SYSERR; + + addr =3D (void *)shmat((*m)->listfd, NULL, 0); + if (addr =3D=3D (void *)NULL) + return errno + APR_OS_START_SYSERR; + + (*m)->offsets =3D (memoffsets_t *)addr; + (*m)->list_base =3D (memlist_t *)(addr + (sizeof(memoffsets_t))); + + (*m)->file =3D shmget(IPC_PRIVATE, reqsize, = (SHM_R|SHM_W|IPC_CREAT)); + if ((*m)->file =3D=3D -1) + return errno + APR_OS_START_SYSERR; + + (*m)->shm_base =3D (void *)shmat((*m)->file, NULL, 0); + if ((*m)->shm_base =3D=3D (void *)NULL) + return errno + APR_OS_START_SYSERR; =20 - mem =3D shmat(new_m->file, NULL, 0); - - /* FIXME: Handle errors. */ - if (shmctl(new_m->file, IPC_STAT, &shmbuf) =3D=3D -1) + if (shmctl((*m)->file, IPC_STAT, &shmbuf) =3D=3D -1) return errno; =20 - apr_current_userid(&uid, &gid, pool); + apr_current_userid(&uid, &gid, p); shmbuf.shm_perm.uid =3D uid; shmbuf.shm_perm.gid =3D gid; =20 - if (shmctl(new_m->file, IPC_SET, &shmbuf) =3D=3D -1) - return errno; + if (shmctl((*m)->file, IPC_SET, &shmbuf) =3D=3D -1) + return errno + APR_OS_START_SYSERR; =20 - /* remove in future (once use count hits zero) */ - if (shmctl(new_m->file, IPC_RMID, NULL) =3D=3D -1) - return errno; + if (shmctl((*m)->listfd, IPC_SET, &shmbuf) =3D=3D -1) + return errno + APR_OS_START_SYSERR; =20 + /* Initially all elements after the first element is a free block = */ + piter =3D (*m)->list_base; + for (i =3D 0; i < reqsize/MIN_BLK_SIZE; i++) { + piter->next =3D i + 1; + piter++; + } + piter->next =3D -1; + + (*m)->offsets->l_used =3D -1; + (*m)->offsets->l_usedlast =3D -1; + (*m)->offsets->l_free =3D 0; + (*m)->offsets->l_freelast =3D i; + (*m)->offsets->c_used =3D -1; + (*m)->offsets->c_free =3D -1; + #elif APR_USE_SHMEM_BEOS - new_m->area_id =3D create_area("mm", (void*)&mem, B_ANY_ADDRESS, = reqsize,=20 - B_LAZY_LOCK, = B_READ_AREA|B_WRITE_AREA); - /* FIXME: error code? */ - if (new_m->area_id < 0) - return APR_EGENERAL; =20 + (*m)->area_id =3D create_area("apr_shm", (void*)&((*m)->shm_base), = B_ANY_ADDRESS, + reqsize, B_LAZY_LOCK, = B_READ_AREA|B_WRITE_AREA); + if ((*m)->area_id < 0) + return APR_EGENERAL; /* FIXME: error code? */ #endif =20 - new_m->mem =3D mem; - new_m->curmem =3D mem; - new_m->length =3D reqsize; + (*m)->p =3D p; + (*m)->offsets->shm_offset =3D 0; + (*m)->offsets->shm_length =3D reqsize; =20 - apr_lock_create(&new_m->lock, APR_MUTEX, APR_CROSS_PROCESS, NULL, = pool); - if (!new_m->lock) + apr_lock_create(&(*m)->lock, APR_MUTEX, APR_CROSS_PROCESS, NULL, = p); + if (!(*m)->lock) return APR_EGENERAL; =20 - *m =3D new_m;=20 return APR_SUCCESS; } =20 APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shmem_t *m) { +#if APR_USE_SHMEM_SHMGET + struct shmid_ds shmbuf; + apr_uid_t uid; + apr_gid_t gid; +#endif + + if (m =3D=3D (apr_shmem_t *)NULL) + return APR_SUCCESS; + #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || = APR_USE_SHMEM_MMAP_ZERO - munmap(m->mem, m->length); + munmap(m->shm_base, m->offsets->shm_length); apr_file_close(m->file); #elif APR_USE_SHMEM_MMAP_ANON - munmap(m->mem, m->length); + munmap(m->shm_base, m->offsets->shm_length); #elif APR_USE_SHMEM_SHMGET - shmdt(m->mem); + shmdt(m->shm_base); + apr_current_userid(&uid, &gid, m->p); + shmbuf.shm_perm.uid =3D uid; + shmbuf.shm_perm.gid =3D gid; + + if (shmctl(m->file, IPC_RMID, &shmbuf) =3D=3D -1) + return errno + APR_OS_START_SYSERR; + + shmdt(m->list_base); + if (shmctl(m->listfd, IPC_RMID, &shmbuf) =3D=3D -1) + return errno + APR_OS_START_SYSERR; + #elif APR_USE_SHMEM_BEOS - delete_area(new_m->area_id); + delete_area(m->area_id); #endif =20 + m->offsets =3D NULL; + m->shm_base =3D NULL; + return APR_SUCCESS; } =20 APR_DECLARE(void *) apr_shm_malloc(apr_shmem_t *m, apr_size_t reqsize) { - void *new; - new =3D NULL; + memchunk_t *b =3D (memchunk_t *)NULL; =20 - apr_lock_acquire(m->lock); - /* Do we have enough space? */ - if (((char *)m->curmem - (char *)m->mem + reqsize) <=3D m->length) + if (m !=3D (apr_shmem_t *)NULL) { - new =3D m->curmem; - m->curmem =3D (char *)m->curmem + reqsize; + apr_lock_acquire(m->lock); + b =3D alloc_chunk(m, reqsize); + apr_lock_release(m->lock); } - apr_lock_release(m->lock); - return new; + + return ((b) ? SHM_ADDR(b->offset) : NULL); } =20 APR_DECLARE(void *) apr_shm_calloc(apr_shmem_t *m, apr_size_t reqsize) = { - void *new =3D apr_shm_malloc(m, reqsize); - if (new) - memset(new, '\0', reqsize); - return new; + memchunk_t *b =3D (memchunk_t *)NULL; + + if (m !=3D (apr_shmem_t *)NULL) + { + apr_lock_acquire(m->lock); + b =3D alloc_chunk(m, reqsize); + if (b !=3D NULL) + memset(SHM_ADDR(b->offset), 0, reqsize); + apr_lock_release(m->lock); + } + return ((b) ? SHM_ADDR(b->offset) : NULL); +} + +APR_DECLARE(void *) apr_shm_realloc(apr_shmem_t *m, void *p, = apr_size_t reqsize) +{ + memchunk_t *b =3D (memchunk_t *)NULL; + =20 + if (m !=3D (apr_shmem_t *)NULL) + { + apr_lock_acquire(m->lock); + if (p !=3D NULL) + b =3D realloc_chunk(m, p, reqsize); + else=20 + b =3D alloc_chunk(m, reqsize); + apr_lock_release(m->lock); + } + + return ((b) ? SHM_ADDR(b->offset) : NULL); } =20 -APR_DECLARE(apr_status_t) apr_shm_free(apr_shmem_t *shared, void = *entity) +APR_DECLARE(apr_status_t) apr_shm_free(apr_shmem_t *m, void *entity) { - /* Without a memory management scheme within our shared memory, it - * is impossible to implement free. */ + if (m !=3D (apr_shmem_t *)NULL) + { + apr_lock_acquire(m->lock); + free_chunk(m, entity); + apr_lock_release(m->lock); + } return APR_SUCCESS; } =20 -APR_DECLARE(apr_status_t) apr_shm_name_get(apr_shmem_t *c,=20 +APR_DECLARE(apr_status_t) apr_shm_name_get(apr_shmem_t *m,=20 apr_shm_name_t **name) { #if APR_USES_ANONYMOUS_SHM @@ -280,7 +691,7 @@ #endif } =20 -APR_DECLARE(apr_status_t) apr_shm_name_set(apr_shmem_t *c,=20 +APR_DECLARE(apr_status_t) apr_shm_name_set(apr_shmem_t *m,=20 apr_shm_name_t *name) { #if APR_USES_ANONYMOUS_SHM @@ -295,7 +706,7 @@ #endif } =20 -APR_DECLARE(apr_status_t) apr_shm_open(apr_shmem_t *c) +APR_DECLARE(apr_status_t) apr_shm_open(apr_shmem_t *m) { #if APR_USES_ANONYMOUS_SHM =20 @@ -315,16 +726,16 @@ =20 APR_DECLARE(apr_status_t) apr_shm_avail(apr_shmem_t *m, apr_size_t = *size) { - apr_status_t status; - - status =3D APR_ENOSHMAVAIL; + apr_status_t status =3D APR_ENOSHMAVAIL; =20 - apr_lock_acquire(m->lock); + if (m !=3D (apr_shmem_t *)NULL) + { + apr_lock_acquire(m->lock); + if ((*size =3D m->offsets->shm_length) > 0) + status =3D APR_SUCCESS; =20 - *size =3D m->length - ((char *)m->curmem - (char *)m->mem); - if (*size) - status =3D APR_SUCCESS; + apr_lock_release(m->lock); + } =20 - apr_lock_release(m->lock); return status; } ------_=_NextPart_000_01C13BD0.FA843810--