source: rtems-libbsd/rtemsbsd/rtems/rtems-kernel-thread.c @ 5b1f20b

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 5b1f20b was 5b1f20b, checked in by Sebastian Huber <sebastian.huber@…>, on 05/06/16 at 19:22:38

Rename files for kernel namespace script

This makes it easier to create the kernel namespace header.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009-2015 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40#include <machine/rtems-bsd-kernel-space.h>
41#include <machine/rtems-bsd-thread.h>
42#include <machine/rtems-bsd-support.h>
43
44#include <rtems/bsd/sys/param.h>
45#include <rtems/bsd/sys/types.h>
46#include <sys/systm.h>
47#include <sys/kernel.h>
48#include <sys/proc.h>
49#include <sys/kthread.h>
50#include <sys/malloc.h>
51#include <sys/selinfo.h>
52#include <sys/sleepqueue.h>
53
54#include <rtems/bsd/bsd.h>
55
56#undef ticks
57
58#include <rtems/score/objectimpl.h>
59#include <rtems/score/statesimpl.h>
60#include <rtems/score/threaddispatch.h>
61#include <rtems/score/thread.h>
62#include <rtems/score/threadimpl.h>
63#include <rtems/score/threadqimpl.h>
64
65static size_t rtems_bsd_extension_index;
66
67static CHAIN_DEFINE_EMPTY(rtems_bsd_thread_delay_start_chain);
68
69static bool rtems_bsd_thread_ready_to_start;
70
71struct thread *
72rtems_bsd_get_thread(const Thread_Control *thread)
73{
74        return thread->extensions[rtems_bsd_extension_index];
75}
76
77static Thread_Control *
78rtems_bsd_get_thread_by_id(rtems_id task_id)
79{
80        Thread_Control *thread;
81        Objects_Locations location;
82
83        thread = _Thread_Get(task_id, &location);
84        switch (location) {
85                case OBJECTS_LOCAL:
86                        _Objects_Put(&thread->Object);
87                        break;
88#if defined(RTEMS_MULTIPROCESSING)
89                case OBJECTS_REMOTE:
90                        _Thread_Dispatch();
91                        thread = NULL;
92                        break;
93#endif
94                default:
95                        thread = NULL;
96                        break;
97        }
98
99        return thread;
100}
101
102struct thread *
103rtems_bsd_thread_create(Thread_Control *thread, int wait)
104{
105        struct thread *td = malloc(sizeof(*td), M_TEMP, M_ZERO | wait);
106        struct sleepqueue *sq = sleepq_alloc();
107
108        if (td != NULL && sq != NULL) {
109                td->td_thread = thread;
110                td->td_sleepqueue = sq;
111        } else {
112                free(td, M_TEMP);
113                sleepq_free(sq);
114                td = NULL;
115        }
116
117        thread->extensions[rtems_bsd_extension_index] = td;
118
119        return td;
120}
121
122static struct thread *
123rtems_bsd_get_curthread(int wait)
124{
125        Thread_Control *executing = _Thread_Get_executing();
126        struct thread *td = rtems_bsd_get_thread(executing);
127
128        if (td == NULL) {
129                td = rtems_bsd_thread_create(executing, wait);
130        }
131
132        return td;
133}
134
135struct thread *
136rtems_bsd_get_curthread_or_wait_forever(void)
137{
138        return rtems_bsd_get_curthread(M_WAITOK);
139}
140
141struct thread *
142rtems_bsd_get_curthread_or_null(void)
143{
144        return rtems_bsd_get_curthread(0);
145}
146
147static bool
148rtems_bsd_is_bsd_thread(Thread_Control *thread)
149{
150        return thread->Object.name.name_u32 == BSD_TASK_NAME;
151}
152
153static bool
154rtems_bsd_extension_thread_create(
155        Thread_Control *executing,
156        Thread_Control *created
157)
158{
159        bool ok;
160
161        if (rtems_bsd_is_bsd_thread(created)) {
162                struct thread *td = rtems_bsd_thread_create(created, 0);
163
164                ok = td != NULL;
165        } else {
166                ok = true;
167        }
168
169        return ok;
170}
171
172static void
173rtems_bsd_extension_thread_delete(
174        Thread_Control *executing,
175        Thread_Control *deleted
176)
177{
178        struct thread *td = rtems_bsd_get_thread(deleted);
179
180        if (td != NULL) {
181                seltdfini(td);
182                sleepq_free(td->td_sleepqueue);
183                free(td, M_TEMP);
184        }
185}
186
187static const rtems_extensions_table rtems_bsd_extensions = {
188        .thread_create = rtems_bsd_extension_thread_create,
189        .thread_delete = rtems_bsd_extension_thread_delete
190};
191
192static void
193rtems_bsd_threads_init_early(void *arg)
194{
195        rtems_id ext_id;
196        rtems_status_code sc;
197
198        (void) arg;
199
200        sc = rtems_extension_create(
201                BSD_TASK_NAME,
202                &rtems_bsd_extensions,
203                &ext_id
204        );
205        if (sc != RTEMS_SUCCESSFUL) {
206                BSD_PANIC("cannot create extension");
207        }
208
209        rtems_bsd_extension_index = rtems_object_id_get_index(ext_id);
210}
211
212static void
213rtems_bsd_threads_init_late(void *arg)
214{
215        Chain_Control *chain = &rtems_bsd_thread_delay_start_chain;
216        Chain_Node *node;
217
218        (void) arg;
219
220        while ((node = _Chain_Get_unprotected(chain)) != NULL) {
221                Thread_Control *thread = (Thread_Control *) node;
222                rtems_status_code sc;
223
224                sc = rtems_task_start(thread->Object.id,
225                    thread->Start.Entry.Kinds.Numeric.entry,
226                    thread->Start.Entry.Kinds.Numeric.argument);
227                BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
228        }
229
230        rtems_bsd_thread_ready_to_start = true;
231}
232
233SYSINIT(rtems_bsd_threads_early, SI_SUB_INTRINSIC, SI_ORDER_ANY,
234    rtems_bsd_threads_init_early, NULL);
235
236SYSINIT(rtems_bsd_threads_late, SI_SUB_LAST, SI_ORDER_ANY,
237    rtems_bsd_threads_init_late, NULL);
238
239static int
240rtems_bsd_thread_start(struct thread **td_ptr, void (*func)(void *), void *arg,
241    int flags, int pages, const char *fmt, va_list ap)
242{
243        int eno = 0;
244        rtems_status_code sc;
245        rtems_id task_id;
246        struct thread *td;
247        char name[sizeof(td->td_name)];
248
249        BSD_ASSERT(pages >= 0);
250
251        vsnprintf(name, sizeof(name), fmt, ap);
252
253        sc = rtems_task_create(
254                BSD_TASK_NAME,
255                rtems_bsd_get_task_priority(name),
256                rtems_bsd_get_task_stack_size(name)
257                        + (size_t) pages * PAGE_SIZE,
258                RTEMS_DEFAULT_MODES,
259                RTEMS_DEFAULT_ATTRIBUTES,
260                &task_id
261        );
262        if (sc == RTEMS_SUCCESSFUL) {
263                Thread_Control *thread = rtems_bsd_get_thread_by_id(task_id);
264
265                BSD_ASSERT(thread != NULL);
266
267                td = rtems_bsd_get_thread(thread);
268                BSD_ASSERT(td != NULL);
269
270                memcpy(td->td_name, name, sizeof(name));
271
272                if (rtems_bsd_thread_ready_to_start) {
273                        sc = rtems_task_start(task_id, (rtems_task_entry) func,
274                            (rtems_task_argument) arg);
275                        BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
276                } else {
277                        thread->Start.Entry.Kinds.Numeric.entry =
278                            (void (*)(Thread_Entry_numeric_type))func;
279                        thread->Start.Entry.Kinds.Numeric.argument =
280                            (Thread_Entry_numeric_type)arg;
281                        _Chain_Append_unprotected(
282                            &rtems_bsd_thread_delay_start_chain,
283                            &thread->Object.Node);
284                }
285
286                if (td_ptr != NULL) {
287                        *td_ptr = td;
288                }
289        } else {
290                eno = ENOMEM;
291        }
292
293        return eno;
294}
295
296static __dead2 void
297rtems_bsd_thread_delete(void)
298{
299        rtems_task_delete(RTEMS_SELF);
300        BSD_PANIC("delete self failed");
301}
302
303void
304kproc_start(const void *udata)
305{
306        const struct kproc_desc *pd = udata;
307        int eno = kproc_create((void (*)(void *))pd->func, NULL, pd->global_procpp, 0, 0, "%s", pd->arg0);
308
309        BSD_ASSERT(eno == 0);
310}
311
312int
313kproc_create(void (*func)(void *), void *arg, struct proc **newpp, int flags, int pages, const char *fmt, ...)
314{
315        int eno = 0;
316        va_list ap;
317
318        va_start(ap, fmt);
319        eno = rtems_bsd_thread_start(newpp, func, arg, flags, pages, fmt, ap);
320        va_end(ap);
321
322        return eno;
323}
324
325void
326kproc_exit(int ecode)
327{
328        rtems_bsd_thread_delete();
329}
330
331void
332kthread_start(const void *udata)
333{
334        const struct kthread_desc *td = udata;
335        int eno = kthread_add((void (*)(void *)) td->func, NULL, NULL, td->global_threadpp, 0, 0, "%s", td->arg0);
336
337        BSD_ASSERT(eno == 0);
338}
339
340int
341kthread_add(void (*func)(void *), void *arg, struct proc *p, struct thread **newtdp, int flags, int pages, const char *fmt, ...)
342{
343        int eno = 0;
344        va_list ap;
345
346        va_start(ap, fmt);
347        eno = rtems_bsd_thread_start(newtdp, func, arg, flags, pages, fmt, ap);
348        va_end(ap);
349
350        return eno;
351}
352
353void
354kthread_exit(void)
355{
356        rtems_bsd_thread_delete();
357}
358
359int
360kproc_kthread_add(void (*func)(void *), void *arg, struct proc **procptr, struct thread **tdptr, int flags, int pages, const char * procname, const char *fmt, ...)
361{
362        int eno = 0;
363        va_list ap;
364
365        va_start(ap, fmt);
366        eno = rtems_bsd_thread_start(tdptr, func, arg, flags, pages, fmt, ap);
367        va_end(ap);
368
369        return eno;
370}
Note: See TracBrowser for help on using the repository browser.