xref: /illumos-gate/usr/src/test/libc-tests/tests/mutex_attr.c (revision f2eefd9cb6ed5c98dcc789738dcd5d661cef8da4)
1*f2eefd9cSRobert Mustacchi /*
2*f2eefd9cSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*f2eefd9cSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*f2eefd9cSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*f2eefd9cSRobert Mustacchi  * 1.0 of the CDDL.
6*f2eefd9cSRobert Mustacchi  *
7*f2eefd9cSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*f2eefd9cSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*f2eefd9cSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*f2eefd9cSRobert Mustacchi  */
11*f2eefd9cSRobert Mustacchi 
12*f2eefd9cSRobert Mustacchi /*
13*f2eefd9cSRobert Mustacchi  * Copyright 2025 Oxide Computer Company
14*f2eefd9cSRobert Mustacchi  */
15*f2eefd9cSRobert Mustacchi 
16*f2eefd9cSRobert Mustacchi /*
17*f2eefd9cSRobert Mustacchi  * Verify we can set and obtain various mutex attributes in the structure. This
18*f2eefd9cSRobert Mustacchi  * is also a regression test for illumos#17334 where we did not get the type
19*f2eefd9cSRobert Mustacchi  * correctly. This does not validate that a mutex can be successfully created
20*f2eefd9cSRobert Mustacchi  * with these attributes.
21*f2eefd9cSRobert Mustacchi  */
22*f2eefd9cSRobert Mustacchi 
23*f2eefd9cSRobert Mustacchi #include <stdlib.h>
24*f2eefd9cSRobert Mustacchi #include <err.h>
25*f2eefd9cSRobert Mustacchi #include <pthread.h>
26*f2eefd9cSRobert Mustacchi #include <sys/sysmacros.h>
27*f2eefd9cSRobert Mustacchi #include <stdbool.h>
28*f2eefd9cSRobert Mustacchi #include <errno.h>
29*f2eefd9cSRobert Mustacchi #include <string.h>
30*f2eefd9cSRobert Mustacchi 
31*f2eefd9cSRobert Mustacchi typedef int (*attr_set_f)(pthread_mutexattr_t *, int);
32*f2eefd9cSRobert Mustacchi typedef int (*attr_get_f)(const pthread_mutexattr_t *, int *);
33*f2eefd9cSRobert Mustacchi 
34*f2eefd9cSRobert Mustacchi static const int check_types[] = { PTHREAD_MUTEX_NORMAL,
35*f2eefd9cSRobert Mustacchi     PTHREAD_MUTEX_ERRORCHECK, PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_DEFAULT };
36*f2eefd9cSRobert Mustacchi static const int check_shared[] = { PTHREAD_PROCESS_SHARED,
37*f2eefd9cSRobert Mustacchi     PTHREAD_PROCESS_PRIVATE };
38*f2eefd9cSRobert Mustacchi static const int check_prioceil[] = { 0, 1, 2 };
39*f2eefd9cSRobert Mustacchi static const int check_protocol[] = { PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT,
40*f2eefd9cSRobert Mustacchi     PTHREAD_PRIO_PROTECT };
41*f2eefd9cSRobert Mustacchi static const int check_robust[] = { PTHREAD_MUTEX_STALLED, PTHREAD_MUTEX_ROBUST,
42*f2eefd9cSRobert Mustacchi     PTHREAD_MUTEX_STALL_NP, PTHREAD_MUTEX_ROBUST_NP };
43*f2eefd9cSRobert Mustacchi 
44*f2eefd9cSRobert Mustacchi static bool
check_field(const char * desc,pthread_mutexattr_t * attr,attr_get_f get_f,attr_set_f set_f,int def,const int * vals,size_t nvals,int err_code)45*f2eefd9cSRobert Mustacchi check_field(const char *desc, pthread_mutexattr_t *attr, attr_get_f get_f,
46*f2eefd9cSRobert Mustacchi     attr_set_f set_f, int def, const int *vals, size_t nvals, int err_code)
47*f2eefd9cSRobert Mustacchi {
48*f2eefd9cSRobert Mustacchi 	bool ret = true;
49*f2eefd9cSRobert Mustacchi 	int r, v;
50*f2eefd9cSRobert Mustacchi 
51*f2eefd9cSRobert Mustacchi 	if ((r = get_f(attr, NULL)) != EINVAL) {
52*f2eefd9cSRobert Mustacchi 		warnx("TEST FAILED: expected getting %s attribute with invalid "
53*f2eefd9cSRobert Mustacchi 		    "attr structure to return EINVAL, found %s", desc,
54*f2eefd9cSRobert Mustacchi 		    strerrorname_np(r));
55*f2eefd9cSRobert Mustacchi 		ret = false;
56*f2eefd9cSRobert Mustacchi 	} else {
57*f2eefd9cSRobert Mustacchi 		(void) printf("TEST PASSED: getting attribute %s with invalid "
58*f2eefd9cSRobert Mustacchi 		    "attributes returned EINVAL\n");
59*f2eefd9cSRobert Mustacchi 	}
60*f2eefd9cSRobert Mustacchi 
61*f2eefd9cSRobert Mustacchi 	if ((r = get_f(attr, &v)) != 0) {
62*f2eefd9cSRobert Mustacchi 		warnc(r, "TEST FAILED: failed to get default value for mutex "
63*f2eefd9cSRobert Mustacchi 		    "%s", desc);
64*f2eefd9cSRobert Mustacchi 		ret = false;
65*f2eefd9cSRobert Mustacchi 	} else if (v != def) {
66*f2eefd9cSRobert Mustacchi 		warnx("TEST FAILED: mutex %s has wrong default value: expected "
67*f2eefd9cSRobert Mustacchi 		    "0x%x, found 0x%x", desc, def, v);
68*f2eefd9cSRobert Mustacchi 		ret = false;
69*f2eefd9cSRobert Mustacchi 	} else {
70*f2eefd9cSRobert Mustacchi 		(void) printf("TEST PASSED: mutex %s default value is the "
71*f2eefd9cSRobert Mustacchi 		    "expected value\n", desc);
72*f2eefd9cSRobert Mustacchi 	}
73*f2eefd9cSRobert Mustacchi 
74*f2eefd9cSRobert Mustacchi 	for (size_t i = 0; i < nvals; i++) {
75*f2eefd9cSRobert Mustacchi 		if ((r = set_f(attr, vals[i])) != 0) {
76*f2eefd9cSRobert Mustacchi 			warnc(r, "TEST FAILED: failed to set mutex %s "
77*f2eefd9cSRobert Mustacchi 			    "attribute to 0x%x", desc, vals[i]);
78*f2eefd9cSRobert Mustacchi 			ret = false;
79*f2eefd9cSRobert Mustacchi 			continue;
80*f2eefd9cSRobert Mustacchi 		}
81*f2eefd9cSRobert Mustacchi 
82*f2eefd9cSRobert Mustacchi 		if ((r = get_f(attr, &v)) != 0) {
83*f2eefd9cSRobert Mustacchi 			warnc(r, "TEST FAILED: failed to get value for mutex "
84*f2eefd9cSRobert Mustacchi 			    "%s", desc);
85*f2eefd9cSRobert Mustacchi 			ret = false;
86*f2eefd9cSRobert Mustacchi 		} else if (v != vals[i]) {
87*f2eefd9cSRobert Mustacchi 			warnx("TEST FAILED: mutex %s has wrong value: expected "
88*f2eefd9cSRobert Mustacchi 			    "0x%x, found 0x%x", desc, vals[i], v);
89*f2eefd9cSRobert Mustacchi 			ret = false;
90*f2eefd9cSRobert Mustacchi 		} else {
91*f2eefd9cSRobert Mustacchi 			(void) printf("TEST PASSED: mutex %s value matches "
92*f2eefd9cSRobert Mustacchi 			    "what we just set (0x%x)\n", desc, vals[i]);
93*f2eefd9cSRobert Mustacchi 		}
94*f2eefd9cSRobert Mustacchi 	}
95*f2eefd9cSRobert Mustacchi 
96*f2eefd9cSRobert Mustacchi 	if ((r = set_f(attr, INT32_MAX)) != err_code) {
97*f2eefd9cSRobert Mustacchi 		warnx("TEST FAILED: expected setting mutex %s to INT32_MAX to "
98*f2eefd9cSRobert Mustacchi 		    "fail with %s, got %s (0x%x)", desc,
99*f2eefd9cSRobert Mustacchi 		    strerrorname_np(err_code), strerrorname_np(r), r);
100*f2eefd9cSRobert Mustacchi 		ret = false;
101*f2eefd9cSRobert Mustacchi 	} else {
102*f2eefd9cSRobert Mustacchi 		(void) printf("TEST PASSED: Setting mutex %s to invalid value "
103*f2eefd9cSRobert Mustacchi 		    "(INT32_MAX) correctly failed with %s\n", desc,
104*f2eefd9cSRobert Mustacchi 		    strerrorname_np(err_code));
105*f2eefd9cSRobert Mustacchi 	}
106*f2eefd9cSRobert Mustacchi 
107*f2eefd9cSRobert Mustacchi 	if ((r = set_f(attr, INT32_MIN)) != err_code) {
108*f2eefd9cSRobert Mustacchi 		warnx("TEST FAILED: expected setting mutex %s to INT32_MIN to "
109*f2eefd9cSRobert Mustacchi 		    "fail with %s, got %s (0x%x)", desc,
110*f2eefd9cSRobert Mustacchi 		    strerrorname_np(err_code), strerrorname_np(r), r);
111*f2eefd9cSRobert Mustacchi 		ret = false;
112*f2eefd9cSRobert Mustacchi 	} else {
113*f2eefd9cSRobert Mustacchi 		(void) printf("TEST PASSED: Setting mutex %s to invalid value "
114*f2eefd9cSRobert Mustacchi 		    "(INT32_MIN) correctly failed with %s\n", desc,
115*f2eefd9cSRobert Mustacchi 		    strerrorname_np(err_code));
116*f2eefd9cSRobert Mustacchi 	}
117*f2eefd9cSRobert Mustacchi 
118*f2eefd9cSRobert Mustacchi 	return (ret);
119*f2eefd9cSRobert Mustacchi }
120*f2eefd9cSRobert Mustacchi 
121*f2eefd9cSRobert Mustacchi int
main(void)122*f2eefd9cSRobert Mustacchi main(void)
123*f2eefd9cSRobert Mustacchi {
124*f2eefd9cSRobert Mustacchi 	int ret = EXIT_SUCCESS, r;
125*f2eefd9cSRobert Mustacchi 	pthread_mutexattr_t attr;
126*f2eefd9cSRobert Mustacchi 
127*f2eefd9cSRobert Mustacchi 	if ((r = pthread_mutexattr_init(&attr)) != 0) {
128*f2eefd9cSRobert Mustacchi 		errc(EXIT_FAILURE, r, "TEST FAILED: failed to initialize "
129*f2eefd9cSRobert Mustacchi 		    "mutex attributes");
130*f2eefd9cSRobert Mustacchi 	}
131*f2eefd9cSRobert Mustacchi 
132*f2eefd9cSRobert Mustacchi 	if (!check_field("type", &attr, pthread_mutexattr_gettype,
133*f2eefd9cSRobert Mustacchi 	    pthread_mutexattr_settype, PTHREAD_MUTEX_DEFAULT, check_types,
134*f2eefd9cSRobert Mustacchi 	    ARRAY_SIZE(check_types), EINVAL)) {
135*f2eefd9cSRobert Mustacchi 		ret = EXIT_FAILURE;
136*f2eefd9cSRobert Mustacchi 	}
137*f2eefd9cSRobert Mustacchi 
138*f2eefd9cSRobert Mustacchi 	if (!check_field("shared", &attr, pthread_mutexattr_getpshared,
139*f2eefd9cSRobert Mustacchi 	    pthread_mutexattr_setpshared, PTHREAD_PROCESS_PRIVATE, check_shared,
140*f2eefd9cSRobert Mustacchi 	    ARRAY_SIZE(check_shared), EINVAL)) {
141*f2eefd9cSRobert Mustacchi 		ret = EXIT_FAILURE;
142*f2eefd9cSRobert Mustacchi 	}
143*f2eefd9cSRobert Mustacchi 
144*f2eefd9cSRobert Mustacchi 	if (!check_field("priority ceiling", &attr,
145*f2eefd9cSRobert Mustacchi 	    pthread_mutexattr_getprioceiling, pthread_mutexattr_setprioceiling,
146*f2eefd9cSRobert Mustacchi 	    0, check_prioceil, ARRAY_SIZE(check_prioceil), EINVAL)) {
147*f2eefd9cSRobert Mustacchi 		ret = EXIT_FAILURE;
148*f2eefd9cSRobert Mustacchi 	}
149*f2eefd9cSRobert Mustacchi 
150*f2eefd9cSRobert Mustacchi 	if (!check_field("protocol", &attr, pthread_mutexattr_getprotocol,
151*f2eefd9cSRobert Mustacchi 	    pthread_mutexattr_setprotocol, PTHREAD_PRIO_NONE, check_protocol,
152*f2eefd9cSRobert Mustacchi 	    ARRAY_SIZE(check_protocol), ENOTSUP)) {
153*f2eefd9cSRobert Mustacchi 		ret = EXIT_FAILURE;
154*f2eefd9cSRobert Mustacchi 	}
155*f2eefd9cSRobert Mustacchi 
156*f2eefd9cSRobert Mustacchi 	if (!check_field("robust", &attr, pthread_mutexattr_getrobust,
157*f2eefd9cSRobert Mustacchi 	    pthread_mutexattr_setrobust, PTHREAD_MUTEX_STALLED, check_robust,
158*f2eefd9cSRobert Mustacchi 	    ARRAY_SIZE(check_robust), EINVAL)) {
159*f2eefd9cSRobert Mustacchi 		ret = EXIT_FAILURE;
160*f2eefd9cSRobert Mustacchi 	}
161*f2eefd9cSRobert Mustacchi 
162*f2eefd9cSRobert Mustacchi 	if ((r = pthread_mutexattr_destroy(&attr)) != 0) {
163*f2eefd9cSRobert Mustacchi 		warnc(r, "TEST FAILED: failed to destroy mutex attributes");
164*f2eefd9cSRobert Mustacchi 		ret = EXIT_FAILURE;
165*f2eefd9cSRobert Mustacchi 	}
166*f2eefd9cSRobert Mustacchi 
167*f2eefd9cSRobert Mustacchi 	if (ret == EXIT_SUCCESS) {
168*f2eefd9cSRobert Mustacchi 		(void) printf("All tests passed successfully\n");
169*f2eefd9cSRobert Mustacchi 	}
170*f2eefd9cSRobert Mustacchi 
171*f2eefd9cSRobert Mustacchi 	return (ret);
172*f2eefd9cSRobert Mustacchi }
173