FreeBSD Bugzilla – Attachment 153486 Details for
Bug 198014
Signals can lead to an inconsistency in PI mutex ownership
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
Randomized, racy test case
umtx_signal_race.c (text/x-c), 6.32 KB, created by
eric
on 2015-02-24 22:53:17 UTC
(
hide
)
Description:
Randomized, racy test case
Filename:
MIME Type:
Creator:
eric
Created:
2015-02-24 22:53:17 UTC
Size:
6.32 KB
patch
obsolete
>/*- > * Copyright (c) 2015 Dell Inc. > * All rights reserved. > * > * Author: Eric van Gyzen <eric_van_gyzen dell com> > * > * 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. > */ > >/* > * This is a randomized, racy test case for > * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198014 > */ > >#include <sys/cdefs.h> >#include <sys/types.h> > >#include <machine/cpufunc.h> >#include <machine/cpu.h> > >#include <err.h> >#include <errno.h> >#include <pthread.h> >#include <pthread_np.h> >#include <signal.h> >#include <stdio.h> >#include <stdlib.h> >#include <unistd.h> > >volatile sig_atomic_t got_sigint = 0; > >pthread_mutex_t the_mutex = PTHREAD_MUTEX_INITIALIZER; >pthread_t *the_threads; > >// 2**24 pause instructions is roughly 85 ms on a 2.13GHz Xeon E5606. >const uintptr_t SPIN_MASK = 1UL << 16 - 1; > >static void >spin(uintptr_t count) >{ > while (count-- > 0) > cpu_spinwait(); >} > > >static void * >thread_func(void *arg) >{ > uintptr_t spin_incr = (uintptr_t)arg | 1; // Ensure non-zero. > uintptr_t spin_count = spin_incr & SPIN_MASK; > int error; > > while (!got_sigint) { > error = pthread_mutex_lock(&the_mutex); > if (error) errc(1, error, "pthread_mutex_lock"); > spin(spin_count >> 1); > error = pthread_mutex_unlock(&the_mutex); > if (error) { > // If libthr has been fixed to return the error, > // ignore EPERM so this test will still work (i.e. fail). > if (error == EPERM) > warnc(error, "pthread_mutex_unlock"); > else > errc(1, error, "pthread_mutex_unlock"); > } > if (!got_sigint) { > pthread_yield(); > spin(spin_count << 1); > spin_count = (spin_count + spin_incr) & SPIN_MASK; > } > } > > return (NULL); >} > >static void >usage() >{ > errx(1, "usage: test <thread_count> <random_seed>"); >} > >void >handle_sigwinch(int i __unused) >{ > // do nothing >} > >void >handle_sigint(int i __unused) >{ > got_sigint = 1; >} > >int >main(int argc, char **argv) >{ > size_t thread_count; > unsigned int random_seed; > int error; > > if (argc == 3) { > thread_count = strtoul(argv[1], NULL, 0); > if (thread_count == 0) { > usage(); > } > random_seed = strtoul(argv[2], NULL, 0); > if (random_seed == 0) { > usage(); > } > } else { > usage(); > } > > /* > * The author had good luck with > * thread_count = 1.5 * CPU_count > * on bare metal, > * thread_count = CPU_count > * in a VM, and > * random_seed = 1424141100 > * in all cases. > */ > > printf("thread count: %zu\nrandom seed: %u\n", thread_count, random_seed); > > signal(SIGWINCH, handle_sigwinch); > signal(SIGINT, handle_sigint); > > const int SCHED_POLICY = SCHED_RR; > const int MAX_PRIO = sched_get_priority_max(SCHED_POLICY); > const int MIN_PRIO = sched_get_priority_min(SCHED_POLICY); > > struct sched_param schedp = { > .sched_priority = MAX_PRIO > }; > > // The initial thread will be the signaller. Raise it to max priority. > pthread_set_name_np(pthread_self(), "signaller"); > error = pthread_setschedparam(pthread_self(), SCHED_POLICY, &schedp); > if (error) errc(1, error, "pthread_setschedparam"); > > 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"); > > pthread_attr_t attr; > > error = pthread_attr_init(&attr); > if (error) errc(1, error, "pthread_attr_init"); > > error = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); > if (error) errc(1, error, "pthread_attr_setinheritsched"); > > error = pthread_attr_setschedpolicy(&attr, SCHED_POLICY); > if (error) errc(1, error, "pthread_attr_setschedpolicy"); > > schedp.sched_priority = (MAX_PRIO + MIN_PRIO) / 2; > error = pthread_attr_setschedparam(&attr, &schedp); > if (error) errc(1, error, "pthread_attr_setschedparam"); > > the_threads = malloc(thread_count * sizeof(pthread_t)); > > srand(random_seed); > > uintptr_t i; > for (i = 0; i < thread_count; i++) { > char name[64]; > snprintf(name, sizeof(name), "locker_%lu", i); > error = pthread_create(the_threads + i, &attr, thread_func, > (void *)(uintptr_t)(rand() & SPIN_MASK)); > pthread_set_name_np(the_threads[i], name); > if (error) errc(1, error, "pthread_create[%ju]", i); > } > > error = pthread_attr_destroy(&attr); > if (error) errc(1, error, "pthread_attr_destroy"); > > while (!got_sigint) { > for (i = 0; i < thread_count; i++) { > pthread_kill(the_threads[i], SIGWINCH); > usleep(4000); > } > } > > sleep(1); > > /* > * Show the owner after all contention has ceased, > * to show that the UMUTEX_CONTESTED bit still gets cleared. > */ > printf("mutex owner: %x\n", *(int*)the_mutex); > > return (0); >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 198014
:
153475
|
153476
|
153477
|
153485
| 153486 |
153487
|
153524