diff options
author | rbb <rbb@13f79535-47bb-0310-9956-ffa450edef68> | 2000-01-27 23:49:36 +0000 |
---|---|---|
committer | rbb <rbb@13f79535-47bb-0310-9956-ffa450edef68> | 2000-01-27 23:49:36 +0000 |
commit | 6ddb2a0687ccf361a99bc96229dc15dec2b0f062 (patch) | |
tree | cc0a45fe032e8c6b3014a8ff18cf2edf5108194a | |
parent | 0fcaf05d5135154704e005d6a3ca2ee71fa9eee9 (diff) | |
download | libapr-6ddb2a0687ccf361a99bc96229dc15dec2b0f062.tar.gz |
A first pass at shared memory for Unix. This is still pretty ugly, but I
will clean it up over the next few days. At least this gives everybody
some idea of where I want the shared memory stuff to go in APR.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@59625 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | configure.in | 16 | ||||
-rw-r--r-- | include/apr.h.in | 5 | ||||
-rw-r--r-- | include/apr_errno.h | 4 | ||||
-rw-r--r-- | include/apr_shmem.h | 31 | ||||
-rw-r--r-- | shmem/unix/Makefile.in | 5 | ||||
-rw-r--r-- | shmem/unix/shmem.c | 198 | ||||
-rw-r--r-- | test/Makefile.in | 6 | ||||
-rw-r--r-- | test/testshmem.c (renamed from shmem/shmem.c) | 150 |
8 files changed, 247 insertions, 168 deletions
diff --git a/configure.in b/configure.in index 4d8fe4f3b..364be5a5d 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ OS=`./config.sub $OS` # These added to allow default directories to be used... DEFAULT_OSDIR="unix" -MODULES="file_io network_io threadproc misc locks time mmap" +MODULES="file_io network_io threadproc misc locks time mmap shmem" echo "Configuring APR library" echo "Platform: ${OS}" @@ -357,6 +357,15 @@ else procpthreadser="0" fi +# Shared memory support. Until I figure out how to do this well, we are hard +# coding this. I am hoping to do this more generally ASAP. +anonymous_shm="1" +filebased_shm="0" +keybased_shm="0" +AC_SUBST(anonymous_shm) +AC_SUBST(filebased_shm) +AC_SUBST(keybased_shm) + dnl Start building stuff from our information AC_SUBST(LDLIBS) AC_SUBST(OPTIM) @@ -400,6 +409,11 @@ if test "$ac_cv_struct_tm_gmtoff" = "yes"; then AC_DEFINE(HAVE_GMTOFF) fi +# run the MM config script regardless of whether we are going to use +# it or not. When we have a much better idea of who is using MM, we can +# run this on a more conditional basis. +AC_CONFIG_SUBDIRS(shmem/unix/mm) + MAKEFILE1="Makefile lib/Makefile " SUBDIRS="lib " for dir in $MODULES diff --git a/include/apr.h.in b/include/apr.h.in index 298b14415..f70b435df 100644 --- a/include/apr.h.in +++ b/include/apr.h.in @@ -40,6 +40,11 @@ #define APR_USE_PROC_PTHREAD_SERIALIZE @procpthreadser@ #define APR_USE_PTHREAD_SERIALIZE @pthreadser@ +#define APR_USES_ANONYMOUS_SHM @anonymous_shm@ +#define APR_USES_FILEBASED_SHM @filebased_shm@ +#define APR_USES_KEYBASED_SHM @keybased_shm@ + + #define APR_HAVE_IN_ADDR @have_in_addr@ #define APR_HAVE_INET_ADDR @inet_addr@ #define APR_HAVE_INET_NETWORK @inet_network@ diff --git a/include/apr_errno.h b/include/apr_errno.h index fa3d14b12..a5be9532b 100644 --- a/include/apr_errno.h +++ b/include/apr_errno.h @@ -107,6 +107,7 @@ typedef int ap_status_t; #define APR_ENOTHREAD (APR_OS_START_ERROR + 12) #define APR_ENOTHDKEY (APR_OS_START_ERROR + 13) #define APR_ENOTTHREADSAFE (APR_OS_START_ERROR + 14) +#define APR_ESHMLOCK (APR_OS_START_ERROR + 15) /* APR STATUS VALUES */ #define APR_INCHILD (APR_OS_START_STATUS + 1) @@ -127,6 +128,9 @@ typedef int ap_status_t; #define APR_LESS (APR_OS_START_STATUS + 16) #define APR_EQUAL (APR_OS_START_STATUS + 17) #define APR_MORE (APR_OS_START_STATUS + 18) +#define APR_ANONYMOUS (APR_OS_START_STATUS + 19) +#define APR_FILEBASED (APR_OS_START_STATUS + 20) +#define APR_KEYBASED (APR_OS_START_STATUS + 21) /* A simple value to be used to initialze a status variable. */ #define APR_EINIT (APR_OS_START_STATUS + 16) diff --git a/include/apr_shmem.h b/include/apr_shmem.h index d207c3dff..3595da3b5 100644 --- a/include/apr_shmem.h +++ b/include/apr_shmem.h @@ -56,6 +56,7 @@ #ifndef APR_SHMEM_H #define APR_SHMEM_H +#include "apr.h" #include "apr_general.h" #include "apr_errno.h" @@ -63,19 +64,25 @@ extern "C" { #endif /* __cplusplus */ -typedef struct shmem_t ap_shmem_t +#if APR_USES_ANONYMOUS_SHM +typedef void ap_shm_name_t; +#elif APR_USES_FILEBASED_SHM +typedef char * ap_shm_name_t; +#elif APR_USES_KEYBASED_SHM +typedef key_t ap_shm_name_t; +#endif + +typedef struct shmem_t ap_shmem_t; -ap_status_t ap_shm_create(ap_shmem_t **, ap_context_t *, ap_size_t, const char *); -ap_status_t ap_shm_destroy(ap_shmem_t *); -ap_status_t ap_shm_malloc(void **, ap_shmem_t *, ap_size_t); -ap_status_t ap_shm_calloc(void **, ap_shmem_t *, ap_size_t, ap_size_t); -ap_status_t ap_shm_realloc(void **, ap_shmem_t *, ap_size_t); -ap_status_t ap_shm_free(ap_shmem_t *, void *); -ap_status_t ap_shm_strdup(char **, ap_shmem_t *, const char *); -ap_status_t ap_shm_sizeof(ap_shmem_t *, void *, ap_size_t *); -ap_status_t ap_shm_maxsize(ap_size_t *); -ap_status_t ap_shm_available(ap_shmem_t *, ap_size_t *); -ap_status_t ap_shm_child_create(ap_shmem_t**, ap_context_t *, const char *); +ap_status_t ap_shm_init(ap_shmem_t **m, ap_size_t reqsize, const char *file); +ap_status_t ap_shm_destroy(ap_shmem_t *m); +void *ap_shm_malloc(ap_shmem_t *c, ap_size_t reqsize); +void *ap_shm_calloc(ap_shmem_t *shared, ap_size_t size); +ap_status_t ap_shm_free(ap_shmem_t *shared, void *free); +ap_status_t ap_get_shm_name(ap_shmem_t *c, ap_shm_name_t **name); +ap_status_t ap_set_shm_name(ap_shmem_t *c, ap_shm_name_t *name); +ap_status_t ap_open_shmem(ap_shmem_t *c); +ap_status_t ap_shm_avail(ap_shmem_t *c, ap_size_t *avail); #ifdef __cplusplus } diff --git a/shmem/unix/Makefile.in b/shmem/unix/Makefile.in index b96e8b404..c30988938 100644 --- a/shmem/unix/Makefile.in +++ b/shmem/unix/Makefile.in @@ -11,7 +11,8 @@ LIBS=@LIBS@ LDFLAGS=@LDFLAGS@ $(LIBS) INCDIR=../../inc INCDIR1=../../include -INCLUDES=-I$(INCDIR) -I$(INCDIR1) -Imm -I. +INCDIR2=../../misc/@OSDIR@ +INCLUDES=-I$(INCDIR) -I$(INCDIR1) -I$(INCDIR2) -Imm -I. LIB=libshmem.a @@ -32,6 +33,8 @@ $(OBJS): Makefile $(LIB): $(OBJS) $(RM) -f $@ + cd mm; make; cd .. + cp mm/*.o . $(AR) cr $@ $(OBJS) $(RANLIB) $@ diff --git a/shmem/unix/shmem.c b/shmem/unix/shmem.c index 1263c0cee..6addd28a3 100644 --- a/shmem/unix/shmem.c +++ b/shmem/unix/shmem.c @@ -55,116 +55,174 @@ #include "mm.h" #include "apr_general.h" +#include "apr_shmem.h" #include "apr_errno.h" struct shmem_t { MM *mm; - ap_context_t *cntxt; }; -ap_status_t ap_shm_create(ap_context_t *cont, ap_size_t size, const char *file, - struct shmem_t **new) +/* ***APRDOC******************************************************** + * ap_status_t ap_shm_init(ap_shmem_t *, ap_size_t, char *) + * Create a pool of shared memory for use later. + * arg 1) The shared memory block. + * arg 2) The size of the shared memory pool. + * arg 3) The file to use for the shared memory on platforms that + * require it. + */ +ap_status_t ap_shm_init(struct shmem_t **m, ap_size_t reqsize, const char *file) { - MM *mm = mm_create(size, file); - - if (mm == NULL) { - return APR_ENOMEM; - } - (*new) = (struct shmem_t *)mm_malloc(mm, sizeof(struct shmem_t)); - if ((*new) == NULL) { - return APR_ENOMEM; + MM *newmm = mm_create(reqsize, file); + if (newmm == NULL) { + return errno; } - (*new)->mm = mm; - (*new)->cntxt = cont; + (*m) = mm_malloc(newmm, sizeof(struct shmem_t)); + (*m)->mm = newmm; return APR_SUCCESS; } -ap_status_t ap_shm_destroy(struct shmem_t *shared) -{ - mm_destroy(shared->mm); - shared->mm = NULL; - return APR_SUCCESS; -} - -ap_status_t ap_shm_malloc(void **entity, struct shmem_t *shared, ap_size_t size) +/* ***APRDOC******************************************************** + * ap_status_t ap_shm_destroy(ap_shmem_t *) + * Destroy the shared memory block. + * arg 1) The shared memory block to destroy. + */ +ap_status_t ap_shm_destroy(struct shmem_t *m) { - entity = mm_malloc(shared->mm, size); - if (entity == NULL) { - return APR_ENOMEM; - } + mm_destroy(m->mm); + m->mm = NULL; return APR_SUCCESS; } -ap_status_t ap_shm_calloc(struct shmem_t *shared, ap_size_t num, - ap_size_t size, void **entity) +/* ***APRDOC******************************************************** + * ap_status_t ap_shm_malloc(ap_shmem_t *, ap_size_t) + * allocate memory from the block of shared memory. + * arg 1) The shared memory block to destroy. + * arg 2) How much memory to allocate + */ +void *ap_shm_malloc(struct shmem_t *c, ap_size_t reqsize) { - entity = mm_calloc(shared->mm, num, size); - if (entity == NULL) { - return APR_ENOMEM; + if (c->mm == NULL) { + return NULL; } - return APR_SUCCESS; + return mm_malloc(c->mm, reqsize); } -ap_status_t ap_shm_realloc(void **entity, struct shmem_t *shared, ap_size_t size) +/* ***APRDOC******************************************************** + * ap_status_t ap_shm_calloc(ap_shmem_t *, ap_size_t) + * allocate memory from the block of shared memory and initialize it + * to zero. + * arg 1) The shared memory block to destroy. + * arg 2) How much memory to allocate + */ +void *ap_shm_calloc(struct shmem_t *shared, ap_size_t size) { - void *new; - - new = mm_realloc(shared->mm, *entity, size); - if (new == NULL) { - return APR_ENOMEM; + if (shared == NULL) { + return NULL; } - - (*entity) = new; - return APR_SUCCESS; + return mm_calloc(shared->mm, 1, size); } +/* ***APRDOC******************************************************** + * ap_status_t ap_shm_free(ap_shmem_t *, void *) + * free shared memory previously allocated. + * arg 1) The shared memory block to destroy. + */ ap_status_t ap_shm_free(struct shmem_t *shared, void *entity) { mm_free(shared->mm, entity); return APR_SUCCESS; } -ap_status_t ap_shm_strdup(char **new, struct shmem_t *shared, const char *old) +/* ***APRDOC******************************************************** + * ap_status_t ap_get_shm_name(ap_shmem_t *, ap_shm_name_t **) + * Get the name of the shared memory segment if not using + * anonymous shared memory. + * arg 1) The shared memory block to destroy. + * arg 2) The name of the shared memory block, NULL if anonymous + * shared memory. + * return) APR_USES_ANONYMOUS_SHM if we are using anonymous shared + * memory. APR_USES_FILEBASED_SHM if our shared memory is + * based on file access. APR_USES_KEYBASED_SHM if shared + * memory is based on a key value such as shmctl. If the + * shared memory is anonymous, the name is NULL. + */ +ap_status_t ap_get_shm_name(ap_shmem_t *c, ap_shm_name_t **name) { - (*new) = mm_strdup(shared->mm, old); - if ((*new) == NULL) { - return APR_ENOMEM; - } - return APR_SUCCESS; +#if APR_USES_ANONYMOUS_SHM + name = NULL; + return APR_ANONYMOUS; +/* Currently, we are not supporting name based shared memory on Unix + * systems. This may change in the future however, so I will leave + * this in here for now. Plus, this gives other platforms a good idea + * of how to proceed. + */ +#elif APR_USES_FILEBASED_SHM +#elif APR_USES_KEYBASED_SHM +#endif } -ap_status_t ap_shm_sizeof(struct shmem_t *shared, const void *ent, - ap_size_t *size) +/* ***APRDOC******************************************************** + * ap_status_t ap_set_shm_name(ap_shmem_t *, ap_shm_name_t *) + * Set the name of the shared memory segment if not using + * anonymous shared memory. This is to allow processes to open + * shared memory created by another process. + * arg 1) The shared memory block to destroy. + * arg 2) The name of the shared memory block, NULL if anonymous + * shared memory. + * return) APR_USES_ANONYMOUS_SHM if we are using anonymous shared + * memory. APR_SUCCESS if we are using named shared memory + * and we were able to assign the name correctly. + */ +ap_status_t ap_set_shm_name(ap_shmem_t *c, ap_shm_name_t *name) { - *size = mm_sizeof(shared->mm, ent); - if ((*size) == -1) { - return APR_EINVAL; - } - return APR_SUCCESS; +#if APR_USES_ANONYMOUS_SHM + return APR_ANONYMOUS; +/* Currently, we are not supporting name based shared memory on Unix + * systems. This may change in the future however, so I will leave + * this in here for now. Plus, this gives other platforms a good idea + * of how to proceed. + */ +#elif APR_USES_FILEBASED_SHM +#elif APR_USES_KEYBASED_SHM +#endif } -ap_status_t ap_shm_maxsize(ap_size_t *size) +/* ***APRDOC******************************************************** + * ap_status_t ap_open_shmem(ap_shmem_t *) + * Open the shared memory block in a child process. + * arg 1) The shared memory block to open in the child. + * return) This should be called after ap_set_shm_name. The ap_shmem_t + * variable must refer to the memory segment to open. + */ +ap_status_t ap_open_shmem(struct shmem_t *c) { - (*size) = mm_maxsize(); - if ((*size) <= 0) { - return APR_ENOMEM; - } +#if APR_USES_ANONYMOUS_SHM +/* When using MM, we don't need to open shared memory segments in child + * segments, so just return immediately. + */ return APR_SUCCESS; +/* Currently, we are not supporting name based shared memory on Unix + * systems. This may change in the future however, so I will leave + * this in here for now. Plus, this gives other platforms a good idea + * of how to proceed. + */ +#elif APR_USES_FILEBASED_SHM +#elif APR_USES_KEYBASED_SHM +#endif } -ap_status_t ap_shm_available(struct shmem_t *shared, ap_size_t *size) +/* ***APRDOC******************************************************** + * ap_status_t ap_shm_avail(ap_shmem_t *, ap_size_t *) + * Determine how much memory is available in the specified shared + * memory block + * arg 1) The shared memory block to open in the child. + * arg 2) The amount of space available in the shared memory block. + */ +ap_status_t ap_shm_avail(struct shmem_t *c, ap_size_t *size) { - (*size) = mm_available(shared->mm); - if ((*size) <= 0) { - return APR_ENOMEM; + *size = mm_available(c); + if (*size == 0) { + return APR_ESHMLOCK; } return APR_SUCCESS; } - -ap_status_t ap_shm_child_create(ap_context_t *cont, const char *fname, - struct shmem_t **shared) -{ - return APR_SUCCESS; -} - - diff --git a/test/Makefile.in b/test/Makefile.in index 5f1eb34d9..312299483 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -22,7 +22,8 @@ TARGETS= testfile@EXEEXT@ \ testcontext@EXEEXT@ \ ab@EXEEXT@ \ htdigest@EXEEXT@ \ - testmmap@EXEEXT@ + testmmap@EXEEXT@ \ + testshmem@EXEEXT@ OBJS= testfile.o \ testproc.o \ @@ -72,6 +73,9 @@ testtime@EXEEXT@: testtime.o testmmap@EXEEXT@: testmmap.o $(CC) $(CFLAGS) testmmap.o -o testmmap@EXEEXT@ $(LDFLAGS) +testshmem@EXEEXT@: testshmem.o + $(CC) $(CFLAGS) testshmem.o -o testshmem@EXEEXT@ $(LDFLAGS) + clean: $(RM) -f *.o *.a *.so $(TARGETS) diff --git a/shmem/shmem.c b/test/testshmem.c index 41f56b84c..bde3bde86 100644 --- a/shmem/shmem.c +++ b/test/testshmem.c @@ -52,106 +52,90 @@ * project, please see <http://www.apache.org/>. * */ +#include "apr_shmem.h" +#include "apr_lock.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "errno.h" +#include <stdio.h> +#ifdef BEOS +#include <unistd.h> +#endif -struct shmem_t { - MM *mm; - ap_context_t *cntxt; -} +typedef struct mbox { + char msg[1024]; + int msgavail; +} mbox; +ap_context_t *context; +mbox *boxes; -ap_status_t ap_shm_create(struct shmem_t **new, ap_context_t *cont, ap_size_t size, const char *file) +void msgwait(int boxnum) { - MM *mm = mm_create(size, file); - - if (mm == NULL) { - return APR_ENOMEM; - } - (*new) = (struct shmem_t *)mm_malloc(mm, sizeof(struct shmem_t)); - if ((*new) == NULL) - return APR_ENOMEM; - } - (*new)->mm = mm; - (*new)->cntxt = cont; - return APR_SUCCESS; + volatile int test = 0; + while (test == 0) { + test = boxes[boxnum].msgavail; + } + fprintf(stdout, "\nreceived a message in box %d, message was: %s\n", + boxnum, boxes[boxnum].msg); } -ap_status_t ap_shm_destroy(struct shmem_t *shared) +void msgput(int boxnum, char *msg) { - mm_destroy(shared->mm); - shared->mm = NULL; - return APR_SUCCESS; + fprintf(stdout, "Sending message to box %d\n", boxnum); + ap_cpystrn(boxes[boxnum].msg, msg, strlen(msg)); + boxes[boxnum].msgavail = 1; } -ap_status_t ap_shm_malloc(void **entity, struct shmem_t *shared, ap_size_t size) +int main() { - entity = mm_malloc(shared->mm, size); - if (entity == NULL) { - return APR_ENOMEM; - } - return APR_SUCCESS; -} + ap_status_t s4; + ap_shmem_t *shm; + pid_t pid; + ap_status_t s1; + int size; -ap_status_t ap_shm_calloc(void **entity, struct shmem_t *shared, ap_size_t size) -{ - entity = mm_calloc(shared->mm, size); - if (entity == NULL) { - return APR_ENOMEM; - } - return APR_SUCCESS; -} - -ap_status_t ap_shm_realloc(void **entity, struct shmem_t *shared, ap_size_t size) -{ - void *new; + ap_initialize(); - new = mm_realloc(shared->mm, *entity, size); - if (new == NULL) - return APR_ENOMEM; + fprintf(stdout, "Initializing the context......."); + if (ap_create_context(&context, NULL) != APR_SUCCESS) { + fprintf(stderr, "could not initialize\n"); + exit(-1); } + fprintf(stdout, "OK\n"); - (*entity) = new; - return APR_SUCCESS; -} - -ap_status_t ap_shm_free(struct shmem_t *shared, void *entity) -{ - mm_free(shared->mm, entity); - return APR_SUCCESS; -} - -ap_status_t ap_shm_strdup(char **new, struct shmem_t *shared, const char *old) -{ - (*new) = mm_strdup(shared->mm, old); - if ((*new) == NULL) { - return APR_ENOMEM; + fprintf(stdout, "Creating shared memory block......."); + if (ap_shm_init(&shm, 1048576, NULL) != APR_SUCCESS) { + fprintf(stderr, "Error allocating shared memory block\n"); + exit(-1); } - return APR_SUCCESS; -} + fprintf(stdout, "OK\n"); -ap_status_t ap_shm_sizeof(struct shmem_t *shared, const void *ent, - ap_size_t *size) -{ - *size = mm_sizeof(shared->mm, ent); - if ((*size) == -1) { - return APR_EINVAL; + fprintf(stdout, "Allocating shared memory......."); + size = sizeof(mbox) * 2; + boxes = ap_shm_calloc(shm, size); + if (boxes == NULL) { + fprintf(stderr, "Error creating message boxes.\n"); + exit(-1); } - return APR_SUCCESS; -} + fprintf(stdout, "OK\n"); -ap_status_t ap_shm_maxsize(ap_size_t **size) -{ - (*size) = mm_maxsize(); - if ((*size) <= 0) { - return APR_ENOMEM; + fprintf(stdout, "Creating a child process\n"); + pid = fork(); + if (pid == 0) { +sleep(1); + msgwait(1); + msgput(0, "Msg received\n"); + exit(1); } - return APR_SUCCESS; -} - -ap_status_t ap_shm_available(struct shmem_t *shared, ap_size_t *size) -{ - (*size) = mm_available(shared->mm); - if ((*size <= 0) { - return APR_ENOMEM; + else if (pid > 0) { + msgput(1, "Sending a message\n"); +sleep(1); + msgwait(0); + exit(1); + } + else { + fprintf(stderr, "Error creating a child process\n"); + exit(1); } - return APR_SUCCESS; } - |