Commit 69ca354e authored by Pekka Pessi's avatar Pekka Pessi

sofia-sip/su_alloc.h, su_alloc.c: added su_home_lock(), su_home_trylock(), su_home_unlock()

Added test in torture_su_alloc.c. Using in su_pthread_port.c.

darcs-hash:20071116161709-65a35-d5d920529638aab4cfd868bff47551ff8acd3df4.gz
parent 3d4b690f
......@@ -107,6 +107,10 @@ SU_DLL int su_home_mutex_lock(su_home_t *home);
SU_DLL int su_home_mutex_unlock(su_home_t *home);
SU_DLL int su_home_lock(su_home_t *home);
SU_DLL int su_home_trylock(su_home_t *home);
SU_DLL int su_home_unlock(su_home_t *home);
SU_DLL void *su_alloc(su_home_t *h, isize_t size)
__attribute__((__malloc__));
SU_DLL void *su_zalloc(su_home_t *h, isize_t size)
......
......@@ -194,17 +194,18 @@
#include <assert.h>
void (*su_home_locker)(void *mutex);
void (*su_home_unlocker)(void *mutex);
int (*_su_home_locker)(void *mutex);
int (*_su_home_unlocker)(void *mutex);
void (*su_home_mutex_locker)(void *mutex);
void (*su_home_mutex_unlocker)(void *mutex);
int (*_su_home_mutex_locker)(void *mutex);
int (*_su_home_mutex_trylocker)(void *mutex);
int (*_su_home_mutex_unlocker)(void *mutex);
void (*su_home_destroy_mutexes)(void *mutex);
void (*_su_home_destroy_mutexes)(void *mutex);
#define MEMLOCK(h) \
(((h) && (h)->suh_lock ? su_home_locker((h)->suh_lock) : (void)0), (h)->suh_blocks)
#define UNLOCK(h) (((h) && (h)->suh_lock ? su_home_unlocker((h)->suh_lock) : (void)0), NULL)
(((h) && (h)->suh_lock ? _su_home_locker((h)->suh_lock) : (void)0), (h)->suh_blocks)
#define UNLOCK(h) (((h) && (h)->suh_lock ? _su_home_unlocker((h)->suh_lock) : (void)0), NULL)
#ifdef NDEBUG
#define MEMCHECK 0
......@@ -987,7 +988,7 @@ void _su_home_deinit(su_home_t *home)
home->suh_blocks = NULL;
if (home->suh_lock)
su_home_destroy_mutexes(home->suh_lock);
_su_home_destroy_mutexes(home->suh_lock);
}
home->suh_lock = NULL;
......@@ -1462,42 +1463,108 @@ int su_home_is_threadsafe(su_home_t const *home)
return home && home->suh_lock;
}
/** Obtain exclusive lock on home (if home is threadsafe). */
/** Increase refcount and obtain exclusive lock on home.
*
* @note The #su_home_t structure must be created with su_home_new() or
* su_home_clone(), or initialized with su_home_init() before using this
* function.
*
* In order to enable actual locking, use su_home_threadsafe(), too.
* Otherwise the su_home_mutex_lock() will just increase the reference
* count.
*/
int su_home_mutex_lock(su_home_t *home)
{
int error;
if (home == NULL)
return su_seterrno(EFAULT);
if (home->suh_lock) {
su_home_ref(home);
su_home_mutex_locker(home->suh_lock);
}
else if (home->suh_blocks) {
if (!su_home_ref(home))
return -1;
}
if (home->suh_blocks == NULL || !su_home_ref(home))
return su_seterrno(EINVAL); /* Uninitialized home */
if (!home->suh_lock)
return 0; /* No-op */
error = _su_home_mutex_locker(home->suh_lock);
if (error)
return su_seterrno(error);
return 0;
}
/** Release exclusive lock on home (if home is threadsafe) */
/** Release exclusive lock on home and decrease refcount (if home is threadsafe) */
int su_home_mutex_unlock(su_home_t *home)
{
if (home == NULL)
return su_seterrno(EFAULT);
if (home->suh_lock) {
su_home_mutex_unlocker(home->suh_lock);
su_home_unref(home);
}
else if (home->suh_blocks) {
su_home_unref(home);
int error = _su_home_mutex_unlocker(home->suh_lock);
if (error)
return su_seterrno(error);
}
if (home->suh_blocks == NULL)
return su_seterrno(EINVAL), -1; /* Uninitialized home */
su_home_unref(home);
return 0;
}
/** Obtain exclusive lock on home without increasing refcount.
*
* @return 0 if successful, -1 if not threadsafe, error code otherwise.
*
*/
int su_home_lock(su_home_t *home)
{
if (home == NULL)
return EFAULT;
if (home->suh_lock == NULL)
return -1; /* No-op */
return _su_home_mutex_locker(home->suh_lock);
}
/** Try to obtain exclusive lock on home without increasing refcount.
*
* @return 0 if successful, -1 if not threadsafe,
* EBUSY if already locked, error code otherwise.
*
*/
int su_home_trylock(su_home_t *home)
{
if (home == NULL)
return EFAULT;
if (home->suh_lock == NULL)
return -1; /* No-op */
return _su_home_mutex_trylocker(home->suh_lock);
}
/** Release exclusive lock on home.
*
* @return 0 if successful, -1 if not threadsafe, error code otherwise.
*/
int su_home_unlock(su_home_t *home)
{
if (home == NULL)
return EFAULT;
if (home->suh_lock == NULL)
return -1; /* No-op */
return _su_home_mutex_unlocker(home->suh_lock);
}
/** Initialize statistics structure */
void su_home_init_stats(su_home_t *home)
{
......
......@@ -41,25 +41,32 @@
#include <assert.h>
#include <stdlib.h>
extern void (*su_home_locker)(void *mutex);
extern void (*su_home_unlocker)(void *mutex);
extern int (*_su_home_locker)(void *mutex);
extern int (*_su_home_unlocker)(void *mutex);
extern void (*su_home_mutex_locker)(void *mutex);
extern void (*su_home_mutex_unlocker)(void *mutex);
extern int (*_su_home_mutex_locker)(void *mutex);
extern int (*_su_home_mutex_trylocker)(void *mutex);
extern int (*_su_home_mutex_unlocker)(void *mutex);
extern void (*su_home_destroy_mutexes)(void *mutex);
extern void (*_su_home_destroy_mutexes)(void *mutex);
/** Mutex */
static void mutex_locker(void *_mutex)
static int mutex_locker(void *_mutex)
{
pthread_mutex_t *mutex = _mutex;
pthread_mutex_lock(mutex + 1);
return pthread_mutex_lock(mutex + 1);
}
static void mutex_unlocker(void *_mutex)
int mutex_trylocker(void *_mutex)
{
pthread_mutex_t *mutex = _mutex;
pthread_mutex_unlock(mutex + 1);
return pthread_mutex_trylock(mutex + 1);
}
static int mutex_unlocker(void *_mutex)
{
pthread_mutex_t *mutex = _mutex;
return pthread_mutex_unlock(mutex + 1);
}
static void mutex_destroy(void *_mutex)
......@@ -69,7 +76,6 @@ static void mutex_destroy(void *_mutex)
pthread_mutex_destroy(mutex + 1);
free(_mutex);
}
#endif
......@@ -100,13 +106,14 @@ int su_home_threadsafe(su_home_t *home)
#endif
#if SU_HAVE_PTHREADS
if (!su_home_unlocker) {
if (!_su_home_unlocker) {
/* Avoid linking pthread library just for memory management */
su_home_mutex_locker = mutex_locker;
su_home_mutex_unlocker = mutex_unlocker;
su_home_locker = (void (*)(void *))pthread_mutex_lock;
su_home_unlocker = (void (*)(void *))pthread_mutex_unlock;
su_home_destroy_mutexes = mutex_destroy;
_su_home_mutex_locker = mutex_locker;
_su_home_mutex_trylocker = mutex_trylocker;
_su_home_mutex_unlocker = mutex_unlocker;
_su_home_locker = (int (*)(void *))pthread_mutex_lock;
_su_home_unlocker = (int (*)(void *))pthread_mutex_unlock;
_su_home_destroy_mutexes = mutex_destroy;
}
mutex = calloc(1, 2 * (sizeof *mutex));
......
......@@ -97,7 +97,7 @@ void su_pthread_port_lock(su_port_t *self, char const *who)
PORT_LOCK_DEBUG(("%p at %s locking(%p)...",
(void *)pthread_self(), who, self));
su_home_mutex_lock(self->sup_base->sup_home);
su_home_lock(self->sup_base->sup_home);
PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...",
(void *)pthread_self(), who, self));
......@@ -105,7 +105,7 @@ void su_pthread_port_lock(su_port_t *self, char const *who)
void su_pthread_port_unlock(su_port_t *self, char const *who)
{
su_home_mutex_unlock(self->sup_base->sup_home);
su_home_unlock(self->sup_base->sup_home);
PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n",
(void *)pthread_self(), who, self));
......
......@@ -39,6 +39,7 @@
#include <stdlib.h>
#include <sofia-sip/su_alloc.h>
#include <sofia-sip/su_errno.h>
#include <sofia-sip/su_strlst.h>
#include <sofia-sip/su_alloc_stat.h>
......@@ -194,6 +195,42 @@ static int test_alloc(void)
END();
}
static int test_lock(void)
{
su_home_t home[1] = { SU_HOME_INIT(home) };
BEGIN();
TEST(su_home_mutex_lock(home), -1);
TEST(su_home_mutex_unlock(home), -1);
TEST(su_home_lock(home), -1);
TEST(su_home_trylock(home), -1);
TEST(su_home_unlock(home), -1);
TEST(su_home_init(home), 0);
TEST(su_home_mutex_lock(home), 0);
TEST(su_home_trylock(home), -1);
TEST(su_home_mutex_unlock(home), 0);
TEST(su_home_trylock(home), -1);
TEST(su_home_threadsafe(home), 0);
TEST(su_home_mutex_lock(home), 0);
TEST(su_home_trylock(home), EBUSY);
TEST(su_home_mutex_unlock(home), 0);
TEST(su_home_lock(home), 0);
TEST(su_home_trylock(home), EBUSY);
TEST(su_home_unlock(home), 0);
TEST(su_home_trylock(home), 0);
TEST(su_home_unlock(home), 0);
END();
}
static int test_strdupcat(void)
{
su_home_t home[1] = { SU_HOME_INIT(home) };
......@@ -708,6 +745,7 @@ int main(int argc, char *argv[])
#endif
retval |= test_alloc();
retval |= test_lock();
retval |= test_strdupcat();
retval |= test_sprintf("%s.%s", "foo", "bar");
retval |= test_strlst();
......@@ -716,4 +754,3 @@ int main(int argc, char *argv[])
return retval;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment