summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>2000-01-27 23:49:36 +0000
committerrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>2000-01-27 23:49:36 +0000
commit6ddb2a0687ccf361a99bc96229dc15dec2b0f062 (patch)
treecc0a45fe032e8c6b3014a8ff18cf2edf5108194a
parent0fcaf05d5135154704e005d6a3ca2ee71fa9eee9 (diff)
downloadlibapr-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.in16
-rw-r--r--include/apr.h.in5
-rw-r--r--include/apr_errno.h4
-rw-r--r--include/apr_shmem.h31
-rw-r--r--shmem/unix/Makefile.in5
-rw-r--r--shmem/unix/shmem.c198
-rw-r--r--test/Makefile.in6
-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;
}
-