summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-08-15 14:53:18 +0000
committerBenny Prijono <bennylp@teluu.com>2008-08-15 14:53:18 +0000
commit2f24a0b188d55837e7c11fcbef53153702560699 (patch)
tree94db942df28cfcb4c37846be58ddc67c84df2dc6
parentdda962837e8e9d4c28c0d5bb7f30ffebc79f4db8 (diff)
Ticket #595: Broken semaphore implementation on MacOS X (thanks Viktor Krikun for the report)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2217 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/src/pj/os_core_unix.c50
-rw-r--r--pjlib/src/pjlib-test/mutex.c59
2 files changed, 103 insertions, 6 deletions
diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c
index 006f2a0b..9543737f 100644
--- a/pjlib/src/pj/os_core_unix.c
+++ b/pjlib/src/pj/os_core_unix.c
@@ -88,7 +88,7 @@ struct pj_mutex_t
#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
struct pj_sem_t
{
- sem_t sem;
+ sem_t *sem;
char obj_name[PJ_MAX_OBJ_NAME];
};
#endif /* PJ_HAS_SEMAPHORE */
@@ -1470,8 +1470,42 @@ PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool,
sem = PJ_POOL_ALLOC_T(pool, pj_sem_t);
PJ_ASSERT_RETURN(sem, PJ_ENOMEM);
- if (sem_init( &sem->sem, 0, initial) != 0)
+#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
+ /* MacOS X doesn't support anonymous semaphore */
+ {
+ char sem_name[PJ_GUID_MAX_LENGTH+1];
+ pj_str_t nam;
+
+ /* We should use SEM_NAME_LEN, but this doesn't seem to be
+ * declared anywhere? The value here is just from trial and error
+ * to get the longest name supported.
+ */
+# define MAX_SEM_NAME_LEN 23
+
+ /* Create a unique name for the semaphore. */
+ if (PJ_GUID_STRING_LENGTH <= MAX_SEM_NAME_LEN) {
+ nam.ptr = sem_name;
+ pj_generate_unique_string(&nam);
+ sem_name[nam.slen] = '\0';
+ } else {
+ pj_create_random_string(sem_name, MAX_SEM_NAME_LEN);
+ sem_name[MAX_SEM_NAME_LEN] = '\0';
+ }
+
+ /* Create semaphore */
+ sem->sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR,
+ initial);
+ if (sem->sem == SEM_FAILED)
+ return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+
+ /* And immediately release the name as we don't need it */
+ sem_unlink(sem_name);
+ }
+#else
+ sem->sem = PJ_POOL_ALLOC_T(pool, sem_t);
+ if (sem_init( sem->sem, 0, initial) != 0)
return PJ_RETURN_OS_ERROR(pj_get_native_os_error());
+#endif
/* Set name. */
if (!name) {
@@ -1508,7 +1542,7 @@ PJ_DEF(pj_status_t) pj_sem_wait(pj_sem_t *sem)
PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s is waiting",
pj_thread_this()->obj_name));
- result = sem_wait( &sem->sem );
+ result = sem_wait( sem->sem );
if (result == 0) {
PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s",
@@ -1539,7 +1573,7 @@ PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem)
PJ_CHECK_STACK();
PJ_ASSERT_RETURN(sem, PJ_EINVAL);
- result = sem_trywait( &sem->sem );
+ result = sem_trywait( sem->sem );
if (result == 0) {
PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s",
@@ -1564,7 +1598,7 @@ PJ_DEF(pj_status_t) pj_sem_post(pj_sem_t *sem)
int result;
PJ_LOG(6, (sem->obj_name, "Semaphore released by thread %s",
pj_thread_this()->obj_name));
- result = sem_post( &sem->sem );
+ result = sem_post( sem->sem );
if (result == 0)
return PJ_SUCCESS;
@@ -1589,7 +1623,11 @@ PJ_DEF(pj_status_t) pj_sem_destroy(pj_sem_t *sem)
PJ_LOG(6, (sem->obj_name, "Semaphore destroyed by thread %s",
pj_thread_this()->obj_name));
- result = sem_destroy( &sem->sem );
+#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
+ result = sem_close( sem->sem );
+#else
+ result = sem_destroy( sem->sem );
+#endif
if (result == 0)
return PJ_SUCCESS;
diff --git a/pjlib/src/pjlib-test/mutex.c b/pjlib/src/pjlib-test/mutex.c
index 81565c57..0c507609 100644
--- a/pjlib/src/pjlib-test/mutex.c
+++ b/pjlib/src/pjlib-test/mutex.c
@@ -148,6 +148,59 @@ static int recursive_mutex_test(pj_pool_t *pool)
return PJ_SUCCESS;
}
+#if PJ_HAS_SEMAPHORE
+static int semaphore_test(pj_pool_t *pool)
+{
+ pj_sem_t *sem;
+ pj_status_t status;
+
+ PJ_LOG(3,("", "...testing semaphore"));
+
+ status = pj_sem_create(pool, NULL, 0, 1, &sem);
+ if (status != PJ_SUCCESS) {
+ app_perror("...error: pj_sem_create()", status);
+ return -151;
+ }
+
+ status = pj_sem_post(sem);
+ if (status != PJ_SUCCESS) {
+ app_perror("...error: pj_sem_post()", status);
+ pj_sem_destroy(sem);
+ return -153;
+ }
+
+ status = pj_sem_trywait(sem);
+ if (status != PJ_SUCCESS) {
+ app_perror("...error: pj_sem_trywait()", status);
+ pj_sem_destroy(sem);
+ return -156;
+ }
+
+ status = pj_sem_post(sem);
+ if (status != PJ_SUCCESS) {
+ app_perror("...error: pj_sem_post()", status);
+ pj_sem_destroy(sem);
+ return -159;
+ }
+
+ status = pj_sem_wait(sem);
+ if (status != PJ_SUCCESS) {
+ app_perror("...error: pj_sem_wait()", status);
+ pj_sem_destroy(sem);
+ return -161;
+ }
+
+ status = pj_sem_destroy(sem);
+ if (status != PJ_SUCCESS) {
+ app_perror("...error: pj_sem_destroy()", status);
+ return -163;
+ }
+
+ return 0;
+}
+#endif /* PJ_HAS_SEMAPHORE */
+
+
int mutex_test(void)
{
pj_pool_t *pool;
@@ -163,6 +216,12 @@ int mutex_test(void)
if (rc != 0)
return rc;
+#if PJ_HAS_SEMAPHORE
+ rc = semaphore_test(pool);
+ if (rc != 0)
+ return rc;
+#endif
+
pj_pool_release(pool);
return 0;