1 5184 ek110237 /* 2 5184 ek110237 * CDDL HEADER START 3 5184 ek110237 * 4 5184 ek110237 * The contents of this file are subject to the terms of the 5 5184 ek110237 * Common Development and Distribution License (the "License"). 6 5184 ek110237 * You may not use this file except in compliance with the License. 7 5184 ek110237 * 8 5184 ek110237 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 5184 ek110237 * or http://www.opensolaris.org/os/licensing. 10 5184 ek110237 * See the License for the specific language governing permissions 11 5184 ek110237 * and limitations under the License. 12 5184 ek110237 * 13 5184 ek110237 * When distributing Covered Code, include this CDDL HEADER in each 14 5184 ek110237 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 5184 ek110237 * If applicable, add the following below this CDDL HEADER, with the 16 5184 ek110237 * fields enclosed by brackets "[]" replaced with your own identifying 17 5184 ek110237 * information: Portions Copyright [yyyy] [name of copyright owner] 18 5184 ek110237 * 19 5184 ek110237 * CDDL HEADER END 20 5184 ek110237 */ 21 5184 ek110237 /* 22 8615 Andrew * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 5184 ek110237 * Use is subject to license terms. 24 6613 ek110237 * 25 6613 ek110237 * Portions Copyright 2008 Denis Cheng 26 5184 ek110237 */ 27 5184 ek110237 28 5184 ek110237 #include <signal.h> 29 5184 ek110237 #include <fcntl.h> 30 5184 ek110237 #include <sys/stat.h> 31 5184 ek110237 #include <sys/wait.h> 32 5184 ek110237 33 6613 ek110237 #include "filebench.h" 34 5184 ek110237 #include "procflow.h" 35 5184 ek110237 #include "flowop.h" 36 5184 ek110237 #include "ipc.h" 37 5184 ek110237 38 6084 aw148015 /* pid and procflow pointer for this process */ 39 6084 aw148015 pid_t my_pid; 40 6084 aw148015 procflow_t *my_procflow = NULL; 41 5184 ek110237 42 5184 ek110237 static procflow_t *procflow_define_common(procflow_t **list, char *name, 43 5184 ek110237 procflow_t *inherit, int instance); 44 8762 Andrew static void procflow_sleep(procflow_t *procflow, int wait_cnt); 45 5184 ek110237 46 5184 ek110237 #ifdef USE_PROCESS_MODEL 47 5184 ek110237 48 5184 ek110237 static enum create_n_wait { 49 5184 ek110237 CNW_DONE, 50 5184 ek110237 CNW_ERROR 51 5184 ek110237 } cnw_wait; 52 5184 ek110237 53 5184 ek110237 #endif /* USE_PROCESS_MODEL */ 54 5184 ek110237 55 5184 ek110237 56 5184 ek110237 /* 57 5184 ek110237 * Procflows are filebench entities which manage processes. Each 58 5184 ek110237 * worker procflow spawns a separate filebench process, with attributes 59 5184 ek110237 * inherited from a FLOW_MASTER procflow created during f model language 60 5184 ek110237 * parsing. This section contains routines to define, create, control, 61 5184 ek110237 * and delete procflows. 62 5184 ek110237 * 63 5184 ek110237 * Each process defined in the f model creates a FLOW_MASTER 64 5184 ek110237 * procflow which encapsulates the defined attributes, and threads of 65 5184 ek110237 * the f process, including the number of instances to create. At 66 5184 ek110237 * runtime, a worker procflow instance with an associated filebench 67 5184 ek110237 * process is created, which runs until told to quite by the original 68 5184 ek110237 * filebench process or is specifically deleted. 69 5184 ek110237 */ 70 5184 ek110237 71 5184 ek110237 72 5184 ek110237 /* 73 5184 ek110237 * Prints a summary of the syntax for setting procflow parameters. 74 5184 ek110237 */ 75 5184 ek110237 void 76 5184 ek110237 procflow_usage(void) 77 5184 ek110237 { 78 5184 ek110237 (void) fprintf(stderr, 79 5184 ek110237 "define process name=<name>[,instances=<count>]\n"); 80 5184 ek110237 (void) fprintf(stderr, "{\n"); 81 5184 ek110237 (void) fprintf(stderr, " thread ...\n"); 82 5184 ek110237 (void) fprintf(stderr, " thread ...\n"); 83 5184 ek110237 (void) fprintf(stderr, " thread ...\n"); 84 5184 ek110237 (void) fprintf(stderr, "}\n"); 85 5184 ek110237 (void) fprintf(stderr, "\n"); 86 5184 ek110237 (void) fprintf(stderr, "\n"); 87 5184 ek110237 } 88 5184 ek110237 89 5184 ek110237 /* 90 5184 ek110237 * If filebench has been compiled to support multiple processes 91 5184 ek110237 * (USE_PROCESS_MODEL defined), this routine forks a child 92 5184 ek110237 * process and uses either system() or exec() to start up a new 93 5184 ek110237 * instance of filebench, passing it the procflow name, instance 94 5184 ek110237 * number and shared memory region address. 95 5184 ek110237 * If USE_PROCESS_MODEL is NOT defined, then the routine 96 5184 ek110237 * just creates a child thread which begins executing 97 5184 ek110237 * threadflow_init() for the specified procflow. 98 5184 ek110237 */ 99 5184 ek110237 static int 100 5184 ek110237 procflow_createproc(procflow_t *procflow) 101 5184 ek110237 { 102 5184 ek110237 char instance[128]; 103 5184 ek110237 char shmaddr[128]; 104 5184 ek110237 char procname[128]; 105 5184 ek110237 pid_t pid; 106 5184 ek110237 107 5184 ek110237 #ifdef USE_PROCESS_MODEL 108 5184 ek110237 109 5184 ek110237 (void) snprintf(instance, sizeof (instance), "%d", 110 5184 ek110237 procflow->pf_instance); 111 5184 ek110237 (void) snprintf(procname, sizeof (procname), "%s", procflow->pf_name); 112 5184 ek110237 #if defined(_LP64) || (__WORDSIZE == 64) 113 5184 ek110237 (void) snprintf(shmaddr, sizeof (shmaddr), "%llx", filebench_shm); 114 5184 ek110237 #else 115 5184 ek110237 (void) snprintf(shmaddr, sizeof (shmaddr), "%x", filebench_shm); 116 5184 ek110237 #endif 117 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "creating process %s", 118 5184 ek110237 procflow->pf_name); 119 5184 ek110237 120 5184 ek110237 procflow->pf_running = 0; 121 5184 ek110237 122 5184 ek110237 #ifdef HAVE_FORK1 123 5184 ek110237 if ((pid = fork1()) < 0) { 124 5184 ek110237 filebench_log(LOG_ERROR, 125 5184 ek110237 "procflow_createproc fork failed: %s", 126 5184 ek110237 strerror(errno)); 127 5184 ek110237 return (-1); 128 5184 ek110237 } 129 5184 ek110237 #else 130 5184 ek110237 if ((pid = fork()) < 0) { 131 5184 ek110237 filebench_log(LOG_ERROR, 132 5184 ek110237 "procflow_createproc fork failed: %s", 133 5184 ek110237 strerror(errno)); 134 5184 ek110237 return (-1); 135 5184 ek110237 } 136 5184 ek110237 #endif /* HAVE_FORK1 */ 137 5184 ek110237 138 6084 aw148015 /* if child, start up new copy of filebench */ 139 5184 ek110237 if (pid == 0) { 140 5184 ek110237 #ifdef USE_SYSTEM 141 5184 ek110237 char syscmd[1024]; 142 5184 ek110237 #endif 143 5184 ek110237 144 5184 ek110237 (void) sigignore(SIGINT); 145 5184 ek110237 filebench_log(LOG_DEBUG_SCRIPT, 146 5184 ek110237 "Starting %s-%d", procflow->pf_name, 147 5184 ek110237 procflow->pf_instance); 148 5184 ek110237 /* Child */ 149 5184 ek110237 150 5184 ek110237 #ifdef USE_SYSTEM 151 5184 ek110237 (void) snprintf(syscmd, sizeof (syscmd), "%s -a %s -i %s -s %s", 152 5184 ek110237 execname, 153 5184 ek110237 procname, 154 5184 ek110237 instance, 155 5184 ek110237 shmaddr); 156 5184 ek110237 if (system(syscmd) < 0) { 157 5184 ek110237 filebench_log(LOG_ERROR, 158 5184 ek110237 "procflow exec proc failed: %s", 159 5184 ek110237 strerror(errno)); 160 5184 ek110237 filebench_shutdown(1); 161 5184 ek110237 } 162 5184 ek110237 163 5184 ek110237 #else 164 6613 ek110237 if (execlp(execname, procname, "-a", procname, "-i", 165 5184 ek110237 instance, "-s", shmaddr, "-m", shmpath, NULL) < 0) { 166 5184 ek110237 filebench_log(LOG_ERROR, 167 5184 ek110237 "procflow exec proc failed: %s", 168 5184 ek110237 strerror(errno)); 169 5184 ek110237 filebench_shutdown(1); 170 5184 ek110237 } 171 5184 ek110237 #endif 172 5184 ek110237 exit(1); 173 5184 ek110237 } else { 174 6084 aw148015 /* if parent, save pid and return */ 175 5184 ek110237 procflow->pf_pid = pid; 176 5184 ek110237 } 177 5184 ek110237 #else 178 5184 ek110237 procflow->pf_running = 1; 179 5184 ek110237 if (pthread_create(&procflow->pf_tid, NULL, 180 5184 ek110237 (void *(*)(void*))threadflow_init, procflow) != 0) { 181 5184 ek110237 filebench_log(LOG_ERROR, "proc-thread create failed"); 182 5184 ek110237 procflow->pf_running = 0; 183 5184 ek110237 } 184 5184 ek110237 #endif 185 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "procflow_createproc created pid %d", 186 5184 ek110237 pid); 187 5184 ek110237 188 5184 ek110237 return (0); 189 5184 ek110237 } 190 5184 ek110237 191 5184 ek110237 /* 192 5184 ek110237 * Find a procflow of name "name" and instance "instance" on the 193 6391 aw148015 * master procflow list, filebench_shm->shm_proclist. Locks the list 194 5184 ek110237 * and scans through it searching for a procflow with matching 195 5184 ek110237 * name and instance number. If found returns a pointer to the 196 5184 ek110237 * procflow, otherwise returns NULL. 197 5184 ek110237 */ 198 5184 ek110237 static procflow_t * 199 5184 ek110237 procflow_find(char *name, int instance) 200 5184 ek110237 { 201 6391 aw148015 procflow_t *procflow = filebench_shm->shm_proclist; 202 5184 ek110237 203 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "Find: (%s-%d) proclist = %zx", 204 5184 ek110237 name, instance, procflow); 205 5184 ek110237 206 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 207 5184 ek110237 208 5184 ek110237 while (procflow) { 209 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "Find: (%s-%d) == (%s-%d)", 210 5184 ek110237 name, instance, 211 5184 ek110237 procflow->pf_name, 212 5184 ek110237 procflow->pf_instance); 213 5184 ek110237 if ((strcmp(name, procflow->pf_name) == 0) && 214 5184 ek110237 (instance == procflow->pf_instance)) { 215 5184 ek110237 216 6391 aw148015 (void) ipc_mutex_unlock( 217 6391 aw148015 &filebench_shm->shm_procflow_lock); 218 5184 ek110237 219 5184 ek110237 return (procflow); 220 5184 ek110237 } 221 5184 ek110237 procflow = procflow->pf_next; 222 5184 ek110237 } 223 5184 ek110237 224 6391 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 225 5184 ek110237 226 5184 ek110237 return (NULL); 227 5184 ek110237 } 228 5184 ek110237 229 5184 ek110237 static int 230 5184 ek110237 procflow_create_all_procs(void) 231 5184 ek110237 { 232 6391 aw148015 procflow_t *procflow = filebench_shm->shm_proclist; 233 5184 ek110237 int ret = 0; 234 5184 ek110237 235 5184 ek110237 while (procflow) { 236 6212 aw148015 int i, instances; 237 5184 ek110237 238 6212 aw148015 instances = (int)avd_get_int(procflow->pf_instances); 239 6212 aw148015 filebench_log(LOG_INFO, "Starting %d %s instances", 240 6212 aw148015 instances, procflow->pf_name); 241 5184 ek110237 242 5184 ek110237 /* Create instances of procflow */ 243 6212 aw148015 for (i = 0; (i < instances) && (ret == 0); i++) { 244 5184 ek110237 procflow_t *newproc; 245 5184 ek110237 246 5184 ek110237 /* Create processes */ 247 5184 ek110237 newproc = 248 6391 aw148015 procflow_define_common(&filebench_shm->shm_proclist, 249 5184 ek110237 procflow->pf_name, procflow, i + 1); 250 5184 ek110237 if (newproc == NULL) 251 5184 ek110237 ret = -1; 252 5184 ek110237 else 253 5184 ek110237 ret = procflow_createproc(newproc); 254 5184 ek110237 } 255 5184 ek110237 256 5184 ek110237 if (ret != 0) 257 5184 ek110237 break; 258 5184 ek110237 259 5184 ek110237 procflow = procflow->pf_next; 260 5184 ek110237 } 261 5184 ek110237 262 5184 ek110237 return (ret); 263 5184 ek110237 } 264 5184 ek110237 265 5184 ek110237 #ifdef USE_PROCESS_MODEL 266 5184 ek110237 /* 267 5184 ek110237 * Used to start up threads on a child process, when filebench is 268 5184 ek110237 * compiled to support multiple processes. Uses the name string 269 5184 ek110237 * and instance number passed to the child to find the previously 270 5184 ek110237 * created procflow entity. Then uses nice() to reduce the 271 5184 ek110237 * process' priority by at least 10. A call is then made to 272 5184 ek110237 * threadflow_init() which creates and runs the process' threads 273 5184 ek110237 * and flowops to completion. When threadflow_init() returns, 274 5184 ek110237 * a call to exit() terminates the child process. 275 5184 ek110237 */ 276 5184 ek110237 int 277 5184 ek110237 procflow_exec(char *name, int instance) 278 5184 ek110237 { 279 5184 ek110237 procflow_t *procflow; 280 5184 ek110237 int proc_nice; 281 5184 ek110237 #ifdef HAVE_SETRLIMIT 282 5184 ek110237 struct rlimit rlp; 283 5184 ek110237 #endif 284 6084 aw148015 int ret; 285 5184 ek110237 286 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, 287 5184 ek110237 "procflow_execproc %s-%d", 288 5184 ek110237 name, instance); 289 5184 ek110237 290 5184 ek110237 if ((procflow = procflow_find(name, instance)) == NULL) { 291 5184 ek110237 filebench_log(LOG_ERROR, 292 5184 ek110237 "procflow_exec could not find %s-%d", 293 5184 ek110237 name, instance); 294 5184 ek110237 return (-1); 295 5184 ek110237 } 296 6084 aw148015 297 6084 aw148015 /* set the slave process' procflow pointer */ 298 6084 aw148015 my_procflow = procflow; 299 6084 aw148015 300 6084 aw148015 /* set its pid from value stored by main() */ 301 6084 aw148015 procflow->pf_pid = my_pid; 302 5184 ek110237 303 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, 304 6084 aw148015 "Started up %s pid %d", procflow->pf_name, my_pid); 305 5184 ek110237 306 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, 307 5184 ek110237 "nice = %llx", procflow->pf_nice); 308 5184 ek110237 309 6212 aw148015 proc_nice = avd_get_int(procflow->pf_nice); 310 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "Setting pri of %s-%d to %d", 311 5184 ek110237 name, instance, nice(proc_nice + 10)); 312 5184 ek110237 313 5184 ek110237 procflow->pf_running = 1; 314 5184 ek110237 315 5184 ek110237 #ifdef HAVE_SETRLIMIT 316 5184 ek110237 /* Get resource limits */ 317 5184 ek110237 (void) getrlimit(RLIMIT_NOFILE, &rlp); 318 5184 ek110237 filebench_log(LOG_DEBUG_SCRIPT, "%d file descriptors", rlp.rlim_cur); 319 5184 ek110237 #endif 320 5184 ek110237 321 6084 aw148015 if ((ret = threadflow_init(procflow)) != FILEBENCH_OK) { 322 6084 aw148015 if (ret < 0) { 323 6084 aw148015 filebench_log(LOG_ERROR, 324 6084 aw148015 "Failed to start threads for %s pid %d", 325 6084 aw148015 procflow->pf_name, my_pid); 326 6084 aw148015 } 327 6084 aw148015 } else { 328 6084 aw148015 filebench_log(LOG_DEBUG_IMPL, 329 6084 aw148015 "procflow_createproc exiting..."); 330 5184 ek110237 } 331 6084 aw148015 332 6701 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock); 333 6701 aw148015 filebench_shm->shm_procs_running --; 334 6701 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock); 335 5184 ek110237 procflow->pf_running = 0; 336 5184 ek110237 337 6084 aw148015 return (ret); 338 5184 ek110237 } 339 5184 ek110237 340 5184 ek110237 341 5184 ek110237 /* 342 5184 ek110237 * A special thread from which worker (child) processes are created, and 343 5184 ek110237 * which then waits for worker processes to die. If they die unexpectedly, 344 5184 ek110237 * that is not a simple exit(0), then report an error and terminate the 345 5184 ek110237 * run. 346 5184 ek110237 */ 347 5184 ek110237 /* ARGSUSED */ 348 5184 ek110237 static void * 349 5184 ek110237 procflow_createnwait(void *nothing) 350 5184 ek110237 { 351 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 352 5184 ek110237 353 5184 ek110237 if (procflow_create_all_procs() == 0) 354 5184 ek110237 cnw_wait = CNW_DONE; 355 5184 ek110237 else 356 5184 ek110237 cnw_wait = CNW_ERROR; 357 5184 ek110237 358 7556 Andrew if (pthread_cond_signal(&filebench_shm->shm_procflow_procs_cv) != 0) 359 5184 ek110237 exit(1); 360 5184 ek110237 361 6391 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 362 5184 ek110237 363 5184 ek110237 /* CONSTCOND */ 364 5184 ek110237 while (1) { 365 5184 ek110237 siginfo_t status; 366 5184 ek110237 367 5184 ek110237 /* wait for any child process to exit */ 368 5184 ek110237 if (waitid(P_ALL, 0, &status, WEXITED) != 0) 369 5184 ek110237 pthread_exit(0); 370 5184 ek110237 371 6701 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 372 5184 ek110237 /* if normal shutdown in progress, just quit */ 373 9326 Andrew if (filebench_shm->shm_f_abort) { 374 6701 aw148015 (void) ipc_mutex_unlock( 375 6701 aw148015 &filebench_shm->shm_procflow_lock); 376 5184 ek110237 pthread_exit(0); 377 9326 Andrew } 378 6701 aw148015 379 6701 aw148015 /* if nothing running, exit */ 380 6701 aw148015 if (filebench_shm->shm_procs_running == 0) { 381 6701 aw148015 filebench_shm->shm_f_abort = FILEBENCH_ABORT_RSRC; 382 6701 aw148015 (void) ipc_mutex_unlock( 383 6701 aw148015 &filebench_shm->shm_procflow_lock); 384 6701 aw148015 pthread_exit(0); 385 6701 aw148015 } 386 6701 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 387 5184 ek110237 388 5184 ek110237 if (status.si_code == CLD_EXITED) { 389 5184 ek110237 /* A process called exit(); check returned status */ 390 5184 ek110237 if (status.si_status != 0) { 391 5184 ek110237 filebench_log(LOG_ERROR, 392 5184 ek110237 "Unexpected Process termination; exiting", 393 5184 ek110237 status.si_status); 394 5184 ek110237 filebench_shutdown(1); 395 5184 ek110237 } 396 5184 ek110237 } else { 397 5184 ek110237 /* A process quit because of some fatal error */ 398 5184 ek110237 filebench_log(LOG_ERROR, 399 5184 ek110237 "Unexpected Process termination Code %d, Errno %d", 400 5184 ek110237 status.si_code, status.si_errno); 401 5184 ek110237 filebench_shutdown(1); 402 5184 ek110237 } 403 5184 ek110237 404 5184 ek110237 } 405 5184 ek110237 /* NOTREACHED */ 406 5184 ek110237 return (NULL); 407 5184 ek110237 } 408 8762 Andrew 409 8762 Andrew /* 410 8762 Andrew * Cancel all threads within a processes, as well as the process itself. 411 8762 Andrew * Called by ^c or by sig_kill 412 8762 Andrew */ 413 8762 Andrew /* ARGSUSED */ 414 8762 Andrew static void 415 8762 Andrew procflow_cancel(int arg1) 416 8762 Andrew { 417 8762 Andrew filebench_log(LOG_DEBUG_IMPL, "Process signal handler on pid %", 418 8762 Andrew my_procflow->pf_pid); 419 8762 Andrew 420 8762 Andrew procflow_sleep(my_procflow, SHUTDOWN_WAIT_SECONDS); 421 8762 Andrew 422 8762 Andrew threadflow_delete_all(&my_procflow->pf_threads); 423 8762 Andrew 424 8762 Andrew /* quit the main procflow thread and hence the process */ 425 8762 Andrew exit(0); 426 8762 Andrew } 427 8762 Andrew 428 5184 ek110237 #endif /* USE_PROCESS_MODEL */ 429 5184 ek110237 430 5184 ek110237 /* 431 5184 ek110237 * Iterates through proclist, the master list of procflows, 432 5184 ek110237 * creating the number of instances of each procflow specified 433 5184 ek110237 * by its pf_instance attribute. Returns 0 on success, or -1 434 5184 ek110237 * times the number of procflow instances that were not 435 5184 ek110237 * successfully created. 436 5184 ek110237 */ 437 5184 ek110237 int 438 5184 ek110237 procflow_init(void) 439 5184 ek110237 { 440 6391 aw148015 procflow_t *procflow = filebench_shm->shm_proclist; 441 5184 ek110237 pthread_t tid; 442 5184 ek110237 int ret = 0; 443 5184 ek110237 444 9326 Andrew if (procflow == NULL) { 445 9326 Andrew filebench_log(LOG_ERROR, "Workload has no processes"); 446 9326 Andrew return (FILEBENCH_ERROR); 447 9326 Andrew } 448 9326 Andrew 449 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, 450 6286 aw148015 "procflow_init %s, %llu", 451 6286 aw148015 procflow->pf_name, 452 6286 aw148015 (u_longlong_t)avd_get_int(procflow->pf_instances)); 453 5184 ek110237 454 5184 ek110237 #ifdef USE_PROCESS_MODEL 455 5184 ek110237 if ((pthread_create(&tid, NULL, procflow_createnwait, NULL)) != 0) 456 5184 ek110237 return (ret); 457 5184 ek110237 458 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 459 8762 Andrew 460 8762 Andrew (void) signal(SIGUSR1, procflow_cancel); 461 5184 ek110237 462 7556 Andrew if ((ret = pthread_cond_wait(&filebench_shm->shm_procflow_procs_cv, 463 6391 aw148015 &filebench_shm->shm_procflow_lock)) != 0) 464 5184 ek110237 return (ret); 465 5184 ek110237 466 5184 ek110237 if (cnw_wait == CNW_ERROR) 467 5184 ek110237 ret = -1; 468 5184 ek110237 469 5184 ek110237 #else /* USE_PROCESS_MODEL */ 470 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 471 5184 ek110237 472 5184 ek110237 ret = procflow_create_all_procs(); 473 5184 ek110237 #endif /* USE_PROCESS_MODEL */ 474 5184 ek110237 475 6391 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 476 5184 ek110237 477 5184 ek110237 return (ret); 478 5184 ek110237 } 479 5184 ek110237 480 5184 ek110237 #ifdef USE_PROCESS_MODEL 481 5184 ek110237 /* 482 5184 ek110237 * Waits for child processes to finish and returns their exit 483 5184 ek110237 * status. Used by procflow_delete() when the process model is 484 5184 ek110237 * enabled to wait for a deleted process to exit. 485 5184 ek110237 */ 486 5184 ek110237 static void 487 5184 ek110237 procflow_wait(pid_t pid) 488 5184 ek110237 { 489 5184 ek110237 pid_t wpid; 490 5184 ek110237 int stat; 491 5184 ek110237 492 5184 ek110237 (void) waitpid(pid, &stat, 0); 493 5184 ek110237 while ((wpid = waitpid(getpid() * -1, &stat, WNOHANG)) > 0) 494 6286 aw148015 filebench_log(LOG_DEBUG_IMPL, "Waited for pid %d", (int)wpid); 495 5184 ek110237 } 496 5184 ek110237 #endif 497 5184 ek110237 498 5184 ek110237 /* 499 8762 Andrew * Common routine to sleep for wait_cnt seconds or for pf_running to 500 8762 Andrew * go false. Checks once a second to see if pf_running has gone false. 501 8762 Andrew */ 502 8762 Andrew static void 503 8762 Andrew procflow_sleep(procflow_t *procflow, int wait_cnt) 504 8762 Andrew { 505 8762 Andrew while (procflow->pf_running & wait_cnt) { 506 8769 Andrew (void) sleep(1); 507 8762 Andrew wait_cnt--; 508 8762 Andrew } 509 8762 Andrew } 510 8762 Andrew 511 8762 Andrew /* 512 8762 Andrew * Deletes the designated procflow. Finally it frees the 513 6391 aw148015 * procflow entity. filebench_shm->shm_procflow_lock must be held on entry. 514 5184 ek110237 * 515 5184 ek110237 * If the designated procflow is not found on the list it returns -1 and 516 5184 ek110237 * the procflow is not deleted. Otherwise it returns 0. 517 5184 ek110237 */ 518 5184 ek110237 static int 519 8762 Andrew procflow_cleanup(procflow_t *procflow) 520 5184 ek110237 { 521 5184 ek110237 procflow_t *entry; 522 5184 ek110237 523 5184 ek110237 filebench_log(LOG_DEBUG_SCRIPT, 524 5184 ek110237 "Deleted proc: (%s-%d) pid %d", 525 5184 ek110237 procflow->pf_name, 526 5184 ek110237 procflow->pf_instance, 527 5184 ek110237 procflow->pf_pid); 528 5184 ek110237 529 8762 Andrew procflow->pf_running = 0; 530 5184 ek110237 531 5184 ek110237 /* remove entry from proclist */ 532 6391 aw148015 entry = filebench_shm->shm_proclist; 533 5184 ek110237 534 5184 ek110237 /* unlink procflow entity from proclist */ 535 5184 ek110237 if (entry == procflow) { 536 5184 ek110237 /* at head of list */ 537 6391 aw148015 filebench_shm->shm_proclist = procflow->pf_next; 538 5184 ek110237 } else { 539 5184 ek110237 /* search list for procflow */ 540 5184 ek110237 while (entry && entry->pf_next != procflow) 541 5184 ek110237 entry = entry->pf_next; 542 5184 ek110237 543 5184 ek110237 /* if entity found, unlink it */ 544 5184 ek110237 if (entry == NULL) 545 5184 ek110237 return (-1); 546 5184 ek110237 else 547 5184 ek110237 entry->pf_next = procflow->pf_next; 548 5184 ek110237 } 549 5184 ek110237 550 5184 ek110237 /* free up the procflow entity */ 551 5184 ek110237 ipc_free(FILEBENCH_PROCFLOW, (char *)procflow); 552 5184 ek110237 return (0); 553 5184 ek110237 } 554 5184 ek110237 555 5184 ek110237 556 5184 ek110237 /* 557 5184 ek110237 * Waits till all threadflows are started, or a timeout occurs. 558 5184 ek110237 * Checks through the list of procflows, waiting up to 30 559 5184 ek110237 * seconds for each one to set its pf_running flag to 1. If not 560 5184 ek110237 * set after 30 seconds, continues on to the next procflow 561 5184 ek110237 * anyway after logging the fact. Once pf_running is set 562 5184 ek110237 * to 1 for a given procflow or the timeout is reached, 563 5184 ek110237 * threadflow_allstarted() is called to start the threads. 564 6391 aw148015 * Returns 0 (OK), unless filebench_shm->shm_f_abort is signaled, 565 5184 ek110237 * in which case it returns -1. 566 5184 ek110237 */ 567 5184 ek110237 int 568 5184 ek110237 procflow_allstarted() 569 5184 ek110237 { 570 6391 aw148015 procflow_t *procflow = filebench_shm->shm_proclist; 571 6084 aw148015 int running_procs = 0; 572 5184 ek110237 int ret = 0; 573 5184 ek110237 574 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 575 5184 ek110237 576 5184 ek110237 (void) sleep(1); 577 5184 ek110237 578 5184 ek110237 while (procflow) { 579 5184 ek110237 int waits; 580 5184 ek110237 581 5184 ek110237 if (procflow->pf_instance && 582 5184 ek110237 (procflow->pf_instance == FLOW_MASTER)) { 583 5184 ek110237 procflow = procflow->pf_next; 584 5184 ek110237 continue; 585 5184 ek110237 } 586 5184 ek110237 587 5184 ek110237 waits = 10; 588 5184 ek110237 while (waits && procflow->pf_running == 0) { 589 6391 aw148015 (void) ipc_mutex_unlock( 590 6391 aw148015 &filebench_shm->shm_procflow_lock); 591 6391 aw148015 if (filebench_shm->shm_f_abort == 1) 592 5184 ek110237 return (-1); 593 5184 ek110237 594 5184 ek110237 if (waits < 3) 595 5184 ek110237 filebench_log(LOG_INFO, 596 5184 ek110237 "Waiting for process %s-%d %d", 597 5184 ek110237 procflow->pf_name, 598 5184 ek110237 procflow->pf_instance, 599 5184 ek110237 procflow->pf_pid); 600 5184 ek110237 601 5184 ek110237 (void) sleep(3); 602 5184 ek110237 waits--; 603 6391 aw148015 (void) ipc_mutex_lock( 604 6391 aw148015 &filebench_shm->shm_procflow_lock); 605 5184 ek110237 } 606 5184 ek110237 607 5184 ek110237 if (waits == 0) 608 6084 aw148015 filebench_log(LOG_INFO, 609 6084 aw148015 "Failed to start process %s-%d", 610 5184 ek110237 procflow->pf_name, 611 5184 ek110237 procflow->pf_instance); 612 5184 ek110237 613 6084 aw148015 running_procs++; 614 5184 ek110237 threadflow_allstarted(procflow->pf_pid, procflow->pf_threads); 615 5184 ek110237 616 5184 ek110237 procflow = procflow->pf_next; 617 5184 ek110237 } 618 6701 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock); 619 6701 aw148015 filebench_shm->shm_procs_running = running_procs; 620 6701 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock); 621 5184 ek110237 622 6391 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 623 5184 ek110237 624 5184 ek110237 625 5184 ek110237 return (ret); 626 5184 ek110237 } 627 5184 ek110237 628 5184 ek110237 629 5184 ek110237 /* 630 6084 aw148015 * Sets the f_abort flag and clears the running count to stop 631 5184 ek110237 * all the flowop execution threads from running. Iterates 632 5184 ek110237 * through the procflow list and deletes all procflows except 633 5184 ek110237 * for the FLOW_MASTER procflow. Resets the f_abort flag when 634 5184 ek110237 * finished. 635 6701 aw148015 * 636 5184 ek110237 */ 637 5184 ek110237 void 638 5184 ek110237 procflow_shutdown(void) 639 5184 ek110237 { 640 8762 Andrew procflow_t *procflow, *next_procflow; 641 8762 Andrew int wait_cnt = SHUTDOWN_WAIT_SECONDS; 642 5184 ek110237 643 6701 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock); 644 7556 Andrew if (filebench_shm->shm_procs_running <= 0) { 645 6701 aw148015 /* No processes running, so no need to do anything */ 646 6701 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock); 647 6701 aw148015 return; 648 6701 aw148015 } 649 6701 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock); 650 6701 aw148015 651 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 652 9326 Andrew if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_FINI) { 653 9326 Andrew (void) ipc_mutex_unlock( 654 9326 Andrew &filebench_shm->shm_procflow_lock); 655 9326 Andrew return; 656 9326 Andrew } 657 9326 Andrew 658 8615 Andrew procflow = filebench_shm->shm_proclist; 659 9326 Andrew if (filebench_shm->shm_f_abort == FILEBENCH_OK) 660 9326 Andrew filebench_shm->shm_f_abort = FILEBENCH_ABORT_DONE; 661 5184 ek110237 662 5184 ek110237 while (procflow) { 663 5184 ek110237 if (procflow->pf_instance && 664 5184 ek110237 (procflow->pf_instance == FLOW_MASTER)) { 665 5184 ek110237 procflow = procflow->pf_next; 666 5184 ek110237 continue; 667 5184 ek110237 } 668 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "Deleting process %s-%d %d", 669 5184 ek110237 procflow->pf_name, 670 5184 ek110237 procflow->pf_instance, 671 5184 ek110237 procflow->pf_pid); 672 8762 Andrew 673 8762 Andrew next_procflow = procflow->pf_next; 674 8762 Andrew 675 8762 Andrew /* 676 8762 Andrew * Signalling the process with SIGUSR1 will result in it 677 8762 Andrew * gracefully shutting down and exiting 678 8762 Andrew */ 679 8762 Andrew procflow_sleep(procflow, wait_cnt); 680 8762 Andrew if (procflow->pf_running) { 681 8762 Andrew #ifdef USE_PROCESS_MODEL 682 8762 Andrew pid_t pid; 683 8762 Andrew 684 8762 Andrew pid = procflow->pf_pid; 685 8762 Andrew #ifdef HAVE_SIGSEND 686 8762 Andrew (void) sigsend(P_PID, pid, SIGUSR1); 687 8762 Andrew #else 688 8762 Andrew (void) kill(pid, SIGUSR1); 689 8762 Andrew #endif 690 8762 Andrew procflow_wait(pid); 691 8762 Andrew 692 8762 Andrew #else /* USE_PROCESS_MODEL */ 693 8762 Andrew threadflow_delete_all(&procflow->pf_threads); 694 8762 Andrew #endif /* USE_PROCESS_MODEL */ 695 8762 Andrew } 696 8762 Andrew (void) procflow_cleanup(procflow); 697 8762 Andrew procflow = next_procflow; 698 8762 Andrew if (wait_cnt > 0) 699 6084 aw148015 wait_cnt--; 700 5184 ek110237 } 701 5184 ek110237 702 9326 Andrew filebench_shm->shm_f_abort = FILEBENCH_ABORT_FINI; 703 6391 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 704 7556 Andrew 705 7556 Andrew /* indicate all processes are stopped, even if some are "stuck" */ 706 7556 Andrew (void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock); 707 7556 Andrew filebench_shm->shm_procs_running = 0; 708 7556 Andrew (void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock); 709 5184 ek110237 } 710 5184 ek110237 711 5184 ek110237 712 5184 ek110237 /* 713 5184 ek110237 * Create an in-memory process object. Allocates a procflow 714 5184 ek110237 * entity, initialized from the "inherit" procflow if supplied. 715 5184 ek110237 * The name and instance number are set from the supplied name 716 5184 ek110237 * and instance number and the procflow is added to the head of 717 5184 ek110237 * the master procflow list. Returns pointer to the allocated 718 5184 ek110237 * procflow, or NULL if a name isn't supplied or the procflow 719 5184 ek110237 * entity cannot be allocated. 720 5184 ek110237 * 721 6391 aw148015 * The calling routine must hold the filebench_shm->shm_procflow_lock. 722 5184 ek110237 */ 723 5184 ek110237 static procflow_t * 724 5184 ek110237 procflow_define_common(procflow_t **list, char *name, 725 5184 ek110237 procflow_t *inherit, int instance) 726 5184 ek110237 { 727 5184 ek110237 procflow_t *procflow; 728 5184 ek110237 729 5184 ek110237 if (name == NULL) 730 5184 ek110237 return (NULL); 731 5184 ek110237 732 5184 ek110237 procflow = (procflow_t *)ipc_malloc(FILEBENCH_PROCFLOW); 733 5184 ek110237 734 5184 ek110237 if (procflow == NULL) 735 5184 ek110237 return (NULL); 736 5184 ek110237 737 5184 ek110237 if (inherit) 738 5184 ek110237 (void) memcpy(procflow, inherit, sizeof (procflow_t)); 739 5184 ek110237 else 740 5184 ek110237 (void) memset(procflow, 0, sizeof (procflow_t)); 741 5184 ek110237 742 5184 ek110237 procflow->pf_instance = instance; 743 5184 ek110237 (void) strcpy(procflow->pf_name, name); 744 5184 ek110237 745 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "defining process %s-%d", name, instance); 746 5184 ek110237 747 5184 ek110237 /* Add procflow to list, lock is being held already */ 748 5184 ek110237 if (*list == NULL) { 749 5184 ek110237 *list = procflow; 750 5184 ek110237 procflow->pf_next = NULL; 751 5184 ek110237 } else { 752 5184 ek110237 procflow->pf_next = *list; 753 5184 ek110237 *list = procflow; 754 5184 ek110237 } 755 5184 ek110237 filebench_log(LOG_DEBUG_IMPL, "process %s-%d proclist %zx", 756 6391 aw148015 name, instance, filebench_shm->shm_proclist); 757 5184 ek110237 758 5184 ek110237 return (procflow); 759 5184 ek110237 } 760 5184 ek110237 761 5184 ek110237 /* 762 5184 ek110237 * Create an in-memory process object as described by the syntax. 763 6391 aw148015 * Acquires the filebench_shm->shm_procflow_lock and calls 764 5184 ek110237 * procflow_define_common() to create and initialize a 765 5184 ek110237 * FLOW_MASTER procflow entity from the optional "inherit" 766 5184 ek110237 * procflow with the given name and configured for "instances" 767 5184 ek110237 * number of worker procflows. Currently only called from 768 5184 ek110237 * parser_proc_define(). 769 5184 ek110237 */ 770 5184 ek110237 procflow_t * 771 6212 aw148015 procflow_define(char *name, procflow_t *inherit, avd_t instances) 772 5184 ek110237 { 773 5184 ek110237 procflow_t *procflow; 774 5184 ek110237 775 6391 aw148015 (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); 776 5184 ek110237 777 6391 aw148015 procflow = procflow_define_common(&filebench_shm->shm_proclist, 778 5184 ek110237 name, inherit, FLOW_MASTER); 779 5184 ek110237 procflow->pf_instances = instances; 780 5184 ek110237 781 6391 aw148015 (void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock); 782 5184 ek110237 783 5184 ek110237 return (procflow); 784 5184 ek110237 } 785