1272343Sngie/* $NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Matthias Scheler. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie#include <sys/cdefs.h> 32272343Sngie__RCSID("$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $"); 33272343Sngie 34272343Sngie#include <atf-c.h> 35272343Sngie#include <errno.h> 36272343Sngie#include <pthread.h> 37272343Sngie#include <stdio.h> 38272343Sngie#include <stdlib.h> 39272343Sngie#include <string.h> 40272343Sngie#include <time.h> 41272343Sngie 42272343Sngie#define THREADED_NUM_THREADS 8 43272343Sngie#define THREADED_NUM_VARS 16 44272343Sngie#define THREADED_VAR_NAME "THREADED%zu" 45272343Sngie#define THREADED_RUN_TIME 10 46272343Sngie 47272343Sngiestatic void *thread_getenv_r(void *); 48272343Sngiestatic void *thread_putenv(void *); 49272343Sngiestatic void *thread_setenv(void *); 50272343Sngiestatic void *thread_unsetenv(void *); 51272343Sngie 52272343Sngiestatic void * 53272343Sngiethread_getenv_r(void *arg) 54272343Sngie{ 55272343Sngie time_t endtime; 56272343Sngie 57272343Sngie endtime = *(time_t *)arg; 58272343Sngie do { 59272343Sngie size_t i; 60272343Sngie char name[32], value[128]; 61272343Sngie 62272343Sngie i = lrand48() % THREADED_NUM_VARS; 63272343Sngie (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 64272343Sngie 65272343Sngie if (getenv_r(name, value, sizeof(value)) == -1) { 66272343Sngie ATF_CHECK(errno == ENOENT); 67272343Sngie } 68272343Sngie } while (time(NULL) < endtime); 69272343Sngie 70272343Sngie return NULL; 71272343Sngie} 72272343Sngie 73272343Sngie 74272343Sngiestatic void * 75272343Sngiethread_putenv(void *arg) 76272343Sngie{ 77272343Sngie time_t endtime; 78272343Sngie size_t i; 79272343Sngie static char vars[THREADED_NUM_VARS][128]; 80272343Sngie 81272343Sngie for (i = 0; i < THREADED_NUM_VARS; i++) { 82272343Sngie (void)snprintf(vars[i], sizeof(vars[i]), 83272343Sngie THREADED_VAR_NAME "=putenv %ld", i, lrand48()); 84272343Sngie } 85272343Sngie 86272343Sngie endtime = *(time_t *)arg; 87272343Sngie do { 88272343Sngie char name[128]; 89272343Sngie 90272343Sngie i = lrand48() % THREADED_NUM_VARS; 91272343Sngie (void)strlcpy(name, vars[i], sizeof(name)); 92272343Sngie *strchr(name, '=') = '\0'; 93272343Sngie 94272343Sngie ATF_CHECK(unsetenv(name) != -1); 95272343Sngie ATF_CHECK(putenv(vars[i]) != -1); 96272343Sngie } while (time(NULL) < endtime); 97272343Sngie 98272343Sngie return NULL; 99272343Sngie} 100272343Sngie 101272343Sngiestatic void * 102272343Sngiethread_setenv(void *arg) 103272343Sngie{ 104272343Sngie time_t endtime; 105272343Sngie 106272343Sngie endtime = *(time_t *)arg; 107272343Sngie do { 108272343Sngie size_t i; 109272343Sngie char name[32], value[64]; 110272343Sngie 111272343Sngie i = lrand48() % THREADED_NUM_VARS; 112272343Sngie (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 113272343Sngie (void)snprintf(value, sizeof(value), "setenv %ld", lrand48()); 114272343Sngie 115272343Sngie ATF_CHECK(setenv(name, value, 1) != -1); 116272343Sngie } while (time(NULL) < endtime); 117272343Sngie 118272343Sngie return NULL; 119272343Sngie} 120272343Sngie 121272343Sngiestatic void * 122272343Sngiethread_unsetenv(void *arg) 123272343Sngie{ 124272343Sngie time_t endtime; 125272343Sngie 126272343Sngie endtime = *(time_t *)arg; 127272343Sngie do { 128272343Sngie size_t i; 129272343Sngie char name[32]; 130272343Sngie 131272343Sngie i = lrand48() % THREADED_NUM_VARS; 132272343Sngie (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 133272343Sngie 134272343Sngie ATF_CHECK(unsetenv(name) != -1); 135272343Sngie } while (time(NULL) < endtime); 136272343Sngie 137272343Sngie return NULL; 138272343Sngie} 139272343Sngie 140272343SngieATF_TC(getenv_r_thread); 141272343SngieATF_TC_HEAD(getenv_r_thread, tc) 142272343Sngie{ 143272343Sngie 144272343Sngie atf_tc_set_md_var(tc, "descr", "Test getenv_r(3) with threads"); 145272343Sngie atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 146272343Sngie} 147272343Sngie 148272343SngieATF_TC_BODY(getenv_r_thread, tc) 149272343Sngie{ 150272343Sngie pthread_t threads[THREADED_NUM_THREADS]; 151272343Sngie time_t endtime; 152272343Sngie size_t i, j; 153272343Sngie 154272343Sngie endtime = time(NULL) + THREADED_RUN_TIME; 155272343Sngie 156272343Sngie for (i = j = 0; j < 2; j++) { 157272343Sngie 158272343Sngie ATF_CHECK(pthread_create(&threads[i++], NULL, thread_getenv_r, 159272343Sngie &endtime) == 0); 160272343Sngie } 161272343Sngie 162272343Sngie for (j = 0; j < i; j++) 163272343Sngie ATF_CHECK(pthread_join(threads[j], NULL) == 0); 164272343Sngie} 165272343Sngie 166272343SngieATF_TC(putenv_thread); 167272343SngieATF_TC_HEAD(putenv_thread, tc) 168272343Sngie{ 169272343Sngie atf_tc_set_md_var(tc, "descr", "Test concurrent access by putenv(3)"); 170272343Sngie atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 171272343Sngie} 172272343Sngie 173272343SngieATF_TC_BODY(putenv_thread, tc) 174272343Sngie{ 175272343Sngie pthread_t threads[THREADED_NUM_THREADS]; 176272343Sngie time_t endtime; 177272343Sngie size_t i, j; 178272343Sngie 179272343Sngie endtime = time(NULL) + THREADED_RUN_TIME; 180272343Sngie 181272343Sngie for (i = j = 0; j < 2; j++) { 182272343Sngie 183272343Sngie ATF_CHECK(pthread_create(&threads[i++], NULL, thread_putenv, 184272343Sngie &endtime) == 0); 185272343Sngie } 186272343Sngie 187272343Sngie for (j = 0; j < i; j++) 188272343Sngie ATF_CHECK(pthread_join(threads[j], NULL) == 0); 189272343Sngie} 190272343Sngie 191272343SngieATF_TC(setenv_thread); 192272343SngieATF_TC_HEAD(setenv_thread, tc) 193272343Sngie{ 194272343Sngie atf_tc_set_md_var(tc, "descr", "Test concurrent access by setenv(3)"); 195272343Sngie atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 196272343Sngie} 197272343Sngie 198272343SngieATF_TC_BODY(setenv_thread, tc) 199272343Sngie{ 200272343Sngie pthread_t threads[THREADED_NUM_THREADS]; 201272343Sngie time_t endtime; 202272343Sngie size_t i, j; 203272343Sngie 204272343Sngie endtime = time(NULL) + THREADED_RUN_TIME; 205272343Sngie 206272343Sngie for (i = j = 0; j < 2; j++) { 207272343Sngie 208272343Sngie ATF_CHECK(pthread_create(&threads[i++], NULL, thread_setenv, 209272343Sngie &endtime) == 0); 210272343Sngie } 211272343Sngie 212272343Sngie for (j = 0; j < i; j++) 213272343Sngie ATF_CHECK(pthread_join(threads[j], NULL) == 0); 214272343Sngie} 215272343Sngie 216272343SngieATF_TC(unsetenv_thread); 217272343SngieATF_TC_HEAD(unsetenv_thread, tc) 218272343Sngie{ 219272343Sngie atf_tc_set_md_var(tc, "descr", "Test unsetenv(3) with threads"); 220272343Sngie atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5); 221272343Sngie} 222272343Sngie 223272343SngieATF_TC_BODY(unsetenv_thread, tc) 224272343Sngie{ 225272343Sngie pthread_t threads[THREADED_NUM_THREADS]; 226272343Sngie time_t endtime; 227272343Sngie size_t i, j; 228272343Sngie 229272343Sngie endtime = time(NULL) + THREADED_RUN_TIME; 230272343Sngie 231272343Sngie for (i = j = 0; j < 2; j++) { 232272343Sngie 233272343Sngie ATF_CHECK(pthread_create(&threads[i++], NULL, thread_unsetenv, 234272343Sngie &endtime) == 0); 235272343Sngie } 236272343Sngie 237272343Sngie for (j = 0; j < i; j++) 238272343Sngie ATF_CHECK(pthread_join(threads[j], NULL) == 0); 239272343Sngie} 240272343Sngie 241272343SngieATF_TP_ADD_TCS(tp) 242272343Sngie{ 243272343Sngie 244272343Sngie ATF_TP_ADD_TC(tp, getenv_r_thread); 245272343Sngie ATF_TP_ADD_TC(tp, putenv_thread); 246272343Sngie ATF_TP_ADD_TC(tp, setenv_thread); 247272343Sngie ATF_TP_ADD_TC(tp, unsetenv_thread); 248272343Sngie 249272343Sngie return atf_no_error(); 250272343Sngie} 251