Date: Fri, 31 Dec 2004 15:05:19 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 67985 for review Message-ID: <200412311505.iBVF5JAp009532@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=67985 Change 67985 by davidxu@davidxu_tiger on 2004/12/31 15:04:21 rework thread wakeup code, for priority mutex only. Affected files ... .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_mutex.c#7 edit Differences ... ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_mutex.c#7 (text+ko) ==== @@ -216,8 +216,8 @@ } } -void -_thr_mutex_reinit(pthread_mutex_t *mutex) +int +_mutex_reinit(pthread_mutex_t *mutex) { umtx_init(&(*mutex)->m_lock); TAILQ_INIT(&(*mutex)->m_queue); @@ -227,6 +227,7 @@ (*mutex)->m_refcount = 0; (*mutex)->m_prio = 0; (*mutex)->m_saved_prio = 0; + return (0); } int @@ -490,6 +491,7 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m, const struct timespec * abstime) { + long cycle; int ret = 0; THR_ASSERT((m != NULL) && (*m != NULL), @@ -515,10 +517,16 @@ #endif } else if (umtx_owner(&(*m)->m_lock) == curthread->tid && (*m)->m_type != PTHREAD_MUTEX_NORMAL) { + /* + * We don't do deadlock sleep in mutex_self_lock + * if type is normal, instead let umtx_lock sleep + * in kernel. + */ ret = mutex_self_lock(curthread, *m); } else { if (abstime == NULL) { - ret = UMTX_LOCK(&(*m)->m_lock, curthread->tid); + UMTX_LOCK(&(*m)->m_lock, curthread->tid); + ret = 0; } else { ret = umtx_timedlock(&(*m)->m_lock, curthread->tid, abstime); @@ -548,11 +556,6 @@ abstime->tv_nsec >= 1000000000)) return (EINVAL); - /* Reset the interrupted flag: */ - curthread->interrupted = 0; - curthread->timeout = 0; - curthread->wakeup_time.tv_sec = -1; - /* * Enter a loop waiting to become the mutex owner. We need a * loop in case the waiting thread is interrupted by a signal @@ -613,14 +616,6 @@ /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else { - /* Set the wakeup time: */ - if (abstime) { - curthread->wakeup_time.tv_sec = - abstime->tv_sec; - curthread->wakeup_time.tv_nsec = - abstime->tv_nsec; - } - /* * Join the queue of threads waiting to lock * the mutex and save a pointer to the mutex. @@ -629,23 +624,27 @@ curthread->data.mutex = *m; curthread->sigbackout = mutex_lock_backout; - /* - * This thread is active and is in a critical - * region (holding the mutex lock); we should - * be able to safely set the state. - */ if (curthread->active_priority > (*m)->m_prio) /* Adjust priorities: */ mutex_priority_adjust(curthread, *m); - THR_LOCK_SWITCH(curthread); - THR_SET_STATE(curthread, PS_MUTEX_WAIT); + THR_LOCK(curthread); + cycle = curthread->cycle; + THR_UNLOCK(curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); - /* Schedule the next thread: */ - _thr_sched_switch_unlocked(curthread); + if (abstime) { + ret = umtx_timedwait((struct umtx *)&curthread->cycle, + cycle, abstime); + if (ret == EAGAIN) + ret = ETIMEDOUT; + else + ret = 0; + } else { + umtx_wait((struct umtx *)&curthread->cycle, cycle); + } if (THR_IN_MUTEXQ(curthread)) { THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); @@ -707,14 +706,6 @@ /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else { - /* Set the wakeup time: */ - if (abstime) { - curthread->wakeup_time.tv_sec = - abstime->tv_sec; - curthread->wakeup_time.tv_nsec = - abstime->tv_nsec; - } - /* * Join the queue of threads waiting to lock * the mutex and save a pointer to the mutex. @@ -726,20 +717,23 @@ /* Clear any previous error: */ curthread->error = 0; - /* - * This thread is active and is in a critical - * region (holding the mutex lock); we should - * be able to safely set the state. - */ + THR_LOCK(curthread); + cycle = curthread->cycle; + THR_UNLOCK(curthread); - THR_LOCK_SWITCH(curthread); - THR_SET_STATE(curthread, PS_MUTEX_WAIT); - /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); - /* Schedule the next thread: */ - _thr_sched_switch_unlocked(curthread); + if (abstime) { + ret = umtx_timedwait((struct umtx *)&curthread->cycle, + cycle, abstime); + if (ret == EAGAIN) + ret = ETIMEDOUT; + else + ret = 0; + } else { + umtx_wait((struct umtx *)&curthread->cycle, cycle); + } curthread->data.mutex = NULL; if (THR_IN_MUTEXQ(curthread)) { @@ -774,28 +768,8 @@ break; } - } while (((*m)->m_owner != curthread) && (ret == 0) && - (curthread->interrupted == 0) && (curthread->timeout == 0)); - - if (ret == 0 && (*m)->m_owner != curthread && curthread->timeout) - ret = ETIMEDOUT; - - /* - * Check to see if this thread was interrupted and - * is still in the mutex queue of waiting threads: - */ - if (curthread->interrupted != 0) { - /* Remove this thread from the mutex queue. */ - THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); - if (THR_IN_SYNCQ(curthread)) - mutex_queue_remove(*m, curthread); - THR_LOCK_RELEASE(curthread, &(*m)->m_lock); + } while (((*m)->m_owner != curthread) && (ret == 0)); - /* Check for asynchronous cancellation. */ - if (curthread->continuation != NULL) - curthread->continuation((void *) curthread); - } - /* Return the completion status: */ return (ret); } @@ -971,15 +945,15 @@ * What SS2 define as a 'normal' mutex. Intentionally * deadlock on attempts to get a lock you already own. */ - - THR_LOCK_SWITCH(curthread); - THR_SET_STATE(curthread, PS_DEADLOCK); - - /* Unlock the mutex structure: */ - THR_LOCK_RELEASE(curthread, &m->m_lock); + if (m->m_protocol != PTHREAD_PRIO_NONE) { + /* Unlock the mutex structure: */ + THR_LOCK_RELEASE(curthread, &m->m_lock); + for (;;) + thr_suspend(NULL); + } else { + PANIC("shouldn't be here!\n"); + } - /* Schedule the next thread: */ - _thr_sched_switch_unlocked(curthread); ret = 0; break; @@ -1181,8 +1155,6 @@ /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); - if (tid != -1) - thr_wake(tid); } /* Return the completion status: */ @@ -1712,7 +1684,8 @@ } /* Make the thread runnable and unlock the scheduling queue: */ - tid = _thr_setrunnable_unlocked(pthread); + pthread->cycle++; + umtx_wake((struct umtx *)&pthread->cycle, 1); THR_THREAD_UNLOCK(curthread, pthread); if (mutex->m_owner == pthread) @@ -1741,13 +1714,6 @@ while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) { TAILQ_REMOVE(&mutex->m_queue, pthread, sqe); pthread->sflags &= ~THR_FLAGS_IN_SYNCQ; - - /* - * Only exit the loop if the thread hasn't been - * cancelled. - */ - if (pthread->interrupted == 0) - break; } return (pthread);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412311505.iBVF5JAp009532>