1// -*- C++ -*- 2 3// Utility subroutines for the C++ library testsuite. 4// 5// Copyright (C) 2002-2015 Free Software Foundation, Inc. 6// 7// This file is part of the GNU ISO C++ Library. This library is free 8// software; you can redistribute it and/or modify it under the 9// terms of the GNU General Public License as published by the 10// Free Software Foundation; either version 3, or (at your option) 11// any later version. 12// 13// This library is distributed in the hope that it will be useful, 14// but WITHOUT ANY WARRANTY; without even the implied warranty of 15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16// GNU General Public License for more details. 17// 18// You should have received a copy of the GNU General Public License along 19// with this library; see the file COPYING3. If not see 20// <http://www.gnu.org/licenses/>. 21// 22 23#include <testsuite_hooks.h> 24 25#ifdef _GLIBCXX_RES_LIMITS 26#include <unistd.h> 27#include <sys/time.h> 28#include <sys/resource.h> 29#endif 30 31#include <list> 32#include <string> 33#include <stdexcept> 34#include <clocale> 35#include <cstdlib> 36#include <locale> 37#include <cxxabi.h> 38 39// If we have <sys/types.h>, <sys/ipc.h>, and <sys/sem.h>, then assume 40// that System V semaphores are available. 41#if defined(_GLIBCXX_HAVE_SYS_TYPES_H) \ 42 && defined(_GLIBCXX_HAVE_SYS_IPC_H) \ 43 && defined(_GLIBCXX_HAVE_SYS_SEM_H) 44#define _GLIBCXX_SYSV_SEM 45#endif 46 47#ifdef _GLIBCXX_SYSV_SEM 48#include <sys/types.h> 49#include <sys/ipc.h> 50#include <sys/sem.h> 51#endif 52 53namespace __gnu_test 54{ 55#ifdef _GLIBCXX_RES_LIMITS 56 void 57 set_memory_limits(float size) 58 { 59 struct rlimit r; 60 // Cater to the absence of rlim_t. 61 __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur))(size * 1048576); 62 63 // Heap size, seems to be common. 64#if _GLIBCXX_HAVE_LIMIT_DATA 65 getrlimit(RLIMIT_DATA, &r); 66 r.rlim_cur = limit; 67 setrlimit(RLIMIT_DATA, &r); 68#endif 69 70 // Resident set size. 71#if _GLIBCXX_HAVE_LIMIT_RSS 72 getrlimit(RLIMIT_RSS, &r); 73 r.rlim_cur = limit; 74 setrlimit(RLIMIT_RSS, &r); 75#endif 76 77 // Mapped memory (brk + mmap). 78#if _GLIBCXX_HAVE_LIMIT_VMEM 79 getrlimit(RLIMIT_VMEM, &r); 80 r.rlim_cur = limit; 81 setrlimit(RLIMIT_VMEM, &r); 82#endif 83 84 // Virtual memory. On x86_64-linux, the default is -z 85 // max-page-size=0x200000 which means up to 2MB of address space 86 // are accounted for PROT_NONE mappings between text and data 87 // segments of each shared library. There are 4 shared libs 88 // involved in addition to the dynamic linker, maybe 5 if libgomp 89 // is being used as well. Use at least 20MB address space limit. 90#if defined(__x86_64__) && defined(__linux__) 91 if (limit < 20971520) 92 limit = 20971520; 93#endif 94 95 // On HP-UX 11.23, a trivial C++ program that sets RLIMIT_AS to 96 // anything less than 128MB cannot "malloc" even 1K of memory. 97 // Therefore, we skip RLIMIT_AS on HP-UX. 98#if _GLIBCXX_HAVE_LIMIT_AS && !defined(__hpux__) 99 getrlimit(RLIMIT_AS, &r); 100 r.rlim_cur = limit; 101 setrlimit(RLIMIT_AS, &r); 102#endif 103 } 104 105#else 106 void 107 set_memory_limits(float) { } 108#endif 109 110#ifdef _GLIBCXX_RES_LIMITS 111 void 112 set_file_limit(unsigned long size) 113 { 114#if _GLIBCXX_HAVE_LIMIT_FSIZE 115 struct rlimit r; 116 // Cater to the absence of rlim_t. 117 __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur))(size); 118 119 getrlimit(RLIMIT_FSIZE, &r); 120 r.rlim_cur = limit; 121 setrlimit(RLIMIT_FSIZE, &r); 122#endif 123 } 124 125#else 126 void 127 set_file_limit(unsigned long) { } 128#endif 129 130 void 131 verify_demangle(const char* mangled, const char* wanted) 132 { 133 int status = 0; 134 const char* s = abi::__cxa_demangle(mangled, 0, 0, &status); 135 if (!s) 136 { 137 switch (status) 138 { 139 case 0: 140 s = "error code = 0: success"; 141 break; 142 case -1: 143 s = "error code = -1: memory allocation failure"; 144 break; 145 case -2: 146 s = "error code = -2: invalid mangled name"; 147 break; 148 case -3: 149 s = "error code = -3: invalid arguments"; 150 break; 151 default: 152 s = "error code unknown - who knows what happened"; 153 } 154 } 155 156 std::string w(wanted); 157 if (w != s) 158 std::__throw_runtime_error(s); 159 } 160 161 void 162 run_tests_wrapped_locale(const char* name, const func_callback& l) 163 { 164 using namespace std; 165 166 // Set the global locale. 167 locale loc_name = locale(name); 168 locale orig = locale::global(loc_name); 169 170 const char* res = setlocale(LC_ALL, name); 171 if (res) 172 { 173 string preLC_ALL = res; 174 const func_callback::test_type* tests = l.tests(); 175 for (int i = 0; i < l.size(); ++i) 176 (*tests[i])(); 177 string postLC_ALL= setlocale(LC_ALL, 0); 178 VERIFY( preLC_ALL == postLC_ALL ); 179 } 180 else 181 { 182 string s("LC_ALL for "); 183 s += name; 184 __throw_runtime_error(s.c_str()); 185 } 186 } 187 188 void 189 run_tests_wrapped_env(const char* name, const char* env, 190 const func_callback& l) 191 { 192 using namespace std; 193 194#ifdef _GLIBCXX_HAVE_SETENV 195 // Set the global locale. 196 locale loc_name = locale(name); 197 locale orig = locale::global(loc_name); 198 199 // Set environment variable env to value in name. 200 const char* oldENV = getenv(env); 201 if (!setenv(env, name, 1)) 202 { 203 const func_callback::test_type* tests = l.tests(); 204 for (int i = 0; i < l.size(); ++i) 205 (*tests[i])(); 206 setenv(env, oldENV ? oldENV : "", 1); 207 } 208 else 209 { 210 string s(env); 211 s += string(" to "); 212 s += string(name); 213 __throw_runtime_error(s.c_str()); 214 } 215#endif 216 } 217 218 object_counter::size_type object_counter::count = 0; 219 unsigned int copy_constructor::count_ = 0; 220 unsigned int copy_constructor::throw_on_ = 0; 221 unsigned int assignment_operator::count_ = 0; 222 unsigned int assignment_operator::throw_on_ = 0; 223 unsigned int destructor::_M_count = 0; 224 int copy_tracker::next_id_ = 0; 225 226#ifdef _GLIBCXX_SYSV_SEM 227 // This union is not declared in system headers. Instead, it must 228 // be defined by user programs. 229 union semun 230 { 231 int val; 232 struct semid_ds *buf; 233 unsigned short *array; 234 }; 235#endif 236 237 semaphore::semaphore() 238 { 239#ifdef _GLIBCXX_SYSV_SEM 240 // Remember the PID for the process that created the semaphore set 241 // so that only one process will destroy the set. 242 pid_ = getpid(); 243 244 // GLIBC does not define SEM_R and SEM_A. 245#ifndef SEM_R 246#define SEM_R 0400 247#endif 248 249#ifndef SEM_A 250#define SEM_A 0200 251#endif 252 253 // Get a semaphore set with one semaphore. 254 sem_set_ = semget(IPC_PRIVATE, 1, SEM_R | SEM_A); 255 if (sem_set_ == -1) 256 std::__throw_runtime_error("could not obtain semaphore set"); 257 258 // Initialize the semaphore. 259 union semun val; 260 val.val = 0; 261 if (semctl(sem_set_, 0, SETVAL, val) == -1) 262 std::__throw_runtime_error("could not initialize semaphore"); 263#else 264 // There are no semaphores on this system. We have no way to mark 265 // a test as "unsupported" at runtime, so we just exit, pretending 266 // that the test passed. 267 exit(0); 268#endif 269 } 270 271 semaphore::~semaphore() 272 { 273#ifdef _GLIBCXX_SYSV_SEM 274 union semun val; 275 val.val = 0; // Avoid uninitialized variable warning. 276 // Destroy the semaphore set only in the process that created it. 277 if (pid_ == getpid()) 278 semctl(sem_set_, 0, IPC_RMID, val); 279#endif 280 } 281 282 void 283 semaphore::signal() 284 { 285#ifdef _GLIBCXX_SYSV_SEM 286 struct sembuf op[1] = 287 { 288 { 0, 1, 0 } 289 }; 290 if (semop(sem_set_, op, 1) == -1) 291 std::__throw_runtime_error("could not signal semaphore"); 292#endif 293 } 294 295 void 296 semaphore::wait() 297 { 298#ifdef _GLIBCXX_SYSV_SEM 299 struct sembuf op[1] = 300 { 301 { 0, -1, SEM_UNDO } 302 }; 303 if (semop(sem_set_, op, 1) == -1) 304 std::__throw_runtime_error("could not wait for semaphore"); 305#endif 306 } 307 308 // For use in 22_locale/time_get and time_put. 309 std::tm 310 test_tm(int sec, int min, int hour, int mday, int mon, 311 int year, int wday, int yday, int isdst) 312 { 313 static std::tm tmp; 314 tmp.tm_sec = sec; 315 tmp.tm_min = min; 316 tmp.tm_hour = hour; 317 tmp.tm_mday = mday; 318 tmp.tm_mon = mon; 319 tmp.tm_year = year; 320 tmp.tm_wday = wday; 321 tmp.tm_yday = yday; 322 tmp.tm_isdst = isdst; 323 return tmp; 324 } 325} // namespace __gnu_test 326