1/* 2 * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> 3 * 4 * Licensed under the GNU GPLv2 or later. 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /* 20 * Block several processes on a mutex, then wake them up. 21 */ 22 23#include <errno.h> 24#include <sys/types.h> 25#include <sys/wait.h> 26 27#include "test.h" 28#include "safe_macros.h" 29#include "futextest.h" 30#include "futex_common.h" 31 32const char *TCID="futex_wake03"; 33const int TST_TOTAL=11; 34 35static void do_child(void) 36{ 37 futex_wait(futex, *futex, NULL, 0); 38 exit(0); 39} 40 41static void do_wake(int nr_children) 42{ 43 int res, i, cnt; 44 45 res = futex_wake(futex, nr_children, 0); 46 47 if (res != nr_children) { 48 tst_resm(TFAIL, 49 "futex_wake() woken up %i children, expected %i", 50 res, nr_children); 51 return; 52 } 53 54 for (cnt = 0, i = 0; i < 100000; i++) { 55 while (waitpid(-1, &res, WNOHANG) > 0) 56 cnt++; 57 58 if (cnt == nr_children) 59 break; 60 61 usleep(100); 62 } 63 64 if (cnt != nr_children) { 65 tst_resm(TFAIL, "reaped only %i childs, expected %i", 66 cnt, nr_children); 67 } else { 68 tst_resm(TPASS, "futex_wake() woken up %i childs", cnt); 69 } 70} 71 72static void verify_futex_wake(void) 73{ 74 int i, res; 75 pid_t pids[55]; 76 77 for (i = 0; i < (int)ARRAY_SIZE(pids); i++) { 78 pids[i] = tst_fork(); 79 80 switch (pids[i]) { 81 case -1: 82 tst_brkm(TBROK | TERRNO, NULL, "fork()"); 83 case 0: 84 do_child(); 85 default: 86 break; 87 } 88 } 89 90 for (i = 0; i < (int)ARRAY_SIZE(pids); i++) 91 tst_process_state_wait2(pids[i], 'S'); 92 93 for (i = 1; i <= 10; i++) 94 do_wake(i); 95 96 res = futex_wake(futex, 1, 0); 97 98 if (res) { 99 tst_resm(TFAIL, "futex_wake() woken up %u, none were waiting", 100 res); 101 } else { 102 tst_resm(TPASS, "futex_wake() woken up 0 children"); 103 } 104} 105 106int main(int argc, char *argv[]) 107{ 108 int lc; 109 110 tst_parse_opts(argc, argv, NULL, NULL); 111 112 setup(); 113 114 for (lc = 0; TEST_LOOPING(lc); lc++) 115 verify_futex_wake(); 116 117 tst_exit(); 118} 119