You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/08/21 09:28:52 UTC

svn commit: r806434 - in /commons/sandbox/runtime/trunk/src: main/native/include/ main/native/os/unix/ main/native/test/ test/org/apache/commons/runtime/

Author: mturk
Date: Fri Aug 21 07:28:51 2009
New Revision: 806434

URL: http://svn.apache.org/viewvc?rev=806434&view=rev
Log:
Add SysV mutex implementation

Added:
    commons/sandbox/runtime/trunk/src/main/native/os/unix/smutex.c   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/native/include/acr_procmutex.h
    commons/sandbox/runtime/trunk/src/main/native/os/unix/pmutex.c
    commons/sandbox/runtime/trunk/src/main/native/os/unix/psema.c
    commons/sandbox/runtime/trunk/src/main/native/test/testcase.c
    commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestPrivate.java

Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_procmutex.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_procmutex.h?rev=806434&r1=806433&r2=806434&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_procmutex.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_procmutex.h Fri Aug 21 07:28:51 2009
@@ -32,6 +32,11 @@
  */
 
 /**
+ * Any value will do
+ */
+#define ACR_MTX_MAGIC   0xC2303964
+
+/**
  * Private, platform-specific data struture representing a mutex.
  */
 typedef struct acr_pmutex_t acr_pmutex_t;

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/pmutex.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/pmutex.c?rev=806434&r1=806433&r2=806434&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/pmutex.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/pmutex.c Fri Aug 21 07:28:51 2009
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+/*
+ * Posix semaphore implementation.
+ */
+
 #include "acr.h"
 #include "acr_private.h"
 #include "acr_arch.h"
@@ -92,7 +96,7 @@
             *p = '_';
     }
     do {
-        m->sem = sem_open(m->name, O_CREAT | O_EXCL, 0666, 1);
+        m->sem = sem_open(m->name, O_CREAT | O_EXCL, 0660, 1);
         if (m->sem == (sem_t *)SEM_FAILED) {
             if (rc)
                 goto finally;

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/psema.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/psema.c?rev=806434&r1=806433&r2=806434&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/psema.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/psema.c Fri Aug 21 07:28:51 2009
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+/*
+ * Posix semaphore implementation
+ */
+
 #include "acr.h"
 #include "acr_private.h"
 #include "acr_arch.h"
@@ -93,7 +97,7 @@
             *p = '_';
     }
     do {
-        s->sem = sem_open(s->name, O_CREAT | O_EXCL, 0666, value);
+        s->sem = sem_open(s->name, O_CREAT | O_EXCL, 0660, value);
         if (s->sem == (sem_t *)SEM_FAILED) {
             if (rc)
                 goto finally;

Added: commons/sandbox/runtime/trunk/src/main/native/os/unix/smutex.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/smutex.c?rev=806434&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/smutex.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/smutex.c Fri Aug 21 07:28:51 2009
@@ -0,0 +1,532 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * System V semaphore implementation.
+ * Although Linux manual says that Posix semaphores have better API,
+ * they don't provide a simple way for setting the permissions once after
+ * they are created.
+ */
+
+#include "acr.h"
+#include "acr_private.h"
+#include "acr_arch.h"
+#include "acr_clazz.h"
+#include "acr_error.h"
+#include "acr_memory.h"
+#include "acr_string.h"
+#include "acr_descriptor.h"
+#include "acr_pointer.h"
+#include "acr_procmutex.h"
+
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/file.h>
+
+J_DECLARE_CLAZZ = {
+    NULL,
+    NULL,
+    ACR_CLASS_PATH "Mutex"
+};
+
+J_DECLARE_M_ID(0000) = {
+    NULL,
+    "<init>",
+    "(L" ACR_CLASS_PATH "Descriptor;)V"
+};
+
+union semun {
+    int val;
+    struct semid_ds *buf;
+    unsigned short *array;
+};
+
+struct acr_pmutex_t {
+    int         filedes;
+    int         locked;
+    const char *filename;       /* NULL if anonymous */
+};
+
+typedef struct semblock_t {
+    acr_uint32_t    magic;       /* Is this our memeory     */
+    pid_t           creator;     /* Creator's process ID    */
+    acr_uint32_t    value;       /* Maximum semaphore value */
+} semblock_t;
+
+static int mutex_owner_cleanup(void *mutex, int type, unsigned int flags)
+{
+    if (type == ACR_DT_MUTEX) {
+        int rc = ACR_SUCCESS;
+        acr_pmutex_t *m = (acr_pmutex_t *)mutex;
+        if (m->filedes > 0) {
+            union semun ick;
+            if (m->locked) {
+                struct sembuf op;
+                /* Unlock our instance */
+                op.sem_num = 0;
+                op.sem_op  = 1;
+                op.sem_flg = SEM_UNDO;
+                do {
+                    rc = semop(m->filedes, &op, 1);
+                } while (rc < 0 && errno == EINTR);
+            }
+            ick.val = 0;
+            semctl(m->filedes, 0, IPC_RMID, ick);
+        }
+        if (m->filename) {
+            if (access(m->filename, F_OK)) {
+                rc = ACR_SUCCESS;
+            }
+            else {
+                if (unlink(m->filename))
+                    rc = ACR_GET_OS_ERROR();
+            }
+            free((void *)(m->filename));
+        }
+        free(m);
+        return rc;
+    }
+    return ACR_EBADF;
+}
+
+static int mutex_child_cleanup(void *mutex, int type, unsigned int flags)
+{
+    if (type == ACR_DT_MUTEX) {
+        int rc;
+        acr_pmutex_t *m = (acr_pmutex_t *)mutex;
+        if (m->filedes > 0) {
+            if (m->locked) {
+                struct sembuf op;
+                /* Unlock our instance */
+                op.sem_num = 0;
+                op.sem_op  = 1;
+                op.sem_flg = SEM_UNDO;
+                do {
+                    rc = semop(m->filedes, &op, 1);
+                } while (rc < 0 && errno == EINTR);
+            }
+        }
+        free(m);
+        return ACR_SUCCESS;
+    }
+    return ACR_EBADF;
+}
+
+ACR_DECLARE(int) ACR_ProcMutexCreate(JNIEnv *_E, const acr_pchar_t *fname)
+{
+    union semun ick;
+    int rc = 0;
+    acr_pmutex_t *m;
+    key_t mkey = IPC_PRIVATE;
+    int flags  = IPC_CREAT;
+
+    if (fname) {
+        size_t     nbytes;
+        semblock_t hdr;
+        int fs, fd = -1;
+
+        fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0660);
+        if (fd < 0) {
+            rc =  ACR_GET_OS_ERROR();
+            ACR_THROW_IO_ERRNO();
+            return -1;
+        }
+        mkey = ftok(fname, 1);
+        if (mkey == (key_t)-1) {
+            rc =  ACR_GET_OS_ERROR();
+            close(fd);
+            ACR_THROW_IO_IF_ERR(rc);
+            return -1;
+        }
+        /* Write our header to shadow file
+         * Not needed, but might be used in the
+         * future to pass some data along with the mutex
+         */
+        nbytes = sizeof(semblock_t);
+        hdr.creator = getpid();
+        hdr.magic   = ACR_MTX_MAGIC;
+        hdr.value   = 1;
+        do {
+            fs = write(fd,(const void *)&hdr, nbytes);
+        } while (fs == (acr_size_t)-1 && errno == EINTR);
+        if (fs == -1) {
+            rc = ACR_GET_OS_ERROR();
+            close(fd);
+            ACR_THROW_IO_IF_ERR(rc);
+            return -1;
+        }
+        close(fd);
+        flags |= IPC_EXCL;
+    }
+    m = ACR_Calloc(_E, THROW_FMARK, sizeof(acr_pmutex_t));
+    if (!m)
+        return -1;
+    if (fname) {
+        m->filename = ACR_StrdupA(_E, THROW_FMARK, fname);
+        if (!m->filename) {
+            rc =  ACR_GET_OS_ERROR();
+            free(m);
+            ACR_SET_OS_ERROR(rc);
+            return -1;
+        }
+    }
+    m->filedes = semget(mkey, 1, flags | 0660);
+
+    if (m->filedes < 0) {
+        if (fname && errno == EEXIST) {
+            /* XXX: Should we throw separate exception here?
+             */
+        }
+        rc =  ACR_GET_OS_ERROR();
+        goto finally;
+    }
+    ick.val = 1;
+    if (semctl(m->filedes, 0, SETVAL, ick) < 0) {
+        rc =  ACR_GET_OS_ERROR();
+        goto finally;
+    }
+    m->locked = 0;
+
+finally:
+    if (rc) {
+        if (m->filedes > 0) {
+            ick.val = 0;
+            semctl(m->filedes, 0, IPC_RMID, ick);
+        }
+        x_free((void *)(m->filename));
+        free(m);
+        ACR_THROW_IO_IF_ERR(rc);
+        return -1;
+    }
+    else {
+        rc = acr_ioh_open(m, ACR_DT_MUTEX, 0, mutex_owner_cleanup);
+        return rc;
+    }
+}
+
+ACR_DECLARE(int) ACR_ProcMutexAttach(JNIEnv *_E, const acr_pchar_t *fname)
+{
+    int rc = 0;
+    acr_pmutex_t *m;
+    key_t mkey;
+    int   file;
+
+    if (!fname) {
+        /* Cannot attach to unnamed mutex */
+        ACR_THROW_IO_IF_ERR(ACR_EINVAL);
+        return -1;
+    }
+
+    file = open(fname, O_RDONLY);
+    if (file < 0) {
+        ACR_THROW_IO_ERRNO();
+        return -1;
+    }
+
+    mkey = ftok(fname, 1);
+    if (mkey == (key_t)-1) {
+        rc = ACR_GET_OS_ERROR();
+        close(file);
+        ACR_THROW_IO_IF_ERR(rc);
+        return -1;
+    }
+    close(file);
+    m = ACR_Calloc(_E, THROW_FMARK, sizeof(acr_pmutex_t));
+    if (!m)
+        return -1;
+
+    m->filedes = semget(mkey, 1, 0);
+    if (m->filedes < 0) {
+        rc =  ACR_GET_OS_ERROR();
+        goto finally;
+    }
+    m->locked = 0;
+
+finally:
+    if (rc) {
+        free(m);
+        ACR_THROW_IO_IF_ERR(rc);
+        return -1;
+    }
+    else {
+        rc = acr_ioh_open(m, ACR_DT_MUTEX, 0, mutex_child_cleanup);
+        return rc;
+    }
+}
+
+ACR_DECLARE(int) ACR_ProcMutexLock(JNIEnv *_E, int mutex)
+{
+    int rc;
+    struct sembuf op;
+    acr_pmutex_t *m = (acr_pmutex_t *)ACR_IOH(mutex);
+
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(mutex) != ACR_DT_MUTEX) {
+        ACR_SET_OS_ERROR(ACR_EINVAL);
+        return -1;
+    }
+    op.sem_num = 0;
+    op.sem_op  = -1;
+    op.sem_flg = SEM_UNDO;
+
+    do {
+        rc = semop(m->filedes, &op, 1);
+    } while (rc < 0 && errno == EINTR);
+
+    if (rc < 0)
+        return ACR_GET_OS_ERROR();
+    m->locked = 1;
+
+    return ACR_SUCCESS;
+}
+
+ACR_DECLARE(int) ACR_ProcMutexTryLock(JNIEnv *_E, int mutex)
+{
+    int rc;
+    struct sembuf op;
+    acr_pmutex_t *m = (acr_pmutex_t *)ACR_IOH(mutex);
+
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(mutex) != ACR_DT_MUTEX) {
+        return ACR_EINVAL;
+    }
+    op.sem_num = 0;
+    op.sem_op  = -1;
+    op.sem_flg = SEM_UNDO | IPC_NOWAIT;
+
+    do {
+        rc = semop(m->filedes, &op, 1);
+    } while (rc < 0 && errno == EINTR);
+
+    if (rc < 0) {
+        if (errno == EAGAIN) {
+            return ACR_EBUSY;
+        }
+        else
+            return ACR_GET_OS_ERROR();
+    }
+    else
+        m->locked = 1;
+
+    return ACR_SUCCESS;;
+}
+
+ACR_DECLARE(int) ACR_ProcMutexRelease(JNIEnv *_E, int mutex)
+{
+    int rc;
+    struct sembuf op;
+    acr_pmutex_t *m = (acr_pmutex_t *)ACR_IOH(mutex);
+
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(mutex) != ACR_DT_MUTEX) {
+        return ACR_EINVAL;
+    }
+
+    m->locked  = 0;
+    op.sem_num = 0;
+    op.sem_op  = 1;
+    op.sem_flg = SEM_UNDO;
+    do {
+        rc = semop(m->filedes, &op, 1);
+    } while (rc < 0 && errno == EINTR);
+
+    if (rc < 0)
+        return ACR_GET_OS_ERROR();
+    else
+        return ACR_SUCCESS;
+}
+
+ACR_DECLARE(int) ACR_ProcMutexPermSet(JNIEnv *_E, int mutex, int perms,
+                                      acr_uid_t uid, acr_uid_t gid)
+{
+    union  semun ick;
+    struct semid_ds buf;
+    acr_pmutex_t *m = (acr_pmutex_t *)ACR_IOH(mutex);
+
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(mutex) != ACR_DT_MUTEX) {
+        return ACR_EINVAL;
+    }
+    buf.sem_perm.uid  = uid;
+    buf.sem_perm.gid  = gid;
+    buf.sem_perm.mode = ACR_UnixPermsToMode(perms);
+    ick.buf = &buf;
+
+    if (semctl(m->filedes, 0, IPC_SET, ick) < 0) {
+        return ACR_GET_OS_ERROR();
+    }
+    else
+        return ACR_SUCCESS;
+}
+
+ACR_DECLARE(int) ACR_ProcMutexClose(JNIEnv *_E, int mutex)
+{
+
+    /* Close will call the cleanup function
+     */
+    return acr_ioh_close(mutex);
+}
+
+ACR_DECLARE(int) ACR_ProcMutexRemove(JNIEnv *_E, const acr_pchar_t *filename)
+{
+    union semun ick;
+    int         rc = 0;
+    int         file;
+    key_t       mkey;
+    int         mfid;
+
+    /* Presume that the file already exists; just open for writing.
+     * Mode is not needed cause we don't use O_CREAT flag.
+     */
+    file = open(filename, O_WRONLY);
+    if (file < 0) {
+        rc = ACR_GET_OS_ERROR();
+        goto finally;
+    }
+
+    /* ftok() (on solaris at least) requires that the file actually
+     * exist before calling ftok().
+     */
+    mkey = ftok(filename, 1);
+    if (mkey == (key_t)-1) {
+        rc = ACR_GET_OS_ERROR();
+        close(file);
+        goto finally;
+    }
+    close(file);
+    mfid = semget(mkey, 1, 0);
+
+    if ((mfid = semget(mkey, 1, 0)) < 0) {
+        rc =  ACR_GET_OS_ERROR();
+        goto finally;
+    }
+    ick.val = 0;
+    if (semctl(mfid, 0, IPC_RMID, ick) < 0) {
+        rc = ACR_GET_OS_ERROR();
+        goto finally;
+    }
+
+finally:
+    unlink(filename);
+    ACR_THROW_IO_IF_ERR(rc);
+    return rc;
+}
+
+ACR_CLASS_LDEF(Mutex)
+{
+    int rv;
+
+    if ((rv = ACR_LoadClass(_E, &_clazzn, 0)) != ACR_SUCCESS)
+        return rv;
+    J_LOAD_METHOD(0000);
+
+    return ACR_SUCCESS;
+}
+
+ACR_CLASS_UDEF(Mutex)
+{
+    ACR_UnloadClass(_E, &_clazzn);
+}
+
+static int mtx_descriptor_cleanup(ACR_JNISTDARGS,
+                                  acr_descriptor_cb_type_e cm,
+                                  acr_descriptor_cb_t *dp)
+{
+    int rc = ACR_SUCCESS;
+    switch (cm) {
+        case ACR_DESC_CLOSE:
+            if (dp->di > 0)
+                rc = acr_ioh_close(dp->di);
+            else
+                rc = ACR_EBADF;
+        break;
+        default:
+            rc = ACR_ENOTIMPL;
+        break;
+    }
+    return rc;
+}
+
+ACR_DECLARE(jobject) ACR_ProcMutexObjectCreate(JNIEnv *_E,
+                                               const acr_pchar_t *name)
+{
+    jobject mtxo;
+    jobject mtxd;
+    int     imtx;
+
+    imtx = ACR_ProcMutexCreate(_E, name);
+    if (imtx < 0) {
+
+        return NULL;
+    }
+    /* Create Descriptor Object */
+    mtxd = ACR_DescriptorCreate(_E, ACR_DT_MUTEX, imtx, NULL,
+                                mtx_descriptor_cleanup);
+    if (!mtxd) {
+
+        return NULL;
+    }
+    mtxo = (*_E)->NewObject(_E, _clazzn.i, J4MID(0000), mtxd);
+    return mtxo;
+}
+
+ACR_DECLARE(jobject) ACR_ProcMutexObjectAttach(JNIEnv *_E,
+                                               const acr_pchar_t *name)
+{
+    jobject mtxo;
+    jobject mtxd;
+    int     imtx;
+
+    imtx = ACR_ProcMutexAttach(_E, name);
+    if (imtx < 0) {
+
+        return NULL;
+    }
+    /* Create Descriptor Object */
+    mtxd = ACR_DescriptorCreate(_E, ACR_DT_MUTEX, imtx, NULL,
+                                mtx_descriptor_cleanup);
+    if (!mtxd) {
+
+        return NULL;
+    }
+    mtxo = (*_E)->NewObject(_E, _clazzn.i, J4MID(0000), mtxd);
+    return mtxo;
+}
+
+ACR_JNI_EXPORT_DECLARE(jobject, Mutex, create1)(ACR_JNISTDARGS,
+                                                jstring name)
+{
+
+    jobject mtxo = NULL;
+    UNREFERENCED_O;
+
+    WITH_CSTR(name) {
+        mtxo = ACR_ProcMutexObjectCreate(_E, J2S(name));
+    } END_WITH_CSTR(name);
+
+    return mtxo;
+}
+
+ACR_JNI_EXPORT_DECLARE(jobject, Mutex, create2)(ACR_JNISTDARGS,
+                                                jstring name)
+{
+
+    jobject mtxo = NULL;
+    UNREFERENCED_O;
+
+    WITH_CSTR(name) {
+        mtxo = ACR_ProcMutexObjectAttach(_E, J2S(name));
+    } END_WITH_CSTR(name);
+
+    return mtxo;
+}
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/os/unix/smutex.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/sandbox/runtime/trunk/src/main/native/test/testcase.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/testcase.c?rev=806434&r1=806433&r2=806434&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/testcase.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/test/testcase.c Fri Aug 21 07:28:51 2009
@@ -752,7 +752,7 @@
 #if defined(WIN32)
     return ACR_ProcMutexAttach(_E, shr_name);
 #else
-    return 0;
+    return ACR_ProcMutexAttach(_E, shr_name);
 #endif
 }
 

Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestPrivate.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestPrivate.java?rev=806434&r1=806433&r2=806434&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestPrivate.java (original)
+++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestPrivate.java Fri Aug 21 07:28:51 2009
@@ -1014,5 +1014,31 @@
         assertEquals("Destroy Named Process Mutex", 0, rv);
     }
 
+
+    public void testPmutexAttach()
+        throws Throwable
+    {
+        int rv;
+        int sa = test072(0);
+        assertTrue("Named Process Mutex", sa > 0);
+        int sc = test074(0);
+        assertTrue("Named Process Mutex Attach", sc > 0);
+        int sb = test074(0);
+        assertTrue("Named Process Mutex Attach", sb > 0);
+        rv = test073(sc);
+        assertEquals("Destroy attached Named Process Mutex", 0, rv);
+        rv = test073(sb);
+        assertEquals("Destroy attached Named Process Mutex", 0, rv);
+
+        // Try attaching again
+        int sd = test074(0);
+        assertTrue("Named Process Mutex Attach", sd > 0);
+        rv = test073(sd);
+        assertEquals("Destroy attached Named Process Mutex", 0, rv);
+
+        // Destory parent
+        rv = test073(sa);
+        assertEquals("Destroy Named Process Mutex", 0, rv);
+    }
 }