diff --git a/include/pthread.h b/include/pthread.h index 0c382710cf13..dc8ebf08b172 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -164,11 +164,16 @@ struct pthread_once { #endif enum pthread_mutextype { - MUTEX_TYPE_FAST = 1, - MUTEX_TYPE_COUNTING_FAST = 2, /* Recursive */ + PTHREAD_MUTEX_DEFAULT = 1, + PTHREAD_MUTEX_RECURSIVE = 2, + PTHREAD_MUTEX_NORMAL = 3, + PTHREAD_MUTEX_ERRORCHECK = 4, MUTEX_TYPE_MAX }; +#define MUTEX_TYPE_FAST PTHREAD_MUTEX_DEFAULT +#define MUTEX_TYPE_COUNTING_FAST PTHREAD_MUTEX_RECURSIVE + /* * Thread function prototype definitions: */ @@ -233,6 +238,7 @@ int pthread_mutexattr_setprotocol __P((pthread_mutexattr_t *, int protocol)); int pthread_mutexattr_setpshared __P((pthread_mutexattr_t *, int pshared)); +int pthread_mutexattr_settype __P((pthread_mutexattr_t *, int)); int pthread_mutex_destroy __P((pthread_mutex_t *)); int pthread_mutex_getprioceiling __P((pthread_mutex_t *)); int pthread_mutex_init __P((pthread_mutex_t *, diff --git a/lib/libc_r/uthread/uthread_mattr_kind_np.c b/lib/libc_r/uthread/uthread_mattr_kind_np.c index 3eeabff038a7..c145a1f89927 100644 --- a/lib/libc_r/uthread/uthread_mattr_kind_np.c +++ b/lib/libc_r/uthread/uthread_mattr_kind_np.c @@ -61,4 +61,18 @@ pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) } return(ret); } + +int +pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + int ret; + if (attr == NULL || *attr == NULL || type >= MUTEX_TYPE_MAX) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->m_type = type; + ret = 0; + } + return(ret); +} #endif diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c index a7e8dfee6b51..d3801f1750c0 100644 --- a/lib/libc_r/uthread/uthread_mutex.c +++ b/lib/libc_r/uthread/uthread_mutex.c @@ -53,7 +53,7 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Check if default mutex attributes: */ if (mutex_attr == NULL || *mutex_attr == NULL) /* Default to a fast mutex: */ - type = MUTEX_TYPE_FAST; + type = PTHREAD_MUTEX_DEFAULT; else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) /* Return an invalid argument error: */ @@ -74,12 +74,14 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { /* Fast mutex: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: /* Nothing to do here. */ break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; @@ -174,7 +176,9 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { /* Fast mutex: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_ERRORCHECK: /* Check if this mutex is not locked: */ if ((*mutex)->m_owner == NULL) { /* Lock the mutex for the running thread: */ @@ -186,7 +190,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Check if this mutex is locked: */ if ((*mutex)->m_owner != NULL) { /* @@ -239,8 +243,26 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { + /* What SS2 define as a 'normal' mutex. This has to deadlock + on attempts to get a lock you already own. */ + case PTHREAD_MUTEX_NORMAL: + if ((*mutex)->m_owner == _thread_run) { + /* Intetionally deadlock */ + for (;;) + _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__); + } + goto COMMON_LOCK; + + /* Return error (not OK) on attempting to re-lock */ + case PTHREAD_MUTEX_ERRORCHECK: + if ((*mutex)->m_owner == _thread_run) { + ret = EDEADLK; + break; + } + /* Fast mutexes do not check for any error conditions: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_DEFAULT: + COMMON_LOCK: /* * Enter a loop to wait for the mutex to be locked by the * current thread: @@ -269,7 +291,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* * Enter a loop to wait for the mutex to be locked by the * current thread: @@ -331,12 +353,15 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutexes do not check for any error conditions: */ - case MUTEX_TYPE_FAST: + /* Default & normal mutexes do not really need to check for + any error conditions: */ + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_ERRORCHECK: /* Check if the running thread is not the owner of the mutex: */ if ((*mutex)->m_owner != _thread_run) { /* Return an invalid argument error: */ - ret = EINVAL; + ret = (*mutex)->m_owner ? EPERM : EINVAL; } /* * Get the next thread from the queue of threads waiting on @@ -349,24 +374,26 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Check if the running thread is not the owner of the mutex: */ if ((*mutex)->m_owner != _thread_run) { /* Return an invalid argument error: */ ret = EINVAL; } /* Check if there are still counts: */ - else if ((*mutex)->m_data.m_count) { + else if ((*mutex)->m_data.m_count > 1) { /* Decrement the count: */ (*mutex)->m_data.m_count--; - } - /* - * Get the next thread from the queue of threads waiting on - * the mutex: - */ - else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { - /* Allow the new owner of the mutex to run: */ - PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } else { + (*mutex)->m_data.m_count = 0; + /* + * Get the next thread from the queue of threads waiting on + * the mutex: + */ + if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { + /* Allow the new owner of the mutex to run: */ + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } } break; diff --git a/lib/libkse/thread/thr_mattr_kind_np.c b/lib/libkse/thread/thr_mattr_kind_np.c index 3eeabff038a7..c145a1f89927 100644 --- a/lib/libkse/thread/thr_mattr_kind_np.c +++ b/lib/libkse/thread/thr_mattr_kind_np.c @@ -61,4 +61,18 @@ pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) } return(ret); } + +int +pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + int ret; + if (attr == NULL || *attr == NULL || type >= MUTEX_TYPE_MAX) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->m_type = type; + ret = 0; + } + return(ret); +} #endif diff --git a/lib/libkse/thread/thr_mutex.c b/lib/libkse/thread/thr_mutex.c index a7e8dfee6b51..d3801f1750c0 100644 --- a/lib/libkse/thread/thr_mutex.c +++ b/lib/libkse/thread/thr_mutex.c @@ -53,7 +53,7 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Check if default mutex attributes: */ if (mutex_attr == NULL || *mutex_attr == NULL) /* Default to a fast mutex: */ - type = MUTEX_TYPE_FAST; + type = PTHREAD_MUTEX_DEFAULT; else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) /* Return an invalid argument error: */ @@ -74,12 +74,14 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { /* Fast mutex: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: /* Nothing to do here. */ break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; @@ -174,7 +176,9 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { /* Fast mutex: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_ERRORCHECK: /* Check if this mutex is not locked: */ if ((*mutex)->m_owner == NULL) { /* Lock the mutex for the running thread: */ @@ -186,7 +190,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Check if this mutex is locked: */ if ((*mutex)->m_owner != NULL) { /* @@ -239,8 +243,26 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { + /* What SS2 define as a 'normal' mutex. This has to deadlock + on attempts to get a lock you already own. */ + case PTHREAD_MUTEX_NORMAL: + if ((*mutex)->m_owner == _thread_run) { + /* Intetionally deadlock */ + for (;;) + _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__); + } + goto COMMON_LOCK; + + /* Return error (not OK) on attempting to re-lock */ + case PTHREAD_MUTEX_ERRORCHECK: + if ((*mutex)->m_owner == _thread_run) { + ret = EDEADLK; + break; + } + /* Fast mutexes do not check for any error conditions: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_DEFAULT: + COMMON_LOCK: /* * Enter a loop to wait for the mutex to be locked by the * current thread: @@ -269,7 +291,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* * Enter a loop to wait for the mutex to be locked by the * current thread: @@ -331,12 +353,15 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutexes do not check for any error conditions: */ - case MUTEX_TYPE_FAST: + /* Default & normal mutexes do not really need to check for + any error conditions: */ + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_ERRORCHECK: /* Check if the running thread is not the owner of the mutex: */ if ((*mutex)->m_owner != _thread_run) { /* Return an invalid argument error: */ - ret = EINVAL; + ret = (*mutex)->m_owner ? EPERM : EINVAL; } /* * Get the next thread from the queue of threads waiting on @@ -349,24 +374,26 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Check if the running thread is not the owner of the mutex: */ if ((*mutex)->m_owner != _thread_run) { /* Return an invalid argument error: */ ret = EINVAL; } /* Check if there are still counts: */ - else if ((*mutex)->m_data.m_count) { + else if ((*mutex)->m_data.m_count > 1) { /* Decrement the count: */ (*mutex)->m_data.m_count--; - } - /* - * Get the next thread from the queue of threads waiting on - * the mutex: - */ - else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { - /* Allow the new owner of the mutex to run: */ - PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } else { + (*mutex)->m_data.m_count = 0; + /* + * Get the next thread from the queue of threads waiting on + * the mutex: + */ + if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { + /* Allow the new owner of the mutex to run: */ + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } } break; diff --git a/lib/libpthread/thread/thr_mattr_kind_np.c b/lib/libpthread/thread/thr_mattr_kind_np.c index 3eeabff038a7..c145a1f89927 100644 --- a/lib/libpthread/thread/thr_mattr_kind_np.c +++ b/lib/libpthread/thread/thr_mattr_kind_np.c @@ -61,4 +61,18 @@ pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) } return(ret); } + +int +pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + int ret; + if (attr == NULL || *attr == NULL || type >= MUTEX_TYPE_MAX) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->m_type = type; + ret = 0; + } + return(ret); +} #endif diff --git a/lib/libpthread/thread/thr_mutex.c b/lib/libpthread/thread/thr_mutex.c index a7e8dfee6b51..d3801f1750c0 100644 --- a/lib/libpthread/thread/thr_mutex.c +++ b/lib/libpthread/thread/thr_mutex.c @@ -53,7 +53,7 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Check if default mutex attributes: */ if (mutex_attr == NULL || *mutex_attr == NULL) /* Default to a fast mutex: */ - type = MUTEX_TYPE_FAST; + type = PTHREAD_MUTEX_DEFAULT; else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) /* Return an invalid argument error: */ @@ -74,12 +74,14 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { /* Fast mutex: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: /* Nothing to do here. */ break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; @@ -174,7 +176,9 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { /* Fast mutex: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_ERRORCHECK: /* Check if this mutex is not locked: */ if ((*mutex)->m_owner == NULL) { /* Lock the mutex for the running thread: */ @@ -186,7 +190,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Check if this mutex is locked: */ if ((*mutex)->m_owner != NULL) { /* @@ -239,8 +243,26 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { + /* What SS2 define as a 'normal' mutex. This has to deadlock + on attempts to get a lock you already own. */ + case PTHREAD_MUTEX_NORMAL: + if ((*mutex)->m_owner == _thread_run) { + /* Intetionally deadlock */ + for (;;) + _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__); + } + goto COMMON_LOCK; + + /* Return error (not OK) on attempting to re-lock */ + case PTHREAD_MUTEX_ERRORCHECK: + if ((*mutex)->m_owner == _thread_run) { + ret = EDEADLK; + break; + } + /* Fast mutexes do not check for any error conditions: */ - case MUTEX_TYPE_FAST: + case PTHREAD_MUTEX_DEFAULT: + COMMON_LOCK: /* * Enter a loop to wait for the mutex to be locked by the * current thread: @@ -269,7 +291,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* * Enter a loop to wait for the mutex to be locked by the * current thread: @@ -331,12 +353,15 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutexes do not check for any error conditions: */ - case MUTEX_TYPE_FAST: + /* Default & normal mutexes do not really need to check for + any error conditions: */ + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_DEFAULT: + case PTHREAD_MUTEX_ERRORCHECK: /* Check if the running thread is not the owner of the mutex: */ if ((*mutex)->m_owner != _thread_run) { /* Return an invalid argument error: */ - ret = EINVAL; + ret = (*mutex)->m_owner ? EPERM : EINVAL; } /* * Get the next thread from the queue of threads waiting on @@ -349,24 +374,26 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) break; /* Counting mutex: */ - case MUTEX_TYPE_COUNTING_FAST: + case PTHREAD_MUTEX_RECURSIVE: /* Check if the running thread is not the owner of the mutex: */ if ((*mutex)->m_owner != _thread_run) { /* Return an invalid argument error: */ ret = EINVAL; } /* Check if there are still counts: */ - else if ((*mutex)->m_data.m_count) { + else if ((*mutex)->m_data.m_count > 1) { /* Decrement the count: */ (*mutex)->m_data.m_count--; - } - /* - * Get the next thread from the queue of threads waiting on - * the mutex: - */ - else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { - /* Allow the new owner of the mutex to run: */ - PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } else { + (*mutex)->m_data.m_count = 0; + /* + * Get the next thread from the queue of threads waiting on + * the mutex: + */ + if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { + /* Allow the new owner of the mutex to run: */ + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } } break;