1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
5 /* This program is free software; you can redistribute it and/or */
6 /* modify it under the terms of the GNU Library General Public License */
7 /* as published by the Free Software Foundation; either version 2 */
8 /* of the License, or (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU Library General Public License for more details. */
21 #include "internals.h"
26 int __pthread_mutex_init(pthread_mutex_t
* mutex
,
27 const pthread_mutexattr_t
* mutex_attr
)
29 __pthread_init_lock(&mutex
->m_lock
);
31 mutex_attr
== NULL
? PTHREAD_MUTEX_FAST_NP
: mutex_attr
->mutexkind
;
33 mutex
->m_owner
= NULL
;
36 weak_alias (__pthread_mutex_init
, pthread_mutex_init
)
38 int __pthread_mutex_destroy(pthread_mutex_t
* mutex
)
40 if (mutex
->m_lock
.status
!= 0) return EBUSY
;
43 weak_alias (__pthread_mutex_destroy
, pthread_mutex_destroy
)
45 int __pthread_mutex_trylock(pthread_mutex_t
* mutex
)
50 switch(mutex
->m_kind
) {
51 case PTHREAD_MUTEX_FAST_NP
:
52 retcode
= __pthread_trylock(&mutex
->m_lock
);
54 case PTHREAD_MUTEX_RECURSIVE_NP
:
56 if (mutex
->m_owner
== self
) {
60 retcode
= __pthread_trylock(&mutex
->m_lock
);
62 mutex
->m_owner
= self
;
66 case PTHREAD_MUTEX_ERRORCHECK_NP
:
67 retcode
= __pthread_trylock(&mutex
->m_lock
);
69 mutex
->m_owner
= thread_self();
76 weak_alias (__pthread_mutex_trylock
, pthread_mutex_trylock
)
78 int __pthread_mutex_lock(pthread_mutex_t
* mutex
)
82 switch(mutex
->m_kind
) {
83 case PTHREAD_MUTEX_FAST_NP
:
84 __pthread_lock(&mutex
->m_lock
);
86 case PTHREAD_MUTEX_RECURSIVE_NP
:
88 if (mutex
->m_owner
== self
) {
92 __pthread_lock(&mutex
->m_lock
);
93 mutex
->m_owner
= self
;
96 case PTHREAD_MUTEX_ERRORCHECK_NP
:
98 if (mutex
->m_owner
== self
) return EDEADLK
;
99 __pthread_lock(&mutex
->m_lock
);
100 mutex
->m_owner
= self
;
106 weak_alias (__pthread_mutex_lock
, pthread_mutex_lock
)
108 int __pthread_mutex_unlock(pthread_mutex_t
* mutex
)
110 switch (mutex
->m_kind
) {
111 case PTHREAD_MUTEX_FAST_NP
:
112 __pthread_unlock(&mutex
->m_lock
);
114 case PTHREAD_MUTEX_RECURSIVE_NP
:
115 if (mutex
->m_count
> 0) {
119 mutex
->m_owner
= NULL
;
120 __pthread_unlock(&mutex
->m_lock
);
122 case PTHREAD_MUTEX_ERRORCHECK_NP
:
123 if (mutex
->m_owner
!= thread_self() || mutex
->m_lock
.status
== 0)
125 mutex
->m_owner
= NULL
;
126 __pthread_unlock(&mutex
->m_lock
);
132 weak_alias (__pthread_mutex_unlock
, pthread_mutex_unlock
)
134 int __pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
136 attr
->mutexkind
= PTHREAD_MUTEX_FAST_NP
;
139 weak_alias (__pthread_mutexattr_init
, pthread_mutexattr_init
)
141 int __pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
145 weak_alias (__pthread_mutexattr_destroy
, pthread_mutexattr_destroy
)
147 int __pthread_mutexattr_settype(pthread_mutexattr_t
*attr
, int kind
)
149 if (kind
!= PTHREAD_MUTEX_FAST_NP
150 && kind
!= PTHREAD_MUTEX_RECURSIVE_NP
151 && kind
!= PTHREAD_MUTEX_ERRORCHECK_NP
)
153 attr
->mutexkind
= kind
;
156 weak_alias (__pthread_mutexattr_settype
, pthread_mutexattr_settype
)
157 strong_alias ( __pthread_mutexattr_settype
, __pthread_mutexattr_setkind_np
)
158 weak_alias (__pthread_mutexattr_setkind_np
, pthread_mutexattr_setkind_np
)
160 int __pthread_mutexattr_gettype(const pthread_mutexattr_t
*attr
, int *kind
)
162 *kind
= attr
->mutexkind
;
165 weak_alias (__pthread_mutexattr_gettype
, pthread_mutexattr_gettype
)
166 strong_alias (__pthread_mutexattr_gettype
, __pthread_mutexattr_getkind_np
)
167 weak_alias (__pthread_mutexattr_getkind_np
, pthread_mutexattr_getkind_np
)
169 /* Once-only execution */
171 static pthread_mutex_t once_masterlock
= PTHREAD_MUTEX_INITIALIZER
;
172 static pthread_cond_t once_finished
= PTHREAD_COND_INITIALIZER
;
174 enum { NEVER
= 0, IN_PROGRESS
= 1, DONE
= 2 };
176 int __pthread_once(pthread_once_t
* once_control
, void (*init_routine
)(void))
178 /* Test without locking first for speed */
179 if (*once_control
== DONE
) return 0;
180 /* Lock and test again */
181 pthread_mutex_lock(&once_masterlock
);
182 /* If init_routine is being called from another routine, wait until
184 while (*once_control
== IN_PROGRESS
) {
185 pthread_cond_wait(&once_finished
, &once_masterlock
);
187 /* Here *once_control is stable and either NEVER or DONE. */
188 if (*once_control
== NEVER
) {
189 *once_control
= IN_PROGRESS
;
190 pthread_mutex_unlock(&once_masterlock
);
192 pthread_mutex_lock(&once_masterlock
);
193 *once_control
= DONE
;
194 pthread_cond_broadcast(&once_finished
);
196 pthread_mutex_unlock(&once_masterlock
);
199 weak_alias (__pthread_once
, pthread_once
)