Subversion Repositories Kolibri OS

Rev

Rev 6520 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6520 serge 1
/* Implementation of Kos32-specific threads compatibility routines for
2
   libgcc2.
3
 
4
GCC is free software; you can redistribute it and/or modify it under
5
the terms of the GNU General Public License as published by the Free
6
Software Foundation; either version 3, or (at your option) any later
7
version.
8
 
9
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
10
WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
for more details.
13
 
14
Under Section 7 of GPL version 3, you are granted additional
15
permissions described in the GCC Runtime Library Exception, version
16
3.1, as published by the Free Software Foundation.
17
 
18
You should have received a copy of the GNU General Public License and
19
a copy of the GCC Runtime Library Exception along with this program;
20
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21
.  */
22
 
6527 serge 23
#include 
6520 serge 24
#include "gthr-kos32.h"
25
 
26
#define FUTEX_INIT      0
27
#define FUTEX_DESTROY   1
28
#define FUTEX_WAIT      2
29
#define FUTEX_WAKE      3
30
 
31
#define exchange_acquire(ptr, new) \
32
  __atomic_exchange_4((ptr), (new), __ATOMIC_ACQUIRE)
33
 
34
#define exchange_release(ptr, new) \
35
  __atomic_exchange_4((ptr), (new), __ATOMIC_RELEASE)
36
 
37
int __gthr_kos32_once (__gthread_once_t *once, void (*func) (void))
38
{
39
    if (once == NULL || func == NULL)
40
        return EINVAL;
41
 
42
    if (! once->done)
43
    {
44
        if (__sync_add_and_fetch(&(once->started), 1) == 0)
45
        {
46
            (*func) ();
47
            once->done = 1;
48
        }
49
        else
50
        {
51
            while (! once->done)
52
                yield();
53
        }
54
    }
55
    return 0;
56
};
57
 
58
int __gthr_kos32_key_create (__gthread_key_t *key,
59
			 void (*dtor) (void *) __attribute__((unused)))
60
{
61
    int status = 0;
62
    unsigned int tls_index = tls_alloc();
63
    if (tls_index != 0xFFFFFFFF)
64
    {
65
        *key = tls_index;
66
#ifdef MINGW32_SUPPORTS_MT_EH
67
      /* Mingw runtime will run the dtors in reverse order for each thread
68
         when the thread exits.  */
69
        status = __mingwthr_key_dtor (*key, dtor);
70
#endif
71
    }
72
    else
73
        status = -1;
74
    return status;
75
}
76
 
77
int __gthr_kos32_key_delete (__gthread_key_t key)
78
{
79
    return tls_free(key);
80
}
81
 
82
void* __gthr_kos32_getspecific (__gthread_key_t key)
83
{
6527 serge 84
    return tls_get(key);
6520 serge 85
}
86
 
87
int __gthr_kos32_setspecific (__gthread_key_t key, const void *ptr)
88
{
6527 serge 89
    return tls_set(key, CONST_CAST2(void *, const void *, ptr));
6520 serge 90
}
91
 
92
void __gthr_kos32_mutex_init_function (__gthread_mutex_t *mutex)
93
{
94
    int handle;
95
 
96
    mutex->lock = 0;
97
 
98
    __asm__ volatile(
99
    "int $0x40\t"
100
    :"=a"(handle)
101
    :"a"(77),"b"(FUTEX_INIT),"c"(mutex));
102
    mutex->handle = handle;
103
}
104
 
105
void __gthr_kos32_mutex_destroy (__gthread_mutex_t *mutex)
106
{
107
    int retval;
108
 
109
    __asm__ volatile(
110
    "int $0x40\t"
111
    :"=a"(retval)
112
    :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle));
113
}
114
 
115
int __gthr_kos32_mutex_lock (__gthread_mutex_t *mutex)
116
{
117
    int tmp;
118
 
119
    if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
120
        return 0;
121
 
122
    while (exchange_acquire (&mutex->lock, 2) != 0)
123
    {
124
        __asm__ volatile(
125
        "int $0x40\t\n"
126
        :"=a"(tmp)
127
        :"a"(77),"b"(FUTEX_WAIT),
128
        "c"(mutex->handle),"d"(2),"S"(0));
129
   }
130
   return 0;
131
}
132
 
133
int __gthr_kos32_mutex_trylock (__gthread_mutex_t *mutex)
134
{
135
    int zero = 0;
136
 
6527 serge 137
    return !__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED);
6520 serge 138
}
139
 
140
int __gthr_kos32_mutex_unlock (__gthread_mutex_t *mutex)
141
{
142
    int prev;
143
 
144
    prev = exchange_release (&mutex->lock, 0);
145
 
146
    if (prev != 1)
147
    {
148
        __asm__ volatile(
149
        "int $0x40\t"
150
        :"=a"(prev)
151
        :"a"(77),"b"(FUTEX_WAKE),
152
        "c"(mutex->handle),"d"(1));
153
    };
154
    return 0;
155
}
156
 
157
void __gthr_kos32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
158
{
6527 serge 159
    int handle;
160
 
161
    mutex->lock = 0;
162
 
163
    __asm__ volatile(
164
    "int $0x40\t"
165
    :"=a"(handle)
166
    :"a"(77),"b"(FUTEX_INIT),"c"(mutex));
167
    mutex->handle = handle;
168
 
169
    mutex->depth = 0;
170
    mutex->owner = 0;
6520 serge 171
}
172
 
6527 serge 173
int __gthr_kos32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
6520 serge 174
{
6527 serge 175
    int tmp;
176
 
177
    unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
178
 
179
    if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
6520 serge 180
    {
6527 serge 181
        mutex->depth = 1;
182
        mutex->owner = me;
183
        return 0;
6520 serge 184
    }
6527 serge 185
    else if (mutex->owner == me)
6520 serge 186
    {
6527 serge 187
        __sync_fetch_and_sub(&mutex->lock, 1);
188
        ++(mutex->depth);
6520 serge 189
    }
6527 serge 190
    else while (exchange_acquire (&mutex->lock, 2) != 0)
6520 serge 191
    {
6527 serge 192
        __asm__ volatile(
193
        "int $0x40\t\n"
194
        :"=a"(tmp)
195
        :"a"(77),"b"(FUTEX_WAIT),
196
        "c"(mutex->handle),"d"(2),"S"(0));
197
        mutex->depth = 1;
198
        mutex->owner = me;
199
    };
200
 
201
    return 0;
6520 serge 202
}
203
 
6527 serge 204
int __gthr_kos32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
6520 serge 205
{
6527 serge 206
    unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
207
    int zero = 0;
208
 
209
    if(__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED))
6520 serge 210
    {
6527 serge 211
        mutex->depth = 1;
212
        mutex->owner = me;
6520 serge 213
    }
6527 serge 214
    else if (mutex->owner == me)
215
        ++(mutex->depth);
216
    else
217
        return 1;
6520 serge 218
 
6527 serge 219
    return 0;
6520 serge 220
}
221
 
6527 serge 222
int __gthr_kos32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
6520 serge 223
{
6527 serge 224
    --(mutex->depth);
225
 
226
    if (mutex->depth == 0)
6520 serge 227
    {
6527 serge 228
        int prev;
6520 serge 229
 
6527 serge 230
        prev = exchange_release (&mutex->lock, 0);
6520 serge 231
 
6527 serge 232
        if (prev != 1)
233
        {
234
            __asm__ volatile(
235
            "int $0x40\t"
236
            :"=a"(prev)
237
            :"a"(77),"b"(FUTEX_WAKE),
238
            "c"(mutex->handle),"d"(1));
239
        };
240
        mutex->owner = 0;
241
    };
242
 
243
    return 0;
6520 serge 244
}
245
 
6527 serge 246
int __gthr_kos32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex)
6520 serge 247
{
6527 serge 248
    int retval;
249
 
250
    __asm__ volatile(
251
    "int $0x40\t"
252
    :"=a"(retval)
253
    :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle));
254
 
255
    return 0;
6520 serge 256
}
257