Subversion Repositories Kolibri OS

Rev

Rev 6527 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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