netbsd_getenv_thread.c
1 /* $NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matthias Scheler. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $"); 33 34 #include <darwintest.h> 35 36 #include <errno.h> 37 #include <pthread.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <time.h> 42 43 #define THREADED_NUM_THREADS 8 44 #define THREADED_NUM_VARS 16 45 #define THREADED_VAR_NAME "THREADED%zu" 46 #define THREADED_RUN_TIME 10 47 48 static void *thread_putenv(void *); 49 static void *thread_setenv(void *); 50 static void *thread_unsetenv(void *); 51 52 static void * 53 thread_putenv(void *arg) 54 { 55 time_t endtime; 56 size_t i; 57 static char vars[THREADED_NUM_VARS][128]; 58 59 for (i = 0; i < THREADED_NUM_VARS; i++) { 60 (void)snprintf(vars[i], sizeof(vars[i]), 61 THREADED_VAR_NAME "=putenv %ld", i, lrand48()); 62 } 63 64 endtime = *(time_t *)arg; 65 do { 66 char name[128]; 67 68 i = lrand48() % THREADED_NUM_VARS; 69 (void)strlcpy(name, vars[i], sizeof(name)); 70 *strchr(name, '=') = '\0'; 71 72 T_QUIET; T_ASSERT_POSIX_ZERO(unsetenv(name), NULL); 73 T_QUIET; T_ASSERT_POSIX_ZERO(putenv(vars[i]), NULL); 74 } while (time(NULL) < endtime); 75 76 return NULL; 77 } 78 79 static void * 80 thread_setenv(void *arg) 81 { 82 time_t endtime; 83 84 endtime = *(time_t *)arg; 85 do { 86 size_t i; 87 char name[32], value[64]; 88 89 i = lrand48() % THREADED_NUM_VARS; 90 (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 91 (void)snprintf(value, sizeof(value), "setenv %ld", lrand48()); 92 93 T_QUIET; T_ASSERT_POSIX_ZERO(setenv(name, value, 1), NULL); 94 } while (time(NULL) < endtime); 95 96 return NULL; 97 } 98 99 static void * 100 thread_unsetenv(void *arg) 101 { 102 time_t endtime; 103 104 endtime = *(time_t *)arg; 105 do { 106 size_t i; 107 char name[32]; 108 109 i = lrand48() % THREADED_NUM_VARS; 110 (void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i); 111 112 T_QUIET; T_ASSERT_POSIX_ZERO(unsetenv(name), NULL); 113 } while (time(NULL) < endtime); 114 115 return NULL; 116 } 117 118 T_DECL(putenv_thread, "Test concurrent access by putenv(3)") 119 { 120 pthread_t threads[THREADED_NUM_THREADS]; 121 time_t endtime = time(NULL) + THREADED_RUN_TIME; 122 123 for (int i = 0; i < THREADED_NUM_THREADS; i++) { 124 T_QUIET; T_ASSERT_POSIX_ZERO( 125 pthread_create(&threads[i], NULL, thread_putenv, &endtime), 126 NULL); 127 } 128 for (int i = 0; i < THREADED_NUM_THREADS; i++) { 129 T_QUIET; T_ASSERT_POSIX_ZERO(pthread_join(threads[i], NULL), NULL); 130 } 131 T_PASS("putenv_thread() completed successfully"); 132 } 133 134 T_DECL(setenv_thread, "Test concurrent access by setenv(3)") 135 { 136 pthread_t threads[THREADED_NUM_THREADS]; 137 time_t endtime = time(NULL) + THREADED_RUN_TIME; 138 139 for (int i = 0; i < THREADED_NUM_THREADS; i++) { 140 T_QUIET; T_ASSERT_POSIX_ZERO( 141 pthread_create(&threads[i], NULL, thread_setenv, &endtime), 142 NULL); 143 } 144 for (int i = 0; i < THREADED_NUM_THREADS; i++) { 145 T_QUIET; T_ASSERT_POSIX_ZERO(pthread_join(threads[i], NULL), NULL); 146 } 147 T_PASS("setenv_thread() completed successfully"); 148 } 149 150 T_DECL(unsetenv_thread, "Test unsetenv(3) with threads", 151 T_META_ENVVAR("MallocStackLogging=lite")) 152 { 153 pthread_t threads[THREADED_NUM_THREADS]; 154 time_t endtime = time(NULL) + THREADED_RUN_TIME; 155 156 for (int i = 0; i < THREADED_NUM_THREADS; i++) { 157 T_QUIET; T_ASSERT_POSIX_ZERO( 158 pthread_create(&threads[i], NULL, thread_unsetenv, &endtime), 159 NULL); 160 } 161 for (int i = 0; i < THREADED_NUM_THREADS; i++) { 162 T_QUIET; T_ASSERT_POSIX_ZERO(pthread_join(threads[i], NULL), NULL); 163 } 164 T_PASS("unsetenv_thread() completed successfully"); 165 } 166