OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libpthread/] [linuxthreads/] [specific.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* Linuxthreads - a simple clone()-based implementation of Posix        */
2
/* threads for Linux.                                                   */
3
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4
/*                                                                      */
5
/* This program is free software; you can redistribute it and/or        */
6
/* modify it under the terms of the GNU Library General Public License  */
7
/* as published by the Free Software Foundation; either version 2       */
8
/* of the License, or (at your option) any later version.               */
9
/*                                                                      */
10
/* This program is distributed in the hope that it will be useful,      */
11
/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
12
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
13
/* GNU Library General Public License for more details.                 */
14
 
15
/* Thread-specific data */
16
 
17
#include <features.h>
18
#define __USE_GNU
19
#include <errno.h>
20
#include <stddef.h>
21
#include <stdlib.h>
22
#include "pthread.h"
23
#include "internals.h"
24
#include "spinlock.h"
25
#include "restart.h"
26
 
27
 
28
/* Table of keys. */
29
 
30
static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] =
31
  { { 0, NULL } };
32
 
33
/* For debugging purposes put the maximum number of keys in a variable.  */
34
const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX;
35
const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE;
36
 
37
/* Mutex to protect access to pthread_keys */
38
 
39
static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER;
40
 
41
/* Create a new key */
42
 
43
int pthread_key_create(pthread_key_t * key, destr_function destr)
44
{
45
    int i;
46
 
47
    pthread_mutex_lock(&pthread_keys_mutex);
48
    for (i = 0; i < PTHREAD_KEYS_MAX; i++) {
49
        if (! pthread_keys[i].in_use) {
50
            /* Mark key in use */
51
            pthread_keys[i].in_use = 1;
52
            pthread_keys[i].destr = destr;
53
            pthread_mutex_unlock(&pthread_keys_mutex);
54
            *key = i;
55
            return 0;
56
        }
57
    }
58
    pthread_mutex_unlock(&pthread_keys_mutex);
59
    return EAGAIN;
60
}
61
 
62
/* Delete a key */
63
int pthread_key_delete(pthread_key_t key)
64
{
65
    pthread_descr self = thread_self();
66
 
67
    pthread_mutex_lock(&pthread_keys_mutex);
68
    if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) {
69
        pthread_mutex_unlock(&pthread_keys_mutex);
70
        return EINVAL;
71
    }
72
    pthread_keys[key].in_use = 0;
73
    pthread_keys[key].destr = NULL;
74
 
75
    /* Set the value of the key to NULL in all running threads, so
76
       that if the key is reallocated later by pthread_key_create, its
77
       associated values will be NULL in all threads.
78
       Do nothing if no threads have been created yet.  */
79
    if (__pthread_manager_request != -1)
80
    {
81
        pthread_descr th;
82
        unsigned int idx1st, idx2nd;
83
 
84
        idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
85
        idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
86
        th = self;
87
        do {
88
            /* If the thread already is terminated don't modify the memory.  */
89
            if (!th->p_terminated && th->p_specific[idx1st] != NULL)
90
                th->p_specific[idx1st][idx2nd] = NULL;
91
            th = th->p_nextlive;
92
        } while (th != self);
93
    }
94
 
95
    pthread_mutex_unlock(&pthread_keys_mutex);
96
    return 0;
97
}
98
 
99
/* Set the value of a key */
100
 
101
int pthread_setspecific(pthread_key_t key, const void * pointer)
102
{
103
    pthread_descr self = thread_self();
104
    unsigned int idx1st, idx2nd;
105
 
106
    if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use)
107
        return EINVAL;
108
    idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
109
    idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
110
    if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) {
111
        void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *));
112
        if (newp == NULL)
113
            return ENOMEM;
114
        THREAD_SETMEM_NC(self, p_specific[idx1st], newp);
115
    }
116
    THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer;
117
    return 0;
118
}
119
 
120
/* Get the value of a key */
121
 
122
void * pthread_getspecific(pthread_key_t key)
123
{
124
    pthread_descr self = thread_self();
125
    unsigned int idx1st, idx2nd;
126
 
127
    if (key >= PTHREAD_KEYS_MAX)
128
        return NULL;
129
    idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
130
    idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
131
    if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL
132
            || !pthread_keys[key].in_use)
133
        return NULL;
134
    return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd];
135
}
136
 
137
/* Call the destruction routines on all keys */
138
 
139
void __pthread_destroy_specifics()
140
{
141
    pthread_descr self = thread_self();
142
    int i, j, round, found_nonzero;
143
    destr_function destr;
144
    void * data;
145
 
146
    for (round = 0, found_nonzero = 1;
147
            found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS;
148
            round++) {
149
        found_nonzero = 0;
150
        for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
151
            if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL)
152
                for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) {
153
                    destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr;
154
                    data = THREAD_GETMEM_NC(self, p_specific[i])[j];
155
                    if (destr != NULL && data != NULL) {
156
                        THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL;
157
                        destr(data);
158
                        found_nonzero = 1;
159
                    }
160
                }
161
    }
162
    __pthread_lock(THREAD_GETMEM(self, p_lock), self);
163
    for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) {
164
        if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) {
165
            free(THREAD_GETMEM_NC(self, p_specific[i]));
166
            THREAD_SETMEM_NC(self, p_specific[i], NULL);
167
        }
168
    }
169
    __pthread_unlock(THREAD_GETMEM(self, p_lock));
170
}
171
 
172
 
173
/* Thread-specific data for libc. */
174
#if !(USE_TLS && HAVE___THREAD)
175
static int
176
libc_internal_tsd_set(enum __libc_tsd_key_t key, const void * pointer)
177
{
178
    pthread_descr self = thread_self();
179
 
180
    THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer);
181
    return 0;
182
}
183
int (*__libc_internal_tsd_set)(enum __libc_tsd_key_t key, const void * pointer)
184
     = libc_internal_tsd_set;
185
 
186
static void *
187
libc_internal_tsd_get(enum __libc_tsd_key_t key)
188
{
189
    pthread_descr self = thread_self();
190
 
191
    return THREAD_GETMEM_NC(self, p_libc_specific[key]);
192
}
193
void * (*__libc_internal_tsd_get)(enum __libc_tsd_key_t key)
194
     = libc_internal_tsd_get;
195
 
196
static void ** __attribute__ ((__const__))
197
libc_internal_tsd_address (enum __libc_tsd_key_t key)
198
{
199
    pthread_descr self = thread_self();
200
    return &self->p_libc_specific[key];
201
}
202
void **(*const __libc_internal_tsd_address) (enum __libc_tsd_key_t key)
203
     __THROW __attribute__ ((__const__)) = libc_internal_tsd_address;
204
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.