Subversion Repositories Kolibri OS

Rev

Rev 6527 | 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
 
6533 serge 23
#include 
6527 serge 24
#include 
6520 serge 25
#include "gthr-kos32.h"
26
 
27
#define FUTEX_INIT      0
28
#define FUTEX_DESTROY   1
29
#define FUTEX_WAIT      2
30
#define FUTEX_WAKE      3
31
 
32
#define exchange_acquire(ptr, new) \
33
  __atomic_exchange_4((ptr), (new), __ATOMIC_ACQUIRE)
34
 
35
#define exchange_release(ptr, new) \
36
  __atomic_exchange_4((ptr), (new), __ATOMIC_RELEASE)
37
 
38
int __gthr_kos32_once (__gthread_once_t *once, void (*func) (void))
39
{
40
    if (once == NULL || func == NULL)
41
        return EINVAL;
42
 
43
    if (! once->done)
44
    {
45
        if (__sync_add_and_fetch(&(once->started), 1) == 0)
46
        {
47
            (*func) ();
48
            once->done = 1;
49
        }
50
        else
51
        {
52
            while (! once->done)
53
                yield();
54
        }
55
    }
56
    return 0;
57
};
58
 
59
int __gthr_kos32_key_create (__gthread_key_t *key,
60
			 void (*dtor) (void *) __attribute__((unused)))
61
{
62
    int status = 0;
63
    unsigned int tls_index = tls_alloc();
64
    if (tls_index != 0xFFFFFFFF)
65
    {
66
        *key = tls_index;
67
#ifdef MINGW32_SUPPORTS_MT_EH
68
      /* Mingw runtime will run the dtors in reverse order for each thread
69
         when the thread exits.  */
70
        status = __mingwthr_key_dtor (*key, dtor);
71
#endif
72
    }
73
    else
74
        status = -1;
75
    return status;
76
}
77
 
78
int __gthr_kos32_key_delete (__gthread_key_t key)
79
{
80
    return tls_free(key);
81
}
82
 
83
void* __gthr_kos32_getspecific (__gthread_key_t key)
84
{
6527 serge 85
    return tls_get(key);
6520 serge 86
}
87
 
88
int __gthr_kos32_setspecific (__gthread_key_t key, const void *ptr)
89
{
6527 serge 90
    return tls_set(key, CONST_CAST2(void *, const void *, ptr));
6520 serge 91
}
92
 
93
void __gthr_kos32_mutex_init_function (__gthread_mutex_t *mutex)
94
{
95
    int handle;
96
 
97
    mutex->lock = 0;
98
 
99
    __asm__ volatile(
100
    "int $0x40\t"
101
    :"=a"(handle)
102
    :"a"(77),"b"(FUTEX_INIT),"c"(mutex));
103
    mutex->handle = handle;
104
}
105
 
106
void __gthr_kos32_mutex_destroy (__gthread_mutex_t *mutex)
107
{
108
    int retval;
109
 
110
    __asm__ volatile(
111
    "int $0x40\t"
112
    :"=a"(retval)
113
    :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle));
114
}
115
 
116
int __gthr_kos32_mutex_lock (__gthread_mutex_t *mutex)
117
{
118
    int tmp;
119
 
120
    if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
121
        return 0;
122
 
123
    while (exchange_acquire (&mutex->lock, 2) != 0)
124
    {
125
        __asm__ volatile(
126
        "int $0x40\t\n"
127
        :"=a"(tmp)
128
        :"a"(77),"b"(FUTEX_WAIT),
129
        "c"(mutex->handle),"d"(2),"S"(0));
130
   }
131
   return 0;
132
}
133
 
134
int __gthr_kos32_mutex_trylock (__gthread_mutex_t *mutex)
135
{
136
    int zero = 0;
137
 
6527 serge 138
    return !__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED);
6520 serge 139
}
140
 
141
int __gthr_kos32_mutex_unlock (__gthread_mutex_t *mutex)
142
{
143
    int prev;
144
 
145
    prev = exchange_release (&mutex->lock, 0);
146
 
147
    if (prev != 1)
148
    {
149
        __asm__ volatile(
150
        "int $0x40\t"
151
        :"=a"(prev)
152
        :"a"(77),"b"(FUTEX_WAKE),
153
        "c"(mutex->handle),"d"(1));
154
    };
155
    return 0;
156
}
157
 
158
void __gthr_kos32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
159
{
6527 serge 160
    int handle;
161
 
162
    mutex->lock = 0;
163
 
164
    __asm__ volatile(
165
    "int $0x40\t"
166
    :"=a"(handle)
167
    :"a"(77),"b"(FUTEX_INIT),"c"(mutex));
168
    mutex->handle = handle;
169
 
170
    mutex->depth = 0;
171
    mutex->owner = 0;
6520 serge 172
}
173
 
6527 serge 174
int __gthr_kos32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
6520 serge 175
{
6527 serge 176
    int tmp;
177
 
178
    unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
179
 
180
    if( __sync_fetch_and_add(&mutex->lock, 1) == 0)
6520 serge 181
    {
6527 serge 182
        mutex->depth = 1;
183
        mutex->owner = me;
184
        return 0;
6520 serge 185
    }
6527 serge 186
    else if (mutex->owner == me)
6520 serge 187
    {
6527 serge 188
        __sync_fetch_and_sub(&mutex->lock, 1);
189
        ++(mutex->depth);
6520 serge 190
    }
6527 serge 191
    else while (exchange_acquire (&mutex->lock, 2) != 0)
6520 serge 192
    {
6527 serge 193
        __asm__ volatile(
194
        "int $0x40\t\n"
195
        :"=a"(tmp)
196
        :"a"(77),"b"(FUTEX_WAIT),
197
        "c"(mutex->handle),"d"(2),"S"(0));
198
        mutex->depth = 1;
199
        mutex->owner = me;
200
    };
201
 
202
    return 0;
6520 serge 203
}
204
 
6527 serge 205
int __gthr_kos32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
6520 serge 206
{
6527 serge 207
    unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK);
208
    int zero = 0;
209
 
210
    if(__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED))
6520 serge 211
    {
6527 serge 212
        mutex->depth = 1;
213
        mutex->owner = me;
6520 serge 214
    }
6527 serge 215
    else if (mutex->owner == me)
216
        ++(mutex->depth);
217
    else
218
        return 1;
6520 serge 219
 
6527 serge 220
    return 0;
6520 serge 221
}
222
 
6527 serge 223
int __gthr_kos32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
6520 serge 224
{
6527 serge 225
    --(mutex->depth);
226
 
227
    if (mutex->depth == 0)
6520 serge 228
    {
6527 serge 229
        int prev;
6520 serge 230
 
6527 serge 231
        prev = exchange_release (&mutex->lock, 0);
6520 serge 232
 
6527 serge 233
        if (prev != 1)
234
        {
235
            __asm__ volatile(
236
            "int $0x40\t"
237
            :"=a"(prev)
238
            :"a"(77),"b"(FUTEX_WAKE),
239
            "c"(mutex->handle),"d"(1));
240
        };
241
        mutex->owner = 0;
242
    };
243
 
244
    return 0;
6520 serge 245
}
246
 
6527 serge 247
int __gthr_kos32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex)
6520 serge 248
{
6527 serge 249
    int retval;
250
 
251
    __asm__ volatile(
252
    "int $0x40\t"
253
    :"=a"(retval)
254
    :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle));
255
 
256
    return 0;
6520 serge 257
}
258