From owner-freebsd-bugs Thu Jan 11 16:20:21 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 1E69437B6A5 for ; Thu, 11 Jan 2001 16:20:01 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f0C0K1020097; Thu, 11 Jan 2001 16:20:01 -0800 (PST) (envelope-from gnats) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id D812E37B6A4 for ; Thu, 11 Jan 2001 16:12:53 -0800 (PST) Received: (from nobody@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f0C0Crs19290; Thu, 11 Jan 2001 16:12:53 -0800 (PST) (envelope-from nobody) Message-Id: <200101120012.f0C0Crs19290@freefall.freebsd.org> Date: Thu, 11 Jan 2001 16:12:53 -0800 (PST) From: nuspl@polyserve.com To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-1.0 Subject: misc/24261: pthread_mutex_lock/pthread_mutex_unlock does not honor PTHREAD_MUTEX_ERRORCHECK Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 24261 >Category: misc >Synopsis: pthread_mutex_lock/pthread_mutex_unlock does not honor PTHREAD_MUTEX_ERRORCHECK >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Jan 11 16:20:00 PST 2001 >Closed-Date: >Last-Modified: >Originator: Joe Nuspl >Release: 4.2 >Organization: PolyServe Inc. >Environment: FreeBSD tm16.pdx.polyserve.com 4.2-RELEASE FreeBSD 4.2-RELEASE #0: Mon Nov 20 13:02:55 GMT 2000 jkh@bento.FreeBSD.org:/usr/src/sys/compile/GENERIC i386 >Description: The pthread_mutex_lock() and pthread_mutex_unlock() routines do not honor the PTHREAD_MUTEX_ERRORCHECK type. >How-To-Repeat: #include #include #include #include int main(int argc, char **argv) { int failed = -1; int rv; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutexattr_t attr; rv = pthread_mutexattr_init(&attr); if (rv != 0) { (void)perror("pthread_mutexattr_init"); return failed; } rv = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); if (rv != 0) { perror("pthread_mutexattr_settype"); goto unwind_attr; } rv = pthread_mutex_init(&mutex, &attr); if (rv != 0) { perror("pthread_mutex_init"); goto unwind_attr; } rv = pthread_mutex_unlock(&mutex); if (rv != EPERM) { perror("pthread_mutex_unlock"); } rv = pthread_mutex_lock(&mutex); if (rv != 0) { perror("pthread_mutex_lock"); goto unwind_mutex; } rv = pthread_mutex_lock(&mutex); if (rv == EDEADLK) { failed = 0; } else { (void)fprintf(stderr, "rv=%d\n", rv); failed = 1; } (void)fprintf(stderr, "PTHREAD_MUTEX_ERRORCHECK %s\n", (failed ? "failed" : "passed")); unwind_mutex: (void)pthread_mutex_destroy(&mutex); unwind_attr: (void)pthread_mutexattr_destroy(&attr); return (failed); } >Fix: Applying the attached patch to /usr/src/lib/libc_r/uthread/uthread_mutex.c adds the needed error checks to the routines. The patch for mutex_unlock_common() is a quick and dirty fix. It could be improved. --- uthread_mutex.c.orig Thu Jan 11 16:44:56 2001 +++ uthread_mutex.c Thu Jan 11 17:02:19 2001 @@ -420,6 +420,22 @@ _thread_run->interrupted = 0; /* + * According to: + * http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_mutex_lock.html + * If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error + * checking is provided. If a thread attempts to relock a mutex + * that it has already locked, an error will be returned. + * + * The pthread_mutex_lock() function may fail if: + * [EDEADLK] + * The current thread already owns the mutex. + */ + if (((*mutex)->m_owner == _thread_run) && + ((*mutex)->m_type == PTHREAD_MUTEX_ERRORCHECK)) { + return (EDEADLK); + } + + /* * Enter a loop waiting to become the mutex owner. We need a * loop in case the waiting thread is interrupted by a signal * to execute a signal handler. It is not (currently) possible @@ -739,6 +755,7 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) { int ret = 0; + int proto; if (mutex == NULL || *mutex == NULL) { ret = EINVAL; @@ -752,8 +769,33 @@ /* Lock the mutex structure: */ _SPINLOCK(&(*mutex)->lock); + proto = (*mutex)->m_protocol; + + /* + * According to: + * http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_mutex_lock.html + * + * If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then + * error checking is provided. If a thread attempts to + * unlock a mutex that it has not locked or a mutex which + * is unlocked, an error will be returned. + * + * The pthread_mutex_unlock() function may fail if: + * [EPERM] + * The current thread does not own the mutex. + */ + if (((*mutex)->m_owner != _thread_run) && + ((*mutex)->m_type == PTHREAD_MUTEX_ERRORCHECK)) { + proto = -1; + ret = EPERM; + } + /* Process according to mutex type: */ - switch ((*mutex)->m_protocol) { + switch (proto) { + case -1: + /* we've already caught an error, do nothing */ + break; + /* Default POSIX mutex: */ case PTHREAD_PRIO_NONE: /* >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message