2-1.c revision 520f02a0cb9200cca5b837b78079be7e4727004b
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 published by
7 *   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 *
20 *   Date:  20/05/2011
21 */
22
23#include "affinity.h"
24
25#include <stdio.h>
26#include <string.h>
27#include <pthread.h>
28#include <unistd.h>
29#include <stdlib.h>
30#include <errno.h>
31#include <posixtest.h>
32
33/* Priorities for the threads, must be unique, non-zero, and ordered */
34#define PRIO_HIGH	20
35#define PRIO_MED	10
36#define PRIO_LOW	5
37#define PRIO_MAIN	1
38
39static int priorities[3];
40
41static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
42static pthread_mutex_t c_mutex = PTHREAD_MUTEX_INITIALIZER;
43static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
44
45static int thread_started;
46
47#define FAIL_AND_EXIT(f, rc) { \
48	printf("Failed: function: %s status: %s(%u)\n", f, strerror(rc), rc); \
49	exit(PTS_UNRESOLVED); \
50}
51
52static void *thread_func(void *data)
53{
54	struct sched_param sp;
55	int policy;
56	int rc;
57
58	rc = pthread_getschedparam(pthread_self(), &policy, &sp);
59	if (rc)
60		FAIL_AND_EXIT("pthread_getschedparam()", rc);
61
62	rc = pthread_mutex_lock(&c_mutex);
63	if (rc)
64		FAIL_AND_EXIT("pthread_mutex_lock()", rc);
65	thread_started = 1;
66	rc = pthread_cond_signal(&cond);
67	if (rc)
68		FAIL_AND_EXIT("pthread_cond_signal()", rc);
69	rc = pthread_mutex_unlock(&c_mutex);
70	if (rc)
71		FAIL_AND_EXIT("pthread_mutex_unlock()", rc);
72
73	rc = pthread_mutex_lock(&mutex);
74	if (rc)
75		FAIL_AND_EXIT("pthread_mutex_lock()", rc);
76
77	/* Stuff the priority in execution order */
78	if (!priorities[0])
79		priorities[0] = sp.sched_priority;
80	else if (!priorities[1])
81		priorities[1] = sp.sched_priority;
82	else
83		priorities[2] = sp.sched_priority;
84
85	rc = pthread_mutex_unlock(&mutex);
86	if (rc)
87		FAIL_AND_EXIT("pthread_mutex_unlock()", rc);
88
89	return (void *)(long)rc;
90}
91
92static int create_thread(int prio, pthread_t * tid)
93{
94	int rc;
95	struct sched_param sp;
96	pthread_attr_t attr;
97
98	rc = pthread_attr_init(&attr);
99	if (rc != 0)
100		FAIL_AND_EXIT("pthread_attr_init()", rc);
101
102	rc = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
103	if (rc != 0)
104		FAIL_AND_EXIT("pthread_attr_setschedpolicy()", rc);
105
106	rc = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
107	if (rc != 0)
108		FAIL_AND_EXIT("pthread_attr_setinheritsched()", rc);
109
110	sp.sched_priority = prio;
111	rc = pthread_attr_setschedparam(&attr, &sp);
112	if (rc != 0)
113		FAIL_AND_EXIT("pthread_attr_setschedparam()", rc);
114
115	thread_started = 0;
116
117	rc = pthread_create(tid, &attr, thread_func, NULL);
118	if (rc)
119		FAIL_AND_EXIT("pthread_create()", rc);
120
121	rc = pthread_mutex_lock(&c_mutex);
122	if (rc)
123		FAIL_AND_EXIT("pthread_mutex_lock()", rc);
124	while (!thread_started) {
125		rc = pthread_cond_wait(&cond, &c_mutex);
126		if (rc)
127			FAIL_AND_EXIT("pthread_cond_wait()", rc);
128	}
129	rc = pthread_mutex_unlock(&c_mutex);
130	if (rc)
131		FAIL_AND_EXIT("pthread_mutex_unlock()", rc);
132
133	pthread_attr_destroy(&attr);
134
135	return 0;
136}
137
138int main(void)
139{
140	int status;
141	int rc;
142	void *r1;
143	void *r2;
144	void *r3;
145	pthread_t t1;
146	pthread_t t2;
147	pthread_t t3;
148	struct sched_param sp;
149
150	status = PTS_UNRESOLVED;
151
152
153	rc = set_affinity(0);
154	if (rc)
155		FAIL_AND_EXIT("set_affinity", errno);
156
157	sp.sched_priority = PRIO_MAIN;
158	rc = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp);
159	if (rc)
160		FAIL_AND_EXIT("pthread_setschedparam()", rc);
161
162	rc = pthread_mutex_lock(&mutex);
163	if (rc)
164		FAIL_AND_EXIT("pthread_mutex_lock()", rc);
165
166	rc = create_thread(PRIO_LOW, &t3);
167	if (rc)
168		FAIL_AND_EXIT("create_thread LOW", rc);
169
170	rc = create_thread(PRIO_MED, &t2);
171	if (rc)
172		FAIL_AND_EXIT("create_thread MED", rc);
173
174	rc = create_thread(PRIO_HIGH, &t1);
175	if (rc)
176		FAIL_AND_EXIT("create_thread HIGH", rc);
177
178	rc = pthread_mutex_unlock(&mutex);
179	if (rc)
180		FAIL_AND_EXIT("pthread_mutex_unlock()", rc);
181
182	rc = pthread_join(t1, &r1);
183	if (rc)
184		FAIL_AND_EXIT("pthread_join(t1)", rc);
185
186	rc = pthread_join(t2, &r2);
187	if (rc)
188		FAIL_AND_EXIT("pthread_join(t2)", rc);
189
190	rc = pthread_join(t3, &r3);
191	if (rc)
192		FAIL_AND_EXIT("pthread_join(t3)", rc);
193
194	/* priorities must be high to low */
195	status = PTS_FAIL;
196	if (priorities[0] != PRIO_HIGH)
197		printf("Failed: first is prio: %u, should be: %u\n",
198		       priorities[0], PRIO_HIGH);
199	else if (priorities[1] != PRIO_MED)
200		printf("Failed: second is prio: %u, should be: %u\n",
201		       priorities[1], PRIO_MED);
202	else if (priorities[2] != PRIO_LOW)
203		printf("Failed: third is prio: %u, should be: %u\n",
204		       priorities[2], PRIO_LOW);
205	else
206		status = PTS_PASS;
207
208	if (status == PTS_PASS)
209		printf("Test PASSED\n");
210
211	return status;
212}
213