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

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [conts/] [libl4/] [src/] [lib/] [thread/] [thread.c] - Blame information for rev 7

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Thread creation userspace helpers
3
 *
4
 * Copyright (C) 2009 - 2010 B Labs Ltd.
5
 *
6
 * Author: Bahadir Balban
7
 */
8
#include <l4lib/lib/thread.h>
9
#include <l4lib/exregs.h>
10
#include <l4lib/mutex.h>
11
#include <l4/api/errno.h>
12
#include <l4/api/thread.h>
13
#include <memcache/memcache.h>
14
 
15
void *l4_utcb_alloc(void)
16
{
17
        return mem_cache_alloc(utcb_cache);
18
}
19
 
20
void l4_utcb_free(void *utcb)
21
{
22
        BUG_ON(mem_cache_free(utcb_cache, utcb) < 0);
23
}
24
 
25
void *l4_stack_alloc(void)
26
{
27
        void *stack = mem_cache_alloc(stack_cache);
28
 
29
        /* Since it will grow downwards */
30
        stack += (unsigned long)STACK_SIZE;
31
 
32
        return stack;
33
}
34
 
35
/*
36
 * NOTE: may be unaligned
37
 */
38
void l4_stack_free(void *stack)
39
{
40
        /* Allocation pointer was from beginning of stack */
41
        stack -= (unsigned long)STACK_SIZE;
42
        BUG_ON(mem_cache_free(stack_cache, stack) < 0);
43
}
44
 
45
/*
46
 * Allocate and init a thread struct for same space
47
 */
48
struct l4_thread *l4_thread_init(struct l4_thread *thread)
49
{
50
        /*
51
         * Allocate stack and utcb
52
         */
53
        if (!(thread->utcb = l4_utcb_alloc()))
54
                return PTR_ERR(-ENOMEM);
55
        if (!(thread->stack = l4_stack_alloc())) {
56
                l4_utcb_free(thread->utcb);
57
                return PTR_ERR(-ENOMEM);
58
        }
59
        return thread;
60
}
61
 
62
void l4_thread_free(struct l4_thread *thread)
63
{
64
        struct l4_thread_list *tlist = &l4_thread_list;
65
 
66
        /* Lock the list */
67
        l4_mutex_lock(&tlist->lock);
68
 
69
        /* Lock the thread */
70
        l4_mutex_lock(&thread->lock);
71
 
72
        /* Remove the thread from its list */
73
        list_remove(&thread->list);
74
        tlist->total--;
75
 
76
        /* Unlock list */
77
        l4_mutex_unlock(&tlist->lock);
78
 
79
        /* Free thread's stack and utcb if they exist */
80
        if (thread->stack)
81
                l4_stack_free(thread->stack);
82
        if (thread->utcb)
83
                l4_utcb_free(thread->utcb);
84
 
85
        /* Free the thread itself */
86
        BUG_ON(mem_cache_free(tlist->thread_cache, thread) < 0);
87
}
88
 
89
/*
90
 * No locking version
91
 */
92
void l4_thread_free_nolock(struct l4_thread *thread)
93
{
94
        struct l4_thread_list *tlist = &l4_thread_list;
95
 
96
        /* Free thread's stack and utcb if they exist */
97
        if (thread->stack)
98
                l4_stack_free(thread->stack);
99
        if (thread->utcb)
100
                l4_utcb_free(thread->utcb);
101
 
102
        /* Free the thread itself */
103
        BUG_ON(mem_cache_free(tlist->thread_cache, thread) < 0);
104
}
105
 
106
/*
107
 * Destroys a child thread and reclaims its
108
 * stack and utcb.
109
 *
110
 * NOTE: This function is to be called with caution:
111
 * The destroyed child must be in a state that will
112
 * not compromise the system integrity, i.e. not holding
113
 * any locks, not in the middle of an operation.
114
 *
115
 * We usually don't know whether a synchronous destruction
116
 * would cause the thread to leave structures prematurely
117
 * (e.g. need to figure out a way of knowing if the thread
118
 * is holding any locks, busy, has children ...)
119
 */
120
int thread_destroy(struct l4_thread *thread)
121
{
122
        struct l4_thread_list *tlist = &l4_thread_list;
123
        int err;
124
 
125
        /* Lock the list */
126
        l4_mutex_lock(&tlist->lock);
127
 
128
        /* Lock the thread */
129
        l4_mutex_lock(&thread->lock);
130
 
131
        /* Remove the thread from its list */
132
        list_remove(&thread->list);
133
        tlist->total--;
134
 
135
        /* Unlock list */
136
        l4_mutex_unlock(&tlist->lock);
137
 
138
        /* Destroy the thread */
139
        if ((err = l4_thread_control(THREAD_DESTROY, &thread->ids)) < 0)
140
                return err;
141
 
142
        /* Reclaim l4_thread structure */
143
        l4_thread_free_nolock(thread);
144
 
145
        return 0;
146
}
147
 
148
struct l4_thread *l4_thread_alloc_init(void)
149
{
150
        struct l4_thread_list *tlist = &l4_thread_list;
151
        struct l4_thread *thread;
152
 
153
        if (!(thread = mem_cache_zalloc(tlist->thread_cache)))
154
                return PTR_ERR(-ENOMEM);
155
 
156
        link_init(&thread->list);
157
        l4_mutex_init(&thread->lock);
158
 
159
        if (IS_ERR(thread = l4_thread_init(thread))) {
160
                mem_cache_free(tlist->thread_cache, thread);
161
                return PTR_ERR(thread);
162
        }
163
 
164
        list_insert(&tlist->thread_list, &thread->list);
165
        tlist->total++;
166
 
167
        return thread;
168
}
169
 
170
/*
171
 * Called during initialization for setting up the
172
 * existing runnable thread
173
 */
174
void l4_parent_thread_init(void)
175
{
176
        struct l4_thread *thread;
177
        struct exregs_data exregs;
178
        int err;
179
 
180
        /* Allocate structures for the first thread */
181
        thread = l4_thread_alloc_init();
182
 
183
        /* Free the allocated stack since its unnecessary */
184
        l4_stack_free(thread->stack);
185
 
186
        /* Read thread ids */
187
        l4_getid(&thread->ids);
188
 
189
        /* Set up utcb via exregs */
190
        memset(&exregs, 0, sizeof(exregs));
191
        exregs_set_utcb(&exregs, (unsigned long)thread->utcb);
192
        if ((err = l4_exchange_registers(&exregs,
193
                                         thread->ids.tid)) < 0) {
194
                printf("FATAL: Initialization of structures for "
195
                       "currently runnable thread has failed.\n"
196
                       "exregs err=%d\n", err);
197
                l4_thread_free(thread);
198
        }
199
}
200
 
201
/* For threads to exit on their own without any library maintenance */
202
void thread_exit(int exit_code)
203
{
204
        struct task_ids ids;
205
 
206
        /* FIXME: Find this from utcb */
207
        l4_getid(&ids);
208
        l4_thread_control(THREAD_DESTROY | exit_code, &ids);
209
}
210
 
211
int thread_wait(struct l4_thread *thread)
212
{
213
        int ret;
214
 
215
        /* Wait for the thread to exit */
216
        if ((ret = l4_thread_control(THREAD_WAIT, &thread->ids)) < 0)
217
                return ret;
218
 
219
        /* Claim its library structures */
220
        l4_thread_free(thread);
221
 
222
        /* Return zero or positive thread exit code */
223
        return ret;
224
}
225
 
226
/*
227
 * Create a new thread in the same address space as caller
228
 */
229
int thread_create(int (*func)(void *), void *args, unsigned int flags,
230
                  struct l4_thread **tptr)
231
{
232
        struct exregs_data exregs;
233
        struct l4_thread *thread;
234
        int err;
235
 
236
        /* Shared space only */
237
        if (!(TC_SHARE_SPACE & flags)) {
238
                printf("%s: Warning - This function allows only "
239
                       "shared space thread creation.\n",
240
                       __FUNCTION__);
241
                return -EINVAL;
242
        }
243
 
244
        /* Allocate a thread struct */
245
        if (IS_ERR(thread = l4_thread_alloc_init()))
246
                return (int)thread;
247
 
248
        /* Assign own space id since TC_SHARE_SPACE requires it */
249
        l4_getid(&thread->ids);
250
 
251
        /* Create thread in kernel */
252
        if ((err = l4_thread_control(THREAD_CREATE |
253
                                     flags, &thread->ids)) < 0)
254
                goto out_err;
255
 
256
        /* First word of new stack is arg */
257
        thread->stack[-1] = (unsigned long)args;
258
 
259
        /* Second word of new stack is function address */
260
        thread->stack[-2] = (unsigned long)func;
261
 
262
        /* Setup new thread pc, sp, utcb */
263
        memset(&exregs, 0, sizeof(exregs));
264
        exregs_set_stack(&exregs, (unsigned long)thread->stack);
265
        exregs_set_utcb(&exregs, (unsigned long)thread->utcb);
266
        exregs_set_pc(&exregs, (unsigned long)setup_new_thread);
267
 
268
        if ((err = l4_exchange_registers(&exregs, thread->ids.tid)) < 0)
269
                goto out_err;
270
 
271
        /* Start the new thread, unless specified otherwise */
272
        if (!(flags & TC_NOSTART))
273
                if ((err = l4_thread_control(THREAD_RUN,
274
                                             &thread->ids)) < 0)
275
                        goto out_err;
276
 
277
        /* Set pointer to thread structure */
278
        *tptr = thread;
279
 
280
        return 0;
281
 
282
out_err:
283
        l4_thread_free(thread);
284
        return err;
285
}
286
 

powered by: WebSVN 2.1.0

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