GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/librthread/rthread_attr.c Lines: 47 60 78.3 %
Date: 2017-11-07 Branches: 14 24 58.3 %

Line Branch Exec Source
1
/*	$OpenBSD: rthread_attr.c,v 1.23 2017/09/05 02:40:54 guenther Exp $ */
2
/*
3
 * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
4
 * All Rights Reserved.
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
/*
19
 * generic attribute support
20
 */
21
22
#include <stdint.h>
23
#include <stdlib.h>
24
#include <unistd.h>
25
#include <errno.h>
26
27
#include <pthread.h>
28
#include <pthread_np.h>
29
30
#include "rthread.h"
31
32
/*
33
 * Note: stack_size + guard_size == total stack used
34
 *
35
 * pthread_attr_init MUST be called before any other attribute function
36
 * for proper operation.
37
 *
38
 * Every call to pthread_attr_init MUST be matched with a call to
39
 * pthread_attr_destroy to avoid leaking memory.   This is an implementation
40
 * requirement, not a POSIX requirement.
41
 */
42
43
int
44
pthread_attr_init(pthread_attr_t *attrp)
45
{
46
	pthread_attr_t attr;
47
48
	/* make sure _rthread_attr_default has been initialized */
49
50
	if (!_threads_ready)
50
21
		_rthread_init();
51
52
25
	attr = calloc(1, sizeof(*attr));
53
25
	if (!attr)
54
		return (errno);
55
25
	*attr = _rthread_attr_default;
56
25
	*attrp = attr;
57
58
25
	return (0);
59
25
}
60
61
int
62
pthread_attr_destroy(pthread_attr_t *attrp)
63
{
64
8
	free(*attrp);
65
4
	*attrp = NULL;
66
67
4
	return (0);
68
}
69
70
int
71
pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize)
72
{
73
8
	*guardsize = (*attrp)->guard_size;
74
75
4
	return (0);
76
}
77
78
int
79
pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize)
80
{
81
	(*attrp)->guard_size = guardsize;
82
83
	return (0);
84
}
85
86
int
87
pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate)
88
{
89
	*detachstate = (*attrp)->detach_state;
90
91
	return (0);
92
}
93
94
int
95
pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate)
96
{
97
	int error;
98
99
39
	error = (detachstate == PTHREAD_CREATE_DETACHED ||
100
13
		  detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL;
101
13
	if (error == 0)
102
13
		(*attrp)->detach_state = detachstate;
103
104
13
	return (error);
105
}
106
107
int
108
pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr,
109
    size_t *stacksize)
110
{
111
16
	*stackaddr = (*attrp)->stack_addr;
112
8
	*stacksize = (*attrp)->stack_size;
113
114
8
	return (0);
115
}
116
117
int
118
pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize)
119
{
120
	int error;
121
122
	/*
123
	 * XXX Add an alignment test, on stackaddr for stack-grows-up
124
	 * archs or on stackaddr+stacksize for stack-grows-down archs
125
	 */
126
8
	if (stacksize < PTHREAD_STACK_MIN)
127
		return (EINVAL);
128
4
	if ((error = pthread_attr_setstackaddr(attrp, stackaddr)))
129
		return (error);
130
4
	(*attrp)->stack_size = stacksize;
131
132
4
	return (0);
133
4
}
134
135
int
136
pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize)
137
{
138
40
	*stacksize = (*attrp)->stack_size;
139
140
20
	return (0);
141
}
142
143
int
144
pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize)
145
{
146
16
	if (!_threads_ready)		/* for ROUND_TO_PAGE */
147
		_rthread_init();
148
149

12
	if (stacksize < PTHREAD_STACK_MIN ||
150
4
	    stacksize > ROUND_TO_PAGE(stacksize))
151
4
		return (EINVAL);
152
4
	(*attrp)->stack_size = stacksize;
153
154
4
	return (0);
155
8
}
156
157
int
158
pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr)
159
{
160
16
	*stackaddr = (*attrp)->stack_addr;
161
162
8
	return (0);
163
}
164
165
int
166
pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr)
167
{
168
8
	if (!_threads_ready)
169
		_rthread_init();		/* for _thread_pagesize */
170
171

8
	if (stackaddr == NULL || (uintptr_t)stackaddr & (_thread_pagesize - 1))
172
		return (EINVAL);
173
4
	(*attrp)->stack_addr = stackaddr;
174
175
4
	return (0);
176
4
}
177
DEF_NONSTD(pthread_attr_setstackaddr);
178
179
int
180
pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope)
181
{
182
	*contentionscope = (*attrp)->contention_scope;
183
184
	return (0);
185
}
186
187
int
188
pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope)
189
{
190
12
	if (contentionscope != PTHREAD_SCOPE_SYSTEM &&
191
4
	    contentionscope != PTHREAD_SCOPE_PROCESS)
192
		return (EINVAL);
193
4
	(*attrp)->contention_scope = contentionscope;
194
195
4
	return (0);
196
4
}
197