1/* MIPS SDE threads compatibility routines for libgcc2 and libobjc.  */
2/* Compile this one with gcc.  */
3/* Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4   Contributed by Nigel Stephens <nigel@mips.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18Under Section 7 of GPL version 3, you are granted additional
19permissions described in the GCC Runtime Library Exception, version
203.1, as published by the Free Software Foundation.
21
22You should have received a copy of the GNU General Public License and
23a copy of the GCC Runtime Library Exception along with this program;
24see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25<http://www.gnu.org/licenses/>.  */
26
27#ifndef GCC_GTHR_MIPSSDE_H
28#define GCC_GTHR_MIPSSDE_H
29
30/* MIPS SDE threading API specific definitions.
31   Easy, since the interface is pretty much one-to-one.  */
32
33#define __GTHREADS 1
34
35#include <sdethread.h>
36#include <unistd.h>
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42typedef __sdethread_key_t __gthread_key_t;
43typedef __sdethread_once_t __gthread_once_t;
44typedef __sdethread_mutex_t __gthread_mutex_t;
45
46typedef struct {
47  long depth;
48  __sdethread_t owner;
49  __sdethread_mutex_t actual;
50} __gthread_recursive_mutex_t;
51
52#define __GTHREAD_MUTEX_INIT __SDETHREAD_MUTEX_INITIALIZER("gthr")
53#define __GTHREAD_ONCE_INIT __SDETHREAD_ONCE_INIT
54static inline int
55__gthread_recursive_mutex_init_function(__gthread_recursive_mutex_t *__mutex);
56#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
57
58#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
59# define __gthrw(name) \
60  static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
61# define __gthrw_(name) __gthrw_ ## name
62#else
63# define __gthrw(name)
64# define __gthrw_(name) name
65#endif
66
67__gthrw(__sdethread_once)
68__gthrw(__sdethread_key_create)
69__gthrw(__sdethread_key_delete)
70__gthrw(__sdethread_getspecific)
71__gthrw(__sdethread_setspecific)
72
73__gthrw(__sdethread_self)
74
75__gthrw(__sdethread_mutex_lock)
76__gthrw(__sdethread_mutex_trylock)
77__gthrw(__sdethread_mutex_unlock)
78
79__gthrw(__sdethread_mutex_init)
80
81__gthrw(__sdethread_threading)
82
83#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
84
85static inline int
86__gthread_active_p (void)
87{
88  return !!(void *)&__sdethread_threading;
89}
90
91#else /* not SUPPORTS_WEAK */
92
93static inline int
94__gthread_active_p (void)
95{
96  return 1;
97}
98
99#endif /* SUPPORTS_WEAK */
100
101static inline int
102__gthread_once (__gthread_once_t *__once, void (*__func) (void))
103{
104  if (__gthread_active_p ())
105    return __gthrw_(__sdethread_once) (__once, __func);
106  else
107    return -1;
108}
109
110static inline int
111__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
112{
113  return __gthrw_(__sdethread_key_create) (__key, __dtor);
114}
115
116static inline int
117__gthread_key_delete (__gthread_key_t __key)
118{
119  return __gthrw_(__sdethread_key_delete) (__key);
120}
121
122static inline void *
123__gthread_getspecific (__gthread_key_t __key)
124{
125  return __gthrw_(__sdethread_getspecific) (__key);
126}
127
128static inline int
129__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
130{
131  return __gthrw_(__sdethread_setspecific) (__key, __ptr);
132}
133
134static inline int
135__gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex))
136{
137  return 0;
138}
139
140static inline int
141__gthread_mutex_lock (__gthread_mutex_t *__mutex)
142{
143  if (__gthread_active_p ())
144    return __gthrw_(__sdethread_mutex_lock) (__mutex);
145  else
146    return 0;
147}
148
149static inline int
150__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
151{
152  if (__gthread_active_p ())
153    return __gthrw_(__sdethread_mutex_trylock) (__mutex);
154  else
155    return 0;
156}
157
158static inline int
159__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
160{
161  if (__gthread_active_p ())
162    return __gthrw_(__sdethread_mutex_unlock) (__mutex);
163  else
164    return 0;
165}
166
167static inline int
168__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
169{
170  __mutex->depth = 0;
171  __mutex->owner = __gthrw_(__sdethread_self) ();
172  return __gthrw_(__sdethread_mutex_init) (&__mutex->actual, NULL);
173}
174
175static inline int
176__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
177{
178  if (__gthread_active_p ())
179    {
180      __sdethread_t __me = __gthrw_(__sdethread_self) ();
181
182      if (__mutex->owner != __me)
183	{
184	  __gthrw_(__sdethread_mutex_lock) (&__mutex->actual);
185	  __mutex->owner = __me;
186	}
187
188      __mutex->depth++;
189    }
190  return 0;
191}
192
193static inline int
194__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
195{
196  if (__gthread_active_p ())
197    {
198      __sdethread_t __me = __gthrw_(__sdethread_self) ();
199
200      if (__mutex->owner != __me)
201	{
202	  if (__gthrw_(__sdethread_mutex_trylock) (&__mutex->actual))
203	    return 1;
204	  __mutex->owner = __me;
205	}
206
207      __mutex->depth++;
208    }
209  return 0;
210}
211
212static inline int
213__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
214{
215  if (__gthread_active_p ())
216    {
217      if (--__mutex->depth == 0)
218	{
219	   __mutex->owner = (__sdethread_t) 0;
220	   __gthrw_(__sdethread_mutex_unlock) (&__mutex->actual);
221	}
222    }
223  return 0;
224}
225
226#ifdef __cplusplus
227}
228#endif
229
230#endif /* ! GCC_GTHR_MIPSSDE_H */
231