summaryrefslogtreecommitdiffstats
path: root/rtemsbsd/rtems/rtems-bsd-thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemsbsd/rtems/rtems-bsd-thread.c')
-rw-r--r--rtemsbsd/rtems/rtems-bsd-thread.c319
1 files changed, 166 insertions, 153 deletions
diff --git a/rtemsbsd/rtems/rtems-bsd-thread.c b/rtemsbsd/rtems/rtems-bsd-thread.c
index 357fb45c..a0a78a59 100644
--- a/rtemsbsd/rtems/rtems-bsd-thread.c
+++ b/rtemsbsd/rtems/rtems-bsd-thread.c
@@ -7,10 +7,10 @@
*/
/*
- * Copyright (c) 2009, 2010 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2009-2013 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
@@ -38,225 +38,238 @@
*/
#include <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
#include <rtems/bsd/sys/param.h>
#include <rtems/bsd/sys/types.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/malloc.h>
-#include <rtems/bsd/sys/lock.h>
-#include <sys/mutex.h>
+#include <sys/selinfo.h>
+#include <sys/filedesc.h>
#include <sys/jail.h>
#include <sys/resourcevar.h>
-#include <sys/filedesc.h>
+
+#include <rtems/score/threadimpl.h>
+#include <rtems/score/objectimpl.h>
RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_thread_chain);
/* FIXME: What to do with the credentials? */
static struct ucred FIXME_ucred = {
- .cr_ref = 1 /* reference count */
+ .cr_ref = 1 /* reference count */
};
static struct filedesc FIXME_fd = {
- .fd_ofiles = NULL /* file structures for open files */
+ .fd_ofiles = NULL /* file structures for open files */
};
static struct proc FIXME_proc = {
.p_ucred = NULL /* (c) Process owner's identity. */
};
-static int prison_init = 1;
static struct prison FIXME_prison = {
.pr_parent = NULL
};
-static struct uidinfo FIXME_uidinfo; /* per euid resource consumption */
-static struct uidinfo FIXME_ruidinfo; /* per ruid resource consumption */
+static size_t rtems_bsd_extension_index;
-static struct thread *rtems_bsd_current_td = NULL;
-
-static void rtems_bsd_thread_descriptor_dtor(void *td)
+struct thread *
+rtems_bsd_get_thread(const Thread_Control *thread)
{
- // XXX are there other pieces to clean up?
- free(td, M_TEMP);
+ return thread->extensions[rtems_bsd_extension_index];
}
static struct thread *
-rtems_bsd_thread_init( rtems_id id )
+rtems_bsd_get_thread_by_id(rtems_id task_id)
{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- unsigned index = 0;
- char name [5] = "_???";
- struct thread *td;
- struct proc *proc;
-
- td = malloc(sizeof(struct thread), M_TEMP, M_WAITOK | M_ZERO);
- if (td == NULL)
- return NULL;
-
- // Initialize the thread descriptor
- index = rtems_object_id_get_index(id);
- snprintf(name + 1, sizeof(name) - 1, "%03u", index);
- sc = rtems_object_set_name(id, name);
- if (sc != RTEMS_SUCCESSFUL) {
- // XXX does the thread get deleted? Seems wrong
- // rtems_task_delete(id);
- free(td, M_TEMP);
- return NULL;
+ struct thread *td = NULL;
+ Thread_Control *thread;
+ Objects_Locations location;
+
+ thread = _Thread_Get(task_id, &location);
+ switch (location) {
+ case OBJECTS_LOCAL:
+ td = rtems_bsd_get_thread(thread);
+ _Objects_Put(&thread->Object);
+ break;
+#if defined(RTEMS_MULTIPROCESSING)
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ break;
+#endif
+ default:
+ break;
}
- td->td_id = id;
- td->td_ucred = crhold(&FIXME_ucred);
-
- td->td_proc = &FIXME_proc;
- if (td->td_proc->p_ucred == NULL) {
- if ( prison_init ) {
- mtx_init(&FIXME_prison.pr_mtx, "prison lock", NULL, MTX_DEF | MTX_DUPOK);
- prison_init = 0;
- }
- FIXME_ucred.cr_prison = &FIXME_prison; /* jail(2) */
- FIXME_ucred.cr_uidinfo = uifind(0);
- FIXME_ucred.cr_ruidinfo = uifind(0);
- FIXME_ucred.cr_ngroups = 1; /* group 0 */
-
- td->td_proc->p_ucred = crhold(&FIXME_ucred);
- mtx_init(&td->td_proc->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK);
- td->td_proc->p_pid = getpid();
- td->td_proc->p_fibnum = 0;
- td->td_proc->p_fd = &FIXME_fd;
- sx_init_flags(&FIXME_fd.fd_sx, "config SX thread lock", SX_DUPOK);
- }
+ return td;
+}
- // Actually set the global pointer
- rtems_bsd_current_td = td;
+struct thread *
+rtems_bsd_thread_create(Thread_Control *thread, int wait)
+{
+ struct thread *td = malloc(sizeof(*td), M_TEMP, M_ZERO | wait);
- // Now add the task descriptor as a per-task variable
- sc = rtems_task_variable_add(
- id,
- &rtems_bsd_current_td,
- rtems_bsd_thread_descriptor_dtor
- );
- if (sc != RTEMS_SUCCESSFUL) {
- free(td, M_TEMP);
- return NULL;
+ if (td != NULL) {
+ td->td_thread = thread;
+ td->td_proc = &FIXME_proc;
}
- return td;
+ thread->extensions[rtems_bsd_extension_index] = td;
+
+ return td;
}
-/*
- * Threads which delete themselves would leak the task
- * descriptor so we are using the per-task variable so
- * it can be cleaned up.
- */
-struct thread *rtems_get_curthread(void)
+static struct thread *
+rtems_bsd_get_curthread(int wait)
{
- struct thread *td;
-
- /*
- * If we already have a struct thread associated with this thread,
- * obtain it. Otherwise, allocate and initialize one.
- */
- td = rtems_bsd_current_td;
- if ( td == NULL ) {
- td = rtems_bsd_thread_init( rtems_task_self() );
- if ( td == NULL ){
- panic("rtems_get_curthread: Unable to thread descriptor\n");
- }
+ Thread_Control *executing = _Thread_Get_executing();
+ struct thread *td = rtems_bsd_get_thread(executing);
+
+ if (td == NULL) {
+ td = rtems_bsd_thread_create(executing, wait);
}
- return td;
+ return td;
}
-static int
-rtems_bsd_thread_start(struct thread **td_ptr, void (*func)(void *), void *arg, int flags, int pages, const char *fmt, va_list ap)
+struct thread *
+rtems_bsd_get_curthread_or_wait_forever(void)
{
- struct thread *td = malloc(sizeof(struct thread), M_TEMP, M_WAITOK | M_ZERO);
+ return rtems_bsd_get_curthread(M_WAITOK);
+}
- if (td != NULL) {
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- rtems_id id = RTEMS_ID_NONE;
- unsigned index = 0;
- char name [5] = "_???";
-
- BSD_ASSERT(pages >= 0);
-
- memset( td, 0, sizeof(struct thread) );
-
- sc = rtems_task_create(
- rtems_build_name('_', 'T', 'S', 'K'),
- BSD_TASK_PRIORITY_NORMAL,
- BSD_MINIMUM_TASK_STACK_SIZE + (size_t) pages * PAGE_SIZE,
- RTEMS_DEFAULT_ATTRIBUTES,
- RTEMS_DEFAULT_ATTRIBUTES,
- &id
- );
- if (sc != RTEMS_SUCCESSFUL) {
- free(td, M_TEMP);
-
- return ENOMEM;
- }
+struct thread *
+rtems_bsd_get_curthread_or_null(void)
+{
+ return rtems_bsd_get_curthread(0);
+}
- td = rtems_bsd_thread_init( id );
- if (!td)
- return ENOMEM;
-
- sc = rtems_task_start(id, (rtems_task_entry) func, (rtems_task_argument) arg);
- if (sc != RTEMS_SUCCESSFUL) {
- rtems_task_delete(id);
- free(td, M_TEMP);
+static bool
+rtems_bsd_is_bsd_thread(Thread_Control *thread)
+{
+ return thread->Object.name.name_u32 == BSD_TASK_NAME;
+}
+
+static bool
+rtems_bsd_extension_thread_create(
+ Thread_Control *executing,
+ Thread_Control *created
+)
+{
+ bool ok = true;
+
+ if (rtems_bsd_is_bsd_thread(created)) {
+ struct thread *td = rtems_bsd_thread_create(created, 0);
- return ENOMEM;
+ ok = td != NULL;
+ if (ok) {
+ rtems_chain_append(&rtems_bsd_thread_chain, &td->td_node);
}
+ }
- td->td_id = id;
- vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap);
- td->td_ucred = crhold(&FIXME_ucred);
+ return ok;
+}
+
+static void
+rtems_bsd_extension_thread_delete(
+ Thread_Control *executing,
+ Thread_Control *deleted
+)
+{
+ struct thread *td = rtems_bsd_get_thread(deleted);
- rtems_chain_append(&rtems_bsd_thread_chain, &td->td_node);
+ if (td != NULL) {
+ seltdfini(td);
- if (td_ptr != NULL) {
- *td_ptr = td;
+ if (rtems_bsd_is_bsd_thread(deleted)) {
+ rtems_chain_explicit_extract(&rtems_bsd_thread_chain, &td->td_node);
}
- return 0;
+ free(td, M_TEMP);
}
-
- return ENOMEM;
}
-static void rtems_bsd_thread_delete(void) __dead2;
+static const rtems_extensions_table rtems_bsd_extensions = {
+ .thread_create = rtems_bsd_extension_thread_create,
+ .thread_delete = rtems_bsd_extension_thread_delete
+};
static void
-rtems_bsd_thread_delete(void)
+rtems_bsd_threads_init(void *arg __unused)
{
- rtems_chain_control *chain = &rtems_bsd_thread_chain;
- rtems_chain_node *node = rtems_chain_first(chain);
- rtems_id id = rtems_task_self();
- struct thread *td = NULL;
+ rtems_id ext_id;
+ rtems_status_code sc;
+
+ sc = rtems_extension_create(
+ BSD_TASK_NAME,
+ &rtems_bsd_extensions,
+ &ext_id
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ BSD_PANIC("cannot create extension");
+ }
- while (!rtems_chain_is_tail(chain, node)) {
- struct thread *cur = (struct thread *) node;
+ rtems_bsd_extension_index = rtems_object_id_get_index(ext_id);
- if (cur->td_id == id) {
- td = cur;
- break;
- }
+ mtx_init(&FIXME_prison.pr_mtx, "prison lock", NULL, MTX_DEF | MTX_DUPOK);
- node = rtems_chain_next(node);
- }
+ FIXME_ucred.cr_prison = &FIXME_prison; /* jail(2) */
+ FIXME_ucred.cr_uidinfo = uifind(0);
+ FIXME_ucred.cr_ruidinfo = uifind(0);
+ FIXME_ucred.cr_ngroups = 1; /* group 0 */
- if (td != NULL) {
- rtems_chain_extract(&td->td_node);
+ FIXME_proc.p_ucred = crhold(&FIXME_ucred);
+ mtx_init(&FIXME_proc.p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK);
+ FIXME_proc.p_pid = getpid();
+ FIXME_proc.p_fibnum = 0;
+ FIXME_proc.p_fd = &FIXME_fd;
+ sx_init_flags(&FIXME_fd.fd_sx, "config SX thread lock", SX_DUPOK);
+}
- free(td, M_TEMP);
+SYSINIT(rtems_bsd_threads, SI_SUB_INTRINSIC, SI_ORDER_ANY, rtems_bsd_threads_init, NULL);
+
+static int
+rtems_bsd_thread_start(struct thread **td_ptr, void (*func)(void *), void *arg, int flags, int pages, const char *fmt, va_list ap)
+{
+ int eno = 0;
+ rtems_status_code sc;
+ rtems_id task_id;
+
+ BSD_ASSERT(pages >= 0);
+
+ sc = rtems_task_create(
+ BSD_TASK_NAME,
+ BSD_TASK_PRIORITY_NORMAL,
+ BSD_MINIMUM_TASK_STACK_SIZE + (size_t) pages * PAGE_SIZE,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &task_id
+ );
+ if (sc == RTEMS_SUCCESSFUL) {
+ struct thread *td = rtems_bsd_get_thread_by_id(task_id);
+
+ BSD_ASSERT(td != NULL);
+
+ vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap);
+
+ sc = rtems_task_start(task_id, (rtems_task_entry) func, (rtems_task_argument) arg);
+ BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
+
+ if (td_ptr != NULL) {
+ *td_ptr = td;
+ }
} else {
- BSD_PANIC("cannot find task entry");
+ eno = ENOMEM;
}
- rtems_task_delete(RTEMS_SELF);
+ return eno;
+}
- while (true) {
- /* Do nothing */
- }
+static __dead2 void
+rtems_bsd_thread_delete(void)
+{
+ rtems_task_delete(RTEMS_SELF);
+ BSD_PANIC("delete self failed");
}
void