threads: Delay thread start during initialization

The FreeBSD initialization is supposed to be single-threaded.
This commit is contained in:
Sebastian Huber 2013-11-13 16:52:02 +01:00
parent 7f1836cfe6
commit c2f6513a05

View File

@ -61,35 +61,39 @@ RTEMS_CHAIN_DEFINE_EMPTY(rtems_bsd_thread_chain);
static size_t rtems_bsd_extension_index; static size_t rtems_bsd_extension_index;
static CHAIN_DEFINE_EMPTY(rtems_bsd_thread_delay_start_chain);
static bool rtems_bsd_thread_ready_to_start;
struct thread * struct thread *
rtems_bsd_get_thread(const Thread_Control *thread) rtems_bsd_get_thread(const Thread_Control *thread)
{ {
return thread->extensions[rtems_bsd_extension_index]; return thread->extensions[rtems_bsd_extension_index];
} }
static struct thread * static Thread_Control *
rtems_bsd_get_thread_by_id(rtems_id task_id) rtems_bsd_get_thread_by_id(rtems_id task_id)
{ {
struct thread *td = NULL;
Thread_Control *thread; Thread_Control *thread;
Objects_Locations location; Objects_Locations location;
thread = _Thread_Get(task_id, &location); thread = _Thread_Get(task_id, &location);
switch (location) { switch (location) {
case OBJECTS_LOCAL: case OBJECTS_LOCAL:
td = rtems_bsd_get_thread(thread);
_Objects_Put(&thread->Object); _Objects_Put(&thread->Object);
break; break;
#if defined(RTEMS_MULTIPROCESSING) #if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE: case OBJECTS_REMOTE:
_Thread_Dispatch(); _Thread_Dispatch();
thread = NULL;
break; break;
#endif #endif
default: default:
thread = NULL;
break; break;
} }
return td; return thread;
} }
struct thread * struct thread *
@ -198,11 +202,13 @@ static const rtems_extensions_table rtems_bsd_extensions = {
}; };
static void static void
rtems_bsd_threads_init(void *arg __unused) rtems_bsd_threads_init_early(void *arg)
{ {
rtems_id ext_id; rtems_id ext_id;
rtems_status_code sc; rtems_status_code sc;
(void) arg;
sc = rtems_extension_create( sc = rtems_extension_create(
BSD_TASK_NAME, BSD_TASK_NAME,
&rtems_bsd_extensions, &rtems_bsd_extensions,
@ -215,10 +221,35 @@ rtems_bsd_threads_init(void *arg __unused)
rtems_bsd_extension_index = rtems_object_id_get_index(ext_id); rtems_bsd_extension_index = rtems_object_id_get_index(ext_id);
} }
SYSINIT(rtems_bsd_threads, SI_SUB_INTRINSIC, SI_ORDER_ANY, rtems_bsd_threads_init, NULL); static void
rtems_bsd_threads_init_late(void *arg)
{
Chain_Control *chain = &rtems_bsd_thread_delay_start_chain;
Chain_Node *node;
(void) arg;
while ((node = _Chain_Get_unprotected(chain)) != NULL) {
Thread_Control *thread = (Thread_Control *) node;
rtems_status_code sc;
sc = rtems_task_start(thread->Object.id, (rtems_task_entry)
thread->Start.entry_point, thread->Start.numeric_argument);
BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
}
rtems_bsd_thread_ready_to_start = true;
}
SYSINIT(rtems_bsd_threads_early, SI_SUB_INTRINSIC, SI_ORDER_ANY,
rtems_bsd_threads_init_early, NULL);
SYSINIT(rtems_bsd_threads_late, SI_SUB_RUN_SCHEDULER, SI_ORDER_ANY,
rtems_bsd_threads_init_late, NULL);
static int 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) 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; int eno = 0;
rtems_status_code sc; rtems_status_code sc;
@ -235,14 +266,28 @@ rtems_bsd_thread_start(struct thread **td_ptr, void (*func)(void *), void *arg,
&task_id &task_id
); );
if (sc == RTEMS_SUCCESSFUL) { if (sc == RTEMS_SUCCESSFUL) {
struct thread *td = rtems_bsd_get_thread_by_id(task_id); Thread_Control *thread = rtems_bsd_get_thread_by_id(task_id);
struct thread *td;
BSD_ASSERT(thread != NULL);
td = rtems_bsd_get_thread(thread);
BSD_ASSERT(td != NULL); BSD_ASSERT(td != NULL);
vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap); vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap);
sc = rtems_task_start(task_id, (rtems_task_entry) func, (rtems_task_argument) arg); if (rtems_bsd_thread_ready_to_start) {
BSD_ASSERT(sc == RTEMS_SUCCESSFUL); sc = rtems_task_start(task_id, (rtems_task_entry) func,
(rtems_task_argument) arg);
BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
} else {
thread->Start.entry_point = (Thread_Entry) func;
thread->Start.numeric_argument =
(Thread_Entry_numeric_type) arg;
_Chain_Append_unprotected(
&rtems_bsd_thread_delay_start_chain,
&thread->Object.Node);
}
if (td_ptr != NULL) { if (td_ptr != NULL) {
*td_ptr = td; *td_ptr = td;