1 /*
2 This file is part of Deadbeef Player source code
3 http://deadbeef.sourceforge.net
4
5 pthread wrapper
6
7 Copyright (C) 2009-2013 Alexey Yakovenko
8
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any damages
11 arising from the use of this software.
12
13 Permission is granted to anyone to use this software for any purpose,
14 including commercial applications, and to alter it and redistribute it
15 freely, subject to the following restrictions:
16
17 1. The origin of this software must not be misrepresented; you must not
18 claim that you wrote the original software. If you use this software
19 in a product, an acknowledgment in the product documentation would be
20 appreciated but is not required.
21 2. Altered source versions must be plainly marked as such, and must not be
22 misrepresented as being the original software.
23 3. This notice may not be removed or altered from any source distribution.
24
25 Alexey Yakovenko waker@users.sourceforge.net
26 */
27 #include <stdio.h>
28 #include <pthread.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <string.h>
32 #include "threading.h"
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 intptr_t
thread_start(void (* fn)(void * ctx),void * ctx)38 thread_start (void (*fn)(void *ctx), void *ctx) {
39 pthread_t tid;
40 pthread_attr_t attr;
41 int s = pthread_attr_init (&attr);
42 if (s != 0) {
43 fprintf (stderr, "pthread_attr_init failed: %s\n", strerror (s));
44 return 0;
45 }
46
47 s = pthread_create (&tid, &attr, (void *(*)(void *))fn, (void*)ctx);
48 if (s != 0) {
49 fprintf (stderr, "pthread_create failed: %s\n", strerror (s));
50 return 0;
51 }
52 s = pthread_attr_destroy (&attr);
53 if (s != 0) {
54 fprintf (stderr, "pthread_attr_destroy failed: %s\n", strerror (s));
55 return 0;
56 }
57 return (uintptr_t)tid;
58 }
59
60 intptr_t
thread_start_low_priority(void (* fn)(void * ctx),void * ctx)61 thread_start_low_priority (void (*fn)(void *ctx), void *ctx) {
62 #if defined(__linux__) && !defined(ANDROID)
63 pthread_t tid;
64 pthread_attr_t attr;
65 int s = pthread_attr_init (&attr);
66 if (s != 0) {
67 fprintf (stderr, "pthread_attr_init failed: %s\n", strerror (s));
68 return 0;
69 }
70 #if !STATICLINK && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4
71 int policy;
72 s = pthread_attr_getschedpolicy (&attr, &policy);
73 if (s != 0) {
74 fprintf (stderr, "pthread_attr_getschedpolicy failed: %s\n", strerror (s));
75 return 0;
76 }
77 int minprio = sched_get_priority_min (policy);
78 #endif
79
80 s = pthread_create (&tid, &attr, (void *(*)(void *))fn, (void*)ctx);
81 if (s != 0) {
82 fprintf (stderr, "pthread_create failed: %s\n", strerror (s));
83 return 0;
84 }
85 #if !STATICLINK && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4
86 s = pthread_setschedprio (tid, minprio);
87 if (s != 0) {
88 fprintf (stderr, "pthread_setschedprio failed: %s\n", strerror (s));
89 pthread_cancel (tid);
90 return 0;
91 }
92 #endif
93
94 s = pthread_attr_destroy (&attr);
95 if (s != 0) {
96 fprintf (stderr, "pthread_attr_destroy failed: %s\n", strerror (s));
97 pthread_cancel (tid);
98 return 0;
99 }
100 return tid;
101 #else
102 return thread_start (fn, ctx);
103 #endif
104 }
105
106 int
thread_join(intptr_t tid)107 thread_join (intptr_t tid) {
108 void *retval;
109 int s = pthread_join ((pthread_t)tid, &retval);
110 if (s) {
111 fprintf (stderr, "pthread_join failed: %s\n", strerror (s));
112 return -1;
113 }
114 return 0;
115 }
116
117 int
thread_detach(intptr_t tid)118 thread_detach (intptr_t tid) {
119 int s = pthread_detach ((pthread_t)tid);
120 if (s) {
121 fprintf (stderr, "pthread_detach failed: %s\n", strerror (s));
122 return -1;
123 }
124 return 0;
125 }
126
127 void
thread_exit(void * retval)128 thread_exit (void *retval) {
129 pthread_exit (retval);
130 }
131
132 uintptr_t
mutex_create_nonrecursive(void)133 mutex_create_nonrecursive (void) {
134 pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
135 pthread_mutexattr_t attr = {0};
136 pthread_mutexattr_init (&attr);
137 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL);
138 int err = pthread_mutex_init (mtx, &attr);
139 if (err != 0) {
140 fprintf (stderr, "pthread_mutex_init failed: %s\n", strerror (err));
141 return 0;
142 }
143 pthread_mutexattr_destroy (&attr);
144 return (uintptr_t)mtx;
145 }
146
147 uintptr_t
mutex_create(void)148 mutex_create (void) {
149 pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
150 pthread_mutexattr_t attr = {0};
151 pthread_mutexattr_init (&attr);
152 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
153 int err = pthread_mutex_init (mtx, &attr);
154 if (err != 0) {
155 fprintf (stderr, "pthread_mutex_init failed: %s\n", strerror (err));
156 return 0;
157 }
158 pthread_mutexattr_destroy (&attr);
159 return (uintptr_t)mtx;
160 }
161
162 void
mutex_free(uintptr_t _mtx)163 mutex_free (uintptr_t _mtx) {
164 pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
165 pthread_mutex_destroy (mtx);
166 free (mtx);
167 }
168
169 int
mutex_lock(uintptr_t _mtx)170 mutex_lock (uintptr_t _mtx) {
171 pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
172 int err = pthread_mutex_lock (mtx);
173 if (err != 0) {
174 fprintf (stderr, "pthread_mutex_lock failed: %s\n", strerror (err));
175 }
176 return err;
177 }
178
179 int
mutex_unlock(uintptr_t _mtx)180 mutex_unlock (uintptr_t _mtx) {
181 pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
182 int err = pthread_mutex_unlock (mtx);
183 if (err != 0) {
184 fprintf (stderr, "pthread_mutex_unlock failed: %s\n", strerror (err));
185 }
186 return err;
187 }
188
189 uintptr_t
cond_create(void)190 cond_create (void) {
191 pthread_cond_t *cond = malloc (sizeof (pthread_cond_t));
192 int err = pthread_cond_init (cond, NULL);
193 if (err != 0) {
194 fprintf (stderr, "pthread_cond_init failed: %s\n", strerror (err));
195 return 0;
196 }
197 return (uintptr_t)cond;
198 }
199
200 void
cond_free(uintptr_t c)201 cond_free (uintptr_t c) {
202 if (c) {
203 pthread_cond_t *cond = (pthread_cond_t *)c;
204 pthread_cond_destroy (cond);
205 free (cond);
206 }
207 }
208
209 int
cond_wait(uintptr_t c,uintptr_t m)210 cond_wait (uintptr_t c, uintptr_t m) {
211 pthread_cond_t *cond = (pthread_cond_t *)c;
212 pthread_mutex_t *mutex = (pthread_mutex_t *)m;
213 int err = mutex_lock (m);
214 if (err != 0) {
215 return err;
216 }
217 err = pthread_cond_wait (cond, mutex);
218 if (err != 0) {
219 fprintf (stderr, "pthread_cond_wait failed: %s\n", strerror (err));
220 }
221 return err;
222 }
223
224 int
cond_signal(uintptr_t c)225 cond_signal (uintptr_t c) {
226 pthread_cond_t *cond = (pthread_cond_t *)c;
227 int err = pthread_cond_signal (cond);
228 if (err != 0) {
229 fprintf (stderr, "pthread_cond_signal failed: %s\n", strerror (err));
230 }
231 return err;
232 }
233
234 int
cond_broadcast(uintptr_t c)235 cond_broadcast (uintptr_t c) {
236 pthread_cond_t *cond = (pthread_cond_t *)c;
237 int err = pthread_cond_broadcast (cond);
238 if (err != 0) {
239 fprintf (stderr, "pthread_cond_broadcast failed: %s\n", strerror (err));
240 }
241 return err;
242 }
243