1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 
5 #include <errno.h>
6 #include <string.h>
7 #include <pthread.h>
8 #include <sched.h>
9 
10 #include "internal/pthread.h"
11 
pthread_attr_init(pthread_attr_t * attr)12 int pthread_attr_init(pthread_attr_t *attr)
13 {
14     if (attr == NULL) {
15         return EINVAL;
16     }
17 
18     memset(attr, 0, sizeof(pthread_attr_t));
19     attr->stacksize                 = PTHREAD_DEFAULT_STACK_SIZE;
20     attr->sched_priority            = PTHREAD_DEFAULT_PRIORITY;
21     attr->sched_slice               = PTHREAD_DEFAULT_SLICE;
22     attr->detachstate               = PTHREAD_CREATE_JOINABLE;
23     attr->contentionscope           = PTHREAD_SCOPE_SYSTEM;
24     attr->inheritsched              = PTHREAD_EXPLICIT_SCHED;
25     attr->guardsize                 = PTHREAD_DEFAULT_GUARD_SIZE;
26     attr->stackaddr                 = NULL;
27     attr->flag                      = PTHREAD_DYN_INIT;
28 
29     return 0;
30 }
31 
pthread_attr_destroy(pthread_attr_t * attr)32 int pthread_attr_destroy(pthread_attr_t *attr)
33 {
34     if (attr == NULL) {
35         return EINVAL;
36     }
37 
38     memset(attr, 0, sizeof(pthread_attr_t));
39 
40     return 0;
41 }
42 
pthread_attr_setdetachstate(pthread_attr_t * attr,int detachstate)43 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
44 {
45     if ((attr == NULL) || ((detachstate != PTHREAD_CREATE_DETACHED) &&
46                             (detachstate != PTHREAD_CREATE_JOINABLE))) {
47         return EINVAL;
48     }
49 
50     attr->detachstate = detachstate;
51 
52     return 0;
53 }
54 
pthread_attr_getdetachstate(const pthread_attr_t * attr,int * detachstate)55 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
56 {
57     if ((attr == NULL) || (detachstate == NULL)) {
58         return EINVAL;
59     }
60 
61     *detachstate = attr->detachstate;
62 
63     return 0;
64 }
65 
pthread_attr_setschedpolicy(pthread_attr_t * attr,int policy)66 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
67 {
68     if ((attr == NULL) || ((policy < SCHED_OTHER) || (policy > SCHED_RR))) {
69         return EINVAL;
70     }
71 
72     attr->schedpolicy = policy;
73 
74     return 0;
75 }
76 
pthread_attr_getschedpolicy(const pthread_attr_t * attr,int * policy)77 int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
78 {
79     if ((attr == NULL) || (policy == NULL)) {
80         return EINVAL;
81     }
82 
83     *policy = attr->schedpolicy;
84 
85     return 0;
86 }
87 
pthread_attr_setschedparam(pthread_attr_t * attr,const struct sched_param * param)88 int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
89 {
90     if ((attr == NULL) || (param == NULL)) {
91         return EINVAL;
92     }
93 
94     attr->sched_priority = param->sched_priority;
95     attr->sched_slice = param->slice;
96     return 0;
97 }
98 
pthread_attr_getschedparam(const pthread_attr_t * attr,struct sched_param * param)99 int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
100 {
101     if ((attr == NULL) || (param == NULL)) {
102         return EINVAL;
103     }
104 
105     param->sched_priority = attr->sched_priority;
106     param->slice = attr->sched_slice;
107 
108     return 0;
109 }
110 
pthread_attr_setstacksize(pthread_attr_t * attr,size_t stacksize)111 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
112 {
113     if ((attr == NULL) || (stacksize <= 0)) {
114         return EINVAL;
115     }
116 
117     attr->stacksize = stacksize;
118 
119     return 0;
120 }
121 
pthread_attr_getstacksize(const pthread_attr_t * attr,size_t * stacksize)122 int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
123 {
124     if ((attr == NULL) || (stacksize == NULL)) {
125         return EINVAL;
126     }
127 
128     *stacksize = attr->stacksize;
129 
130     return 0;
131 }
132 
pthread_attr_setstackaddr(pthread_attr_t * attr,void * stackaddr)133 int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
134 {
135     if ((attr == NULL) || (stackaddr == NULL)) {
136         return EINVAL;
137     }
138 
139     attr->stackaddr = stackaddr;
140 
141     return 0;
142 }
143 
pthread_attr_getstackaddr(const pthread_attr_t * attr,void ** stackaddr)144 int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
145 {
146     if ((attr == NULL) || (stackaddr == NULL)) {
147         return EINVAL;
148     }
149 
150     *stackaddr = attr->stackaddr;
151 
152     return 0;
153 }
154 
pthread_attr_setstack(pthread_attr_t * attr,void * stackaddr,size_t stacksize)155 int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize)
156 {
157     if ((attr == NULL) || (stackaddr == NULL) || (stacksize <= 0)) {
158         return EINVAL;
159     }
160 
161     attr->stackaddr = stackaddr;
162     attr->stacksize = stacksize;
163 
164     return 0;
165 }
166 
pthread_attr_getstack(const pthread_attr_t * attr,void ** stackaddr,size_t * stacksize)167 int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, size_t *stacksize)
168 {
169     if ((attr == NULL) || (stackaddr == NULL) || (stacksize == NULL)) {
170         return EINVAL;
171     }
172 
173     *stackaddr = attr->stackaddr;
174     *stacksize = attr->stacksize;
175 
176     return 0;
177 }
178 
pthread_attr_getinheritsched(const pthread_attr_t * restrict attr,int * restrict inheritsched)179 int pthread_attr_getinheritsched(const pthread_attr_t *restrict attr, int *restrict inheritsched)
180 {
181     if ((attr == NULL) || (inheritsched == NULL)) {
182         return EINVAL;
183     }
184 
185     *inheritsched = attr->inheritsched;
186 
187     return 0;
188 }
189 
pthread_attr_setinheritsched(pthread_attr_t * attr,int inheritsched)190 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched)
191 {
192     if ((attr == NULL) || (inheritsched < PTHREAD_INHERIT_SCHED) ||
193                           (inheritsched > PTHREAD_EXPLICIT_SCHED)) {
194         return EINVAL;
195     }
196 
197     attr->inheritsched = inheritsched;
198 
199     return 0;
200 }
201 
pthread_attr_setguardsize(pthread_attr_t * attr,size_t guardsize)202 int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
203 {
204     /* guardsize stack protection is not supported by kernel */
205     return ENOSYS;
206 }
207 
pthread_attr_getguardsize(const pthread_attr_t * attr,size_t * guardsize)208 int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
209 {
210     /* guardsize stack protection is not supported by kernel */
211     return ENOSYS;
212 }
213 
pthread_attr_getscope(const pthread_attr_t * restrict attr,int * restrict contentionscope)214 int pthread_attr_getscope(const pthread_attr_t *restrict attr, int *restrict contentionscope)
215 {
216     if ((attr == NULL) || (contentionscope == NULL)) {
217         return EINVAL;
218     }
219 
220     *contentionscope = attr->contentionscope;
221 
222     return 0;
223 }
224 
pthread_attr_setscope(pthread_attr_t * attr,int contentionscope)225 int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
226 {
227     if ((attr == NULL) ||
228         ((contentionscope != PTHREAD_SCOPE_PROCESS) && (contentionscope != PTHREAD_SCOPE_SYSTEM))) {
229         return EINVAL;
230     }
231 
232     attr->contentionscope = contentionscope;
233 
234     return 0;
235 }
236