Subversion Repositories Kolibri OS

Rev

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

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