Home | History | Annotate | Download | only in sched_yield
      1 /*
      2  *
      3  *   Copyright (c) Novell Inc. 2011
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms in version 2 of the GNU General Public License as
      7  *   published by the Free Software Foundation.
      8  *
      9  *   This program is distributed in the hope that it will be useful,
     10  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     12  *   the GNU General Public License for more details.
     13  *
     14  *   You should have received a copy of the GNU General Public License
     15  *   along with this program;  if not, write to the Free Software
     16  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     17  *
     18  *   Author:  Peter W. Morreale <pmorreale AT novell DOT com>
     19  *   Date:    11/08/2011
     20  */
     21 
     22 #include "affinity.h"
     23 
     24 #include <stdio.h>
     25 #include <sys/wait.h>
     26 #include <errno.h>
     27 #include <string.h>
     28 #include <signal.h>
     29 #include <pthread.h>
     30 #include <sched.h>
     31 #include <signal.h>
     32 #include <stdlib.h>
     33 #include <unistd.h>
     34 #include "posixtest.h"
     35 
     36 
     37 #define ERR_LOG(l, rc)   printf("Failed: %s rc: %d errno: %s\n", \
     38 					l, rc, strerror(errno))
     39 
     40 static int child_busy(int fd)
     41 {
     42 	int rc;
     43 
     44 	/* suicide if sched_yield fails */
     45 	alarm(4);
     46 
     47 	/* Tell the parent we're ready */
     48 	write(fd, "go", 2);
     49 
     50 	for (;;) {
     51 		rc = sched_yield();
     52 		if (rc) {
     53 			ERR_LOG("child: sched_yield", rc);
     54 			exit(1);
     55 		}
     56 	}
     57 
     58 	/* should not get here */
     59 	exit(2);
     60 }
     61 
     62 int main(void)
     63 {
     64 	int pid;
     65 	int rc;
     66 	int pfd[2];
     67 	int status = PTS_UNRESOLVED;
     68 	int s;
     69 	struct sched_param sp;
     70 	char buf[8];
     71 
     72 	/* Set up a pipe, for synching.  */
     73 	rc = pipe(pfd);
     74 	if (rc) {
     75 		ERR_LOG("pipe", rc);
     76 		return status;
     77 	}
     78 
     79 	/* get in FIFO */
     80 	sp.sched_priority = sched_get_priority_min(SCHED_FIFO);
     81 	rc = sched_setscheduler(getpid(), SCHED_FIFO, &sp);
     82 	if (rc) {
     83 		ERR_LOG("sched_setscheduler", rc);
     84 		return status;
     85 	}
     86 
     87 	/* Must only use a single CPU */
     88 	rc = set_affinity_single();
     89 	if (rc) {
     90 		ERR_LOG("set_affinity_single", rc);
     91 		return status;
     92 	}
     93 
     94 	pid = fork();
     95 	if (pid == 0)
     96 		child_busy(pfd[1]);
     97 
     98 	if (pid < 0) {
     99 		ERR_LOG("fork", rc);
    100 		return status;
    101 	}
    102 
    103 	/* wait for child */
    104 	rc = read(pfd[0], buf, sizeof(buf));
    105 	if (rc != 2) {
    106 		kill(pid, SIGTERM);
    107 		waitpid(pid, NULL, 0);
    108 		ERR_LOG("read", rc);
    109 		return status;
    110 	}
    111 
    112 	/* Can only get here if sched_yield works. */
    113 	kill(pid, SIGTERM);
    114 	waitpid(pid, &s, 0);
    115 
    116 	status = PTS_PASS;
    117 	if (WIFSIGNALED(s)) {
    118 		s = WTERMSIG(s);
    119 		if (s != SIGTERM) {
    120 			printf("Failed: kill signal: %d, should be: %d\n",
    121 			       s, SIGTERM);
    122 			status = PTS_FAIL;
    123 		}
    124 	} else if (WIFEXITED(s)) {
    125 		printf("Failed: child prematurely exited with: %d\n",
    126 		       WEXITSTATUS(s));
    127 		status = PTS_FAIL;
    128 	}
    129 
    130 	if (status == PTS_PASS)
    131 		printf("Test PASSED\n");
    132 
    133 	return status;
    134 }
    135