threads/150889: PTHREAD_MUTEX_INITIALIZER
+ pthread_mutex_destroy () == EINVAL
Jung-uk Kim
jkim at FreeBSD.org
Fri Sep 24 21:11:31 UTC 2010
On Friday 24 September 2010 11:37 am, Jung-uk Kim wrote:
> On Friday 24 September 2010 09:26 am, John Baldwin wrote:
> > On Thursday, September 23, 2010 11:48:40 pm Jung-uk Kim wrote:
> > > On Thursday 23 September 2010 06:44 pm, Daniel Eischen wrote:
> > > > You shouldn't have to call pthread_mutex_init() on a mutex
> > > > initialized with PTHREAD_MUTEX_INITIALIZER. Our
> > > > implementation should auto initialize the mutex when it is
> > > > first used; if it doesn't, I think that is a bug.
> > >
> > > Ah, I see. I verified that libthr does it correctly. However,
> > > that's a hack and it is far from real static allocation
> > > although it should work pretty well in reality, IMHO. More
> > > over, it will have a side-effect, i.e., any destroyed mutex may
> > > be resurrected if it is used again. POSIX seems to say it
> > > should return EINVAL when it happens. :-(
> >
> > I think the fix there is that we should put a different value
> > ((void *)1 for example) into "destroyed" mutex objects than 0 so
> > that destroyed mutexes can be differentiated from statically
> > initialized mutexes. This would also allow us to properly return
> > EBUSY, etc.
>
> It would be nice if we had "uninitialized" as (void *)0 and "static
> initializer" as (void *)1. IMHO, it looks more natural, i.e.,
> "uninitialized" or "destroyed" one gets zero, and "dynamically
> initialized" or "statically initialized" one gets non-zero. Can we
> break the ABI for 9, maybe? ;-)
--------------------------------
WARNING!!! WARNING!!! WARNING!!!
--------------------------------
This patch is a proof of concept!
This patch massively breaks pthread ABI!
This patch may crash and burn your system!
I couldn't resist trying. ;-)
Jung-uk Kim
-------------- next part --------------
--- include/pthread.h 2009-03-14 16:10:14.000000000 -0400
+++ include/pthread.h 2010-09-24 16:34:45.000000000 -0400
@@ -97,10 +97,10 @@
/*
* Static initialization values.
*/
-#define PTHREAD_MUTEX_INITIALIZER NULL
-#define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP NULL
-#define PTHREAD_COND_INITIALIZER NULL
-#define PTHREAD_RWLOCK_INITIALIZER NULL
+#define PTHREAD_MUTEX_INITIALIZER ((void *)1)
+#define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP ((void *)1)
+#define PTHREAD_COND_INITIALIZER ((void *)1)
+#define PTHREAD_RWLOCK_INITIALIZER ((void *)1)
/*
* Default attribute arguments (draft 4, deprecated).
--- lib/libthr/thread/thr_cond.c 2010-09-01 12:13:31.000000000 -0400
+++ lib/libthr/thread/thr_cond.c 2010-09-24 15:36:56.000000000 -0400
@@ -94,7 +94,7 @@ init_static(struct pthread *thread, pthr
THR_LOCK_ACQUIRE(thread, &_cond_static_lock);
- if (*cond == NULL)
+ if (*cond == STATIC_INITIALIZER)
ret = cond_init(cond, NULL);
else
ret = 0;
@@ -121,6 +121,8 @@ _pthread_cond_destroy(pthread_cond_t *co
if (*cond == NULL)
rval = EINVAL;
+ else if (*cond == STATIC_INITIALIZER)
+ *cond = NULL;
else {
cv = *cond;
THR_UMUTEX_LOCK(curthread, &cv->c_lock);
@@ -184,7 +186,7 @@ cond_wait_common(pthread_cond_t *cond, p
* If the condition variable is statically initialized,
* perform the dynamic initialization:
*/
- if (__predict_false(*cond == NULL &&
+ if (__predict_false(*cond == STATIC_INITIALIZER &&
(ret = init_static(curthread, cond)) != 0))
return (ret);
@@ -273,7 +275,7 @@ cond_signal_common(pthread_cond_t *cond,
* If the condition variable is statically initialized, perform dynamic
* initialization.
*/
- if (__predict_false(*cond == NULL &&
+ if (__predict_false(*cond == STATIC_INITIALIZER &&
(ret = init_static(curthread, cond)) != 0))
return (ret);
--- lib/libthr/thread/thr_mutex.c 2010-09-01 12:13:32.000000000 -0400
+++ lib/libthr/thread/thr_mutex.c 2010-09-24 16:32:07.000000000 -0400
@@ -184,7 +184,7 @@ init_static(struct pthread *thread, pthr
THR_LOCK_ACQUIRE(thread, &_mutex_static_lock);
- if (*mutex == NULL)
+ if (*mutex == STATIC_INITIALIZER)
ret = mutex_init(mutex, NULL, calloc);
else
ret = 0;
@@ -263,6 +263,8 @@ _pthread_mutex_destroy(pthread_mutex_t *
if (__predict_false(*mutex == NULL))
ret = EINVAL;
+ else if (*mutex == STATIC_INITIALIZER)
+ *mutex = NULL;
else {
id = TID(curthread);
@@ -346,7 +348,7 @@ __pthread_mutex_trylock(pthread_mutex_t
* If the mutex is statically initialized, perform the dynamic
* initialization:
*/
- if (__predict_false(*mutex == NULL)) {
+ if (__predict_false(*mutex == STATIC_INITIALIZER)) {
ret = init_static(curthread, mutex);
if (__predict_false(ret))
return (ret);
@@ -454,7 +456,7 @@ __pthread_mutex_lock(pthread_mutex_t *mu
* If the mutex is statically initialized, perform the dynamic
* initialization:
*/
- if (__predict_false((m = *mutex) == NULL)) {
+ if (__predict_false((m = *mutex) == STATIC_INITIALIZER)) {
ret = init_static(curthread, mutex);
if (__predict_false(ret))
return (ret);
@@ -479,7 +481,7 @@ __pthread_mutex_timedlock(pthread_mutex_
* If the mutex is statically initialized, perform the dynamic
* initialization:
*/
- if (__predict_false((m = *mutex) == NULL)) {
+ if (__predict_false((m = *mutex) == STATIC_INITIALIZER)) {
ret = init_static(curthread, mutex);
if (__predict_false(ret))
return (ret);
@@ -614,6 +616,9 @@ mutex_unlock_common(pthread_mutex_t *mut
if (__predict_false((m = *mutex) == NULL))
return (EINVAL);
+ if (*mutex == STATIC_INITIALIZER)
+ return (EPERM);
+
/*
* Check if the running thread is not the owner of the mutex.
*/
@@ -749,7 +754,7 @@ __pthread_mutex_setspinloops_np(pthread_
struct pthread *curthread = _get_curthread();
int ret;
- if (__predict_false(*mutex == NULL)) {
+ if (__predict_false(*mutex == STATIC_INITIALIZER)) {
ret = init_static(curthread, mutex);
if (__predict_false(ret))
return (ret);
@@ -773,7 +778,7 @@ __pthread_mutex_setyieldloops_np(pthread
struct pthread *curthread = _get_curthread();
int ret;
- if (__predict_false(*mutex == NULL)) {
+ if (__predict_false(*mutex == STATIC_INITIALIZER)) {
ret = init_static(curthread, mutex);
if (__predict_false(ret))
return (ret);
@@ -788,7 +793,7 @@ _pthread_mutex_isowned_np(pthread_mutex_
struct pthread *curthread = _get_curthread();
int ret;
- if (__predict_false(*mutex == NULL)) {
+ if (__predict_false(*mutex == STATIC_INITIALIZER)) {
ret = init_static(curthread, mutex);
if (__predict_false(ret))
return (ret);
--- lib/libthr/thread/thr_private.h 2010-09-24 12:01:02.000000000 -0400
+++ lib/libthr/thread/thr_private.h 2010-09-24 14:43:35.000000000 -0400
@@ -125,6 +125,8 @@ TAILQ_HEAD(mutex_queue, pthread_mutex);
} \
} while (0)
+#define STATIC_INITIALIZER ((void *)1)
+
struct pthread_mutex {
/*
* Lock for accesses to this structure.
--- lib/libthr/thread/thr_rwlock.c 2009-07-06 05:31:04.000000000 -0400
+++ lib/libthr/thread/thr_rwlock.c 2010-09-24 16:45:37.000000000 -0400
@@ -64,10 +64,12 @@ rwlock_init(pthread_rwlock_t *rwlock, co
int
_pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
{
- int ret;
+ int ret = 0;
if (rwlock == NULL)
ret = EINVAL;
+ else if (*rwlock == STATIC_INITIALIZER)
+ *rwlock = NULL;
else {
pthread_rwlock_t prwlock;
@@ -75,7 +77,6 @@ _pthread_rwlock_destroy (pthread_rwlock_
*rwlock = NULL;
free(prwlock);
- ret = 0;
}
return (ret);
}
@@ -87,7 +88,7 @@ init_static(struct pthread *thread, pthr
THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock);
- if (*rwlock == NULL)
+ if (*rwlock == STATIC_INITIALIZER)
ret = rwlock_init(rwlock, NULL);
else
ret = 0;
@@ -119,7 +120,7 @@ rwlock_rdlock_common(pthread_rwlock_t *r
prwlock = *rwlock;
/* check for static initialization */
- if (__predict_false(prwlock == NULL)) {
+ if (__predict_false(prwlock == STATIC_INITIALIZER)) {
if ((ret = init_static(curthread, rwlock)) != 0)
return (ret);
@@ -212,7 +213,7 @@ _pthread_rwlock_tryrdlock (pthread_rwloc
prwlock = *rwlock;
/* check for static initialization */
- if (__predict_false(prwlock == NULL)) {
+ if (__predict_false(prwlock == STATIC_INITIALIZER)) {
if ((ret = init_static(curthread, rwlock)) != 0)
return (ret);
@@ -256,7 +257,7 @@ _pthread_rwlock_trywrlock (pthread_rwloc
prwlock = *rwlock;
/* check for static initialization */
- if (__predict_false(prwlock == NULL)) {
+ if (__predict_false(prwlock == STATIC_INITIALIZER)) {
if ((ret = init_static(curthread, rwlock)) != 0)
return (ret);
@@ -283,7 +284,7 @@ rwlock_wrlock_common (pthread_rwlock_t *
prwlock = *rwlock;
/* check for static initialization */
- if (__predict_false(prwlock == NULL)) {
+ if (__predict_false(prwlock == STATIC_INITIALIZER)) {
if ((ret = init_static(curthread, rwlock)) != 0)
return (ret);
@@ -364,6 +365,9 @@ _pthread_rwlock_unlock (pthread_rwlock_t
if (__predict_false(prwlock == NULL))
return (EINVAL);
+ if (prwlock == STATIC_INITIALIZER)
+ return (EPERM);
+
state = prwlock->lock.rw_state;
if (state & URWLOCK_WRITE_OWNER) {
if (__predict_false(prwlock->owner != curthread))
More information about the freebsd-threads
mailing list