#!/bin/sh # The program is a test case by Eric which demonstrates the # bug, unkillable spinning thread, owning a spinlock. # "panic: spin lock held too long" seen. # Fixed in r277970. . ../default.cfg here=`pwd` cd /tmp sed '1,/^EOF/d' < $here/$0 > kern_umtx_inf_loop.c mycc -o kern_umtx_inf_loop -Wall -Wextra -O0 -g kern_umtx_inf_loop.c \ -lpthread || exit 1 rm -f kern_umtx_inf_loop.c /tmp/kern_umtx_inf_loop rm -f /tmp/kern_umtx_inf_loop exit 0 EOF /*- * Copyright (c) 2015 Eric van Gyzen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include pthread_mutex_t the_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_t contender; static void * contender_func(void *arg) { int error; (void) arg; error = pthread_mutex_lock(&the_mutex); if (error) errc(1, error, "pthread_mutex_lock contender"); fprintf(stderr, "contender lock succeeded\n"); error = pthread_mutex_unlock(&the_mutex); if (error) errc(1, error, "pthread_mutex_unlock contender"); fprintf(stderr, "contender unlock succeeded; exiting\n"); return (NULL); } static void * signaler_func(void *arg __unused) { int error; // Wait for the main thread to sleep. usleep(100000); error = pthread_kill(contender, SIGHUP); if (error) errc(1, error, "pthread_kill"); // Wait for the contender to lock umtx_lock // in umtx_repropagate_priority. usleep(100000); error = pthread_mutex_lock(&the_mutex); if (error) errc(1, error, "pthread_mutex_lock signaler"); return (NULL); } int main(void) { int error; pthread_mutexattr_t mattr; error = pthread_mutexattr_init(&mattr); if (error) errc(1, error, "pthread_mutexattr_init"); error = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT); if (error) errc(1, error, "pthread_mutexattr_setprotocol"); error = pthread_mutex_init(&the_mutex, &mattr); if (error) errc(1, error, "pthread_mutex_init"); error = pthread_mutexattr_destroy(&mattr); if (error) errc(1, error, "pthread_mutexattr_destroy"); //error = pthread_mutex_lock(&the_mutex); //if (error) errc(1, error, "pthread_mutex_lock"); // Hack lock. *(int *)the_mutex = pthread_getthreadid_np(); error = pthread_create(&contender, NULL, contender_func, NULL); if (error) errc(1, error, "pthread_create"); // Wait for the contender to sleep. usleep(100000); pthread_t signaler; error = pthread_create(&signaler, NULL, signaler_func, NULL); if (error) errc(1, error, "pthread_create"); error = pthread_mutex_lock(&the_mutex); if (error) errc(1, error, "pthread_mutex_lock recurse"); return (0); }