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);
+ }
}