Blame stdlib/test-atexit-race-common.c

Packit 6c4009
/* Bug 14333: Support file for atexit/exit, etc. race tests.
Packit 6c4009
   Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* This file must be run from within a directory called "stdlib".  */
Packit 6c4009
Packit 6c4009
/* The atexit/exit, at_quick_exit/quick_exit, __cxa_atexit/exit, etc.
Packit 6c4009
   exhibited data race while accessing destructor function list (Bug 14333).
Packit 6c4009
Packit 6c4009
   This test spawns large number of threads, which all race to register
Packit 6c4009
   large number of destructors.
Packit 6c4009
Packit 6c4009
   Before the fix, running this test resulted in a SIGSEGV.
Packit 6c4009
   After the fix, we expect clean process termination.  */
Packit 6c4009
Packit 6c4009
#if !defined(CALL_EXIT) || !defined(CALL_ATEXIT)
Packit 6c4009
#error Must define CALL_EXIT and CALL_ATEXIT before using this file.
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <support/xthread.h>
Packit 6c4009
#include <limits.h>
Packit 6c4009
Packit 6c4009
const size_t kNumThreads = 1024;
Packit 6c4009
const size_t kNumHandlers = 1024;
Packit 6c4009
const size_t kStacksize =
Packit 6c4009
#ifdef PTHREAD_STACK_MIN
Packit 6c4009
	0x20000 < PTHREAD_STACK_MIN ? PTHREAD_STACK_MIN :
Packit 6c4009
#endif
Packit 6c4009
		0x20000;
Packit 6c4009
Packit 6c4009
static void *
Packit 6c4009
threadfunc (void *unused)
Packit 6c4009
{
Packit 6c4009
  size_t i;
Packit 6c4009
  for (i = 0; i < kNumHandlers; ++i) {
Packit 6c4009
    CALL_ATEXIT;
Packit 6c4009
  }
Packit 6c4009
  return NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  size_t i;
Packit 6c4009
  pthread_attr_t attr;
Packit 6c4009
Packit 6c4009
  xpthread_attr_init (&attr);
Packit 6c4009
  xpthread_attr_setdetachstate (&attr, 1);
Packit 6c4009
Packit 6c4009
  /* With default 8MiB Linux stack size, creating 1024 threads can cause
Packit 6c4009
     VM exhausiton on 32-bit machines.  Reduce stack size of each thread to
Packit 6c4009
     128KiB for a maximum required VM size of 128MiB.  */
Packit 6c4009
  xpthread_attr_setstacksize (&attr, kStacksize);
Packit 6c4009
Packit 6c4009
  for (i = 0; i < kNumThreads; ++i) {
Packit 6c4009
    xpthread_create (&attr, threadfunc, NULL);
Packit 6c4009
  }
Packit 6c4009
  xpthread_attr_destroy (&attr);
Packit 6c4009
Packit 6c4009
  CALL_EXIT;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define TEST_FUNCTION do_test
Packit 6c4009
#include <support/test-driver.c>