[rtems-libbsd commit] Use extension to attach a struct thread to threads

Sebastian Huber sebh at rtems.org
Thu Oct 10 07:13:10 UTC 2013


Module:    rtems-libbsd
Branch:    master
Commit:    ab415f95a9ee784f0aa2131d237455ed6aad2dde
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=ab415f95a9ee784f0aa2131d237455ed6aad2dde

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Oct  9 08:56:49 2013 +0200

Use extension to attach a struct thread to threads

Add test thread01.

---

 Makefile                                        |   12 +
 freebsd-to-rtems.py                             |    1 +
 freebsd/sys/dev/usb/usb_process.c               |    8 +-
 freebsd/sys/dev/usb/usb_process.h               |    4 -
 freebsd/sys/kern/kern_intr.c                    |    3 +-
 freebsd/sys/sys/pcpu.h                          |    5 -
 freebsd/sys/sys/proc.h                          |    9 +-
 rtemsbsd/include/machine/pcpu.h                 |   42 +++-
 rtemsbsd/include/machine/rtems-bsd-config.h.in  |   13 -
 rtemsbsd/include/machine/rtems-bsd-thread.h     |   73 +++++
 rtemsbsd/rtems/rtems-bsd-init-with-irq.c        |    5 +-
 rtemsbsd/rtems/rtems-bsd-init.c                 |    1 +
 rtemsbsd/rtems/rtems-bsd-mutex.c                |    1 +
 rtemsbsd/rtems/rtems-bsd-panic.c                |   18 +-
 rtemsbsd/rtems/rtems-bsd-shell.c                |   15 +-
 rtemsbsd/rtems/rtems-bsd-thread.c               |  319 ++++++++++++-----------
 testsuite/include/rtems/bsd/test/default-init.h |    3 +-
 testsuite/swi01/init.c                          |    2 +
 testsuite/thread01/test_main.c                  |  304 +++++++++++++++++++++
 testsuite/timeout01/init.c                      |    2 +
 testsuite/usb01/init.c                          |    2 +
 21 files changed, 625 insertions(+), 217 deletions(-)

diff --git a/Makefile b/Makefile
index 10b335a..f710203 100644
--- a/Makefile
+++ b/Makefile
@@ -863,6 +863,18 @@ O_FILES += $(TEST_INIT01_O_FILES)
 D_FILES += $(TEST_INIT01_D_FILES)
 RUN_TESTS += $(TEST_INIT01)
 
+TEST_THREAD01 = testsuite/thread01/thread01.exe
+TEST_THREAD01_O_FILES =
+TEST_THREAD01_D_FILES =
+TEST_THREAD01_O_FILES += testsuite/thread01/test_main.o
+TEST_THREAD01_D_FILES += testsuite/thread01/test_main.d
+$(TEST_THREAD01): $(TEST_THREAD01_O_FILES) $(LIB)
+	$(LINK.c) $^ -lm -o $@
+TESTS += $(TEST_THREAD01)
+O_FILES += $(TEST_THREAD01_O_FILES)
+D_FILES += $(TEST_THREAD01_D_FILES)
+RUN_TESTS += $(TEST_THREAD01)
+
 ifeq ($(NEED_DUMMY_PIC_IRQ),yes)
 CFLAGS += -I rtems-dummy-pic-irq/include
 endif
diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py
index db43581..bb7cd59 100755
--- a/freebsd-to-rtems.py
+++ b/freebsd-to-rtems.py
@@ -2363,6 +2363,7 @@ tests.addTest('netshell01', ['test_main', 'shellconfig', 'ns_parser_vars'], Fals
 tests.addTest('swi01', ['init', 'swi_test'])
 tests.addTest('timeout01', ['init', 'timeout_test', 'timeout_helper'])
 tests.addTest('init01', ['test_main'])
+tests.addTest('thread01', ['test_main'])
 
 # Register all the Module instances with the Module Manager
 mm.addModule(rtems)
diff --git a/freebsd/sys/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c
index 67ddf69..8cb0047 100644
--- a/freebsd/sys/dev/usb/usb_process.c
+++ b/freebsd/sys/dev/usb/usb_process.c
@@ -99,11 +99,11 @@ usb_process(void *arg)
 {
 	struct usb_process *up = arg;
 	struct usb_proc_msg *pm;
-#ifndef __rtems__
 	struct thread *td;
 
 	/* adjust priority */
 	td = curthread;
+#ifndef __rtems__
 	thread_lock(td);
 	sched_prio(td, up->up_prio);
 	thread_unlock(td);
@@ -111,9 +111,7 @@ usb_process(void *arg)
 
 	mtx_lock(up->up_mtx);
 
-#ifndef __rtems__
 	up->up_curtd = td;
-#endif /* __rtems__ */
 
 	while (1) {
 
@@ -390,11 +388,7 @@ usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
 
 	mtx_assert(up->up_mtx, MA_OWNED);
 
-#ifndef __rtems__
 	if (up->up_curtd == curthread) {
-#else /* __rtems__ */
-	if (up->up_ptr->td_id == rtems_task_self()) {
-#endif /* __rtems__ */
 		/* Just remove the messages from the queue. */
 		if (pm0->pm_qentry.tqe_prev) {
 			TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
diff --git a/freebsd/sys/dev/usb/usb_process.h b/freebsd/sys/dev/usb/usb_process.h
index f9a3c38..b4159af 100644
--- a/freebsd/sys/dev/usb/usb_process.h
+++ b/freebsd/sys/dev/usb/usb_process.h
@@ -49,16 +49,12 @@ struct usb_process {
 	struct cv up_cv;
 	struct cv up_drain;
 
-#ifndef __rtems__
 #if (__FreeBSD_version >= 800000)
 	struct thread *up_ptr;
 #else
 	struct proc *up_ptr;
 #endif
 	struct thread *up_curtd;
-#else /* __rtems__ */
-	struct thread *up_ptr;
-#endif /* __rtems__ */
 	struct mtx *up_mtx;
 
 	usb_size_t up_msg_num;
diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c
index bc252c1..f86fa67 100644
--- a/freebsd/sys/kern/kern_intr.c
+++ b/freebsd/sys/kern/kern_intr.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
   #ifdef INTR_FILTER
     #error INTR_FILTER is currently not suppported with RTEMS
   #endif
+  #include <machine/rtems-bsd-thread.h>
   #define RTEMSBSD_SWI_WAKEUP_EVENT RTEMS_EVENT_31
 #endif /* __rtems__ */
 #ifdef DDB
@@ -924,7 +925,7 @@ intr_event_schedule_thread(struct intr_event *ie)
 	/* Send event to wake the thread up.
 	 * TODO: eventually replace event by a better mechanism
 	 */
-	rtems_status_code sc = rtems_event_send(td->td_id, RTEMSBSD_SWI_WAKEUP_EVENT);
+	rtems_status_code sc = rtems_event_send(rtems_bsd_get_task_id(td), RTEMSBSD_SWI_WAKEUP_EVENT);
 	BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 #endif /* __rtems__ */
 	thread_unlock(td);
diff --git a/freebsd/sys/sys/pcpu.h b/freebsd/sys/sys/pcpu.h
index e0eb23f..b3bbb16 100644
--- a/freebsd/sys/sys/pcpu.h
+++ b/freebsd/sys/sys/pcpu.h
@@ -201,11 +201,6 @@ SLIST_HEAD(cpuhead, pcpu);
 extern struct cpuhead cpuhead;
 extern struct pcpu *cpuid_to_pcpu[MAXCPU];
 
-#ifdef __rtems__
-struct thread *rtems_get_curthread(void);
-#define	curthread	rtems_get_curthread()
-#endif
-
 #define	curcpu		PCPU_GET(cpuid)
 #define	curproc		(curthread->td_proc)
 #ifndef curthread
diff --git a/freebsd/sys/sys/proc.h b/freebsd/sys/sys/proc.h
index cd10421..7bf640c 100644
--- a/freebsd/sys/sys/proc.h
+++ b/freebsd/sys/sys/proc.h
@@ -198,6 +198,11 @@ struct rusage_ext {
  * Thread context.  Processes may have multiple threads.
  */
 struct thread {
+#ifdef __rtems__
+	rtems_chain_node td_node;
+	Thread_Control *td_thread;
+	char td_name [16];
+#endif /* __rtems__ */
 #ifndef __rtems__
 	struct mtx	*volatile td_lock; /* replaces sched lock */
 #endif /* __rtems__ */
@@ -314,10 +319,6 @@ struct thread {
 	const char	*td_vnet_lpush;	/* (k) Debugging vnet push / pop. */
 	struct rusage_ext td_rux;	/* (t) Internal rusage information. */
 	struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */
-#else /* __rtems__ */
-	rtems_chain_node td_node;
-	rtems_id td_id;
-	char td_name [16];
 #endif /* __rtems__ */
 };
 
diff --git a/rtemsbsd/include/machine/pcpu.h b/rtemsbsd/include/machine/pcpu.h
index caf1385..b09f094 100644
--- a/rtemsbsd/include/machine/pcpu.h
+++ b/rtemsbsd/include/machine/pcpu.h
@@ -7,27 +7,48 @@
  */
 
 /*
- * 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 at embedded-brains.de>
  *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef _RTEMS_BSD_MACHINE_PCPU_H_
 #define _RTEMS_BSD_MACHINE_PCPU_H_
 
-#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_CONFIG_H_
-#error "the header file <freebsd/machine/rtems-bsd-config.h> must be included first"
-#endif
+struct thread;
+
+struct thread *
+rtems_bsd_get_curthread_or_wait_forever(void);
 
-#define curthread (( struct thread * )(( RTEMS_API_Control * )_Thread_Executing->API_Extensions[THREAD_API_RTEMS] )->Notepads[RTEMS_NOTEPAD_0] )
+struct thread *
+rtems_bsd_get_curthread_or_null(void);
+
+#define curthread rtems_bsd_get_curthread_or_wait_forever()
 
 extern struct pcpu *pcpup;
 
@@ -35,7 +56,4 @@ extern struct pcpu *pcpup;
 #define PCPU_GET(member) (0)
 #define PCPU_SET(member, val)
 
-//#define PCPU_GET(member)  (pcpup->pc_ ## member)
-//#define PCPU_SET(member, val) (pcpup->pc_ ## member = (val))
-
 #endif /* _RTEMS_BSD_MACHINE_PCPU_H_ */
diff --git a/rtemsbsd/include/machine/rtems-bsd-config.h.in b/rtemsbsd/include/machine/rtems-bsd-config.h.in
index 3990710..477a2cd 100644
--- a/rtemsbsd/include/machine/rtems-bsd-config.h.in
+++ b/rtemsbsd/include/machine/rtems-bsd-config.h.in
@@ -132,17 +132,6 @@ void rtems_bsd_assert_func(const char *file, int line, const char *func, const c
 
 /* General definitions */
 
-#define BSD_TASK_PRIORITY_NORMAL 120
-
-#define BSD_TASK_PRIORITY_TIMER 110
-
-#define BSD_TASK_PRIORITY_INTERRUPT 100
-
-#define BSD_TASK_PRIORITY_RESOURCE_OWNER 100
-
-/* FIXME */
-#define BSD_MINIMUM_TASK_STACK_SIZE ((size_t) 32 * 1024)
-
 #define M_RTEMS_HEAP 0
 
 #define BSD_MAXIMUM_SLEEP_QUEUES 32
@@ -157,8 +146,6 @@ extern rtems_chain_control rtems_bsd_condvar_chain;
 
 extern rtems_chain_control rtems_bsd_callout_chain;
 
-extern rtems_chain_control rtems_bsd_thread_chain;
-
 extern rtems_chain_control rtems_bsd_malloc_chain;
 
 /* CPU definitions */
diff --git a/rtemsbsd/include/machine/rtems-bsd-thread.h b/rtemsbsd/include/machine/rtems-bsd-thread.h
new file mode 100644
index 0000000..b8088b5
--- /dev/null
+++ b/rtemsbsd/include/machine/rtems-bsd-thread.h
@@ -0,0 +1,73 @@
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_machine
+ *
+ * @brief TODO.
+ */
+
+/*
+ * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _RTEMS_BSD_MACHINE_RTEMS_BSD_THREAD_H_
+#define _RTEMS_BSD_MACHINE_RTEMS_BSD_THREAD_H_
+
+#include <rtems/bsd/sys/param.h>
+#include <rtems/bsd/sys/types.h>
+#include <sys/proc.h>
+
+#include <rtems.h>
+
+#define BSD_TASK_NAME rtems_build_name('_', 'B', 'S', 'D')
+
+#define BSD_TASK_PRIORITY_NORMAL 120
+
+#define BSD_TASK_PRIORITY_TIMER 110
+
+#define BSD_TASK_PRIORITY_INTERRUPT 100
+
+#define BSD_TASK_PRIORITY_RESOURCE_OWNER 100
+
+/* FIXME */
+#define BSD_MINIMUM_TASK_STACK_SIZE ((size_t) 32 * 1024)
+
+extern rtems_chain_control rtems_bsd_thread_chain;
+
+struct thread *
+rtems_bsd_get_thread(const Thread_Control *thread);
+
+static inline rtems_id
+rtems_bsd_get_task_id(const struct thread *td)
+{
+	return td->td_thread->Object.id;
+}
+
+#endif /* _RTEMS_BSD_MACHINE_RTEMS_BSD_THREAD_H_ */
diff --git a/rtemsbsd/rtems/rtems-bsd-init-with-irq.c b/rtemsbsd/rtems/rtems-bsd-init-with-irq.c
index a663fe3..c2966d6 100644
--- a/rtemsbsd/rtems/rtems-bsd-init-with-irq.c
+++ b/rtemsbsd/rtems/rtems-bsd-init-with-irq.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 at embedded-brains.de>
@@ -38,6 +38,7 @@
  */
 
 #include <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
 
 #include <rtems/irq-extension.h>
 
diff --git a/rtemsbsd/rtems/rtems-bsd-init.c b/rtemsbsd/rtems/rtems-bsd-init.c
index 9e9fb1f..44262cb 100644
--- a/rtemsbsd/rtems/rtems-bsd-init.c
+++ b/rtemsbsd/rtems/rtems-bsd-init.c
@@ -38,6 +38,7 @@
  */
 
 #include <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
diff --git a/rtemsbsd/rtems/rtems-bsd-mutex.c b/rtemsbsd/rtems/rtems-bsd-mutex.c
index bc36419..fe01bc4 100644
--- a/rtemsbsd/rtems/rtems-bsd-mutex.c
+++ b/rtemsbsd/rtems/rtems-bsd-mutex.c
@@ -38,6 +38,7 @@
  */
 
 #include <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
 
 #include <rtems/score/objectimpl.h>
 #include <rtems/rtems/attrimpl.h>
diff --git a/rtemsbsd/rtems/rtems-bsd-panic.c b/rtemsbsd/rtems/rtems-bsd-panic.c
index 6b1d850..859c34e 100644
--- a/rtemsbsd/rtems/rtems-bsd-panic.c
+++ b/rtemsbsd/rtems/rtems-bsd-panic.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 at embedded-brains.de>
@@ -38,6 +38,7 @@
  */
 
 #include <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
@@ -50,18 +51,19 @@
 static void
 suspend_all_threads(void)
 {
-	rtems_chain_control *chain = &rtems_bsd_thread_chain;
-	rtems_chain_node *node = rtems_chain_first(chain);
+	const rtems_chain_control *chain = &rtems_bsd_thread_chain;
+	const rtems_chain_node *node = rtems_chain_immutable_first(chain);
 	rtems_id self = rtems_task_self();
 
 	while (!rtems_chain_is_tail(chain, node)) {
-		struct thread *td = (struct thread *) node;
+		const struct thread *td = (const struct thread *) node;
+		rtems_id id = rtems_bsd_get_task_id(td);
 
-		if (td->td_id != self && td->td_id != RTEMS_SELF) {
-			rtems_task_suspend(td->td_id);
+		if (id != self) {
+			rtems_task_suspend(id);
 		}
 
-		node = rtems_chain_next(node);
+		node = rtems_chain_immutable_next(node);
 	}
 
 	rtems_task_suspend(RTEMS_SELF);
diff --git a/rtemsbsd/rtems/rtems-bsd-shell.c b/rtemsbsd/rtems/rtems-bsd-shell.c
index fba191a..9e110e2 100644
--- a/rtemsbsd/rtems/rtems-bsd-shell.c
+++ b/rtemsbsd/rtems/rtems-bsd-shell.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 at embedded-brains.de>
@@ -38,6 +38,7 @@
  */
 
 #include <machine/rtems-bsd-config.h>
+#include <machine/rtems-bsd-thread.h>
 
 #include <rtems/bsd/sys/param.h>
 #include <rtems/bsd/sys/types.h>
@@ -105,17 +106,17 @@ rtems_bsd_dump_condvar(void)
 static void
 rtems_bsd_dump_thread(void)
 {
-	rtems_chain_control *chain = &rtems_bsd_thread_chain;
-	rtems_chain_node *node = rtems_chain_first(chain);
+	const rtems_chain_control *chain = &rtems_bsd_thread_chain;
+	const rtems_chain_node *node = rtems_chain_immutable_first(chain);
 
 	printf("thread dump:\n");
 
 	while (!rtems_chain_is_tail(chain, node)) {
-		struct thread *td = (struct thread *) node;
+		const struct thread *td = (const struct thread *) node;
 
-		printf("\t%s: 0x%08x\n", td->td_name, td->td_id);
+		printf("\t%s: 0x%08x\n", td->td_name, rtems_bsd_get_task_id(td));
 
-		node = rtems_chain_next(node);
+		node = rtems_chain_immutable_next(node);
 	}
 }
 
diff --git a/rtemsbsd/rtems/rtems-bsd-thread.c b/rtemsbsd/rtems/rtems-bsd-thread.c
index 357fb45..a0a78a5 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 at 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
diff --git a/testsuite/include/rtems/bsd/test/default-init.h b/testsuite/include/rtems/bsd/test/default-init.h
index 8e0dfc4..09f1f09 100644
--- a/testsuite/include/rtems/bsd/test/default-init.h
+++ b/testsuite/include/rtems/bsd/test/default-init.h
@@ -41,6 +41,8 @@ rtems_task Init(
 
 #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
 
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
+
 #define CONFIGURE_UNLIMITED_OBJECTS
 #define CONFIGURE_UNIFIED_WORK_AREAS
 
@@ -57,7 +59,6 @@ rtems_task Init(
 
 #include <machine/rtems-bsd-sysinit.h>
 
-#define CONFIGURE_NEED_NET
 /* only include FXP and PCI for i386/pc386 for debug on qemu (for now) */
 #if defined(i386)
   #define CONFIGURE_NEED_PCIB
diff --git a/testsuite/swi01/init.c b/testsuite/swi01/init.c
index 57d77f8..ee20665 100644
--- a/testsuite/swi01/init.c
+++ b/testsuite/swi01/init.c
@@ -63,6 +63,8 @@ static void Init(rtems_task_argument arg)
 
 #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
 
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
+
 #define CONFIGURE_UNLIMITED_OBJECTS
 
 #define CONFIGURE_UNIFIED_WORK_AREAS
diff --git a/testsuite/thread01/test_main.c b/testsuite/thread01/test_main.c
new file mode 100644
index 0000000..643a6ad
--- /dev/null
+++ b/testsuite/thread01/test_main.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/rtems-bsd-config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <rtems/bsd/sys/types.h>
+#include <rtems/bsd/sys/param.h>
+#include <sys/proc.h>
+#include <sys/kthread.h>
+#include <sys/errno.h>
+
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/threaddispatch.h>
+#include <rtems/score/wkspace.h>
+
+#define TEST_NAME "LIBBSD THREAD 1"
+
+#define TEST_KTHREAD_ADD ((void *) 0xdeadbeef)
+
+static rtems_id main_task_id;
+
+static char test_kproc_name[] = "kproc";
+
+static struct kproc_desc test_kproc_start_desc;
+
+static char test_kthread_name[] = "kthread";
+
+static struct kthread_desc test_kthread_start_desc;
+
+static void
+test_curthread(const char *name)
+{
+	struct thread *td_0 = rtems_bsd_get_curthread_or_null();
+	struct thread *td_1 = rtems_bsd_get_curthread_or_wait_forever();
+	struct thread *td_2 = curthread;
+
+	assert(td_0 != NULL);
+	assert(td_0 == td_1);
+	assert(td_0 == td_2);
+	assert(strcmp(&td_0->td_name[0], name) == 0);
+}
+
+static void
+wake_up_main_thread(void)
+{
+	rtems_status_code sc;
+
+	sc = rtems_event_transient_send(main_task_id);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+wait_for_worker_thread(void)
+{
+	rtems_status_code sc;
+
+	sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+non_bsd_thread(rtems_task_argument arg)
+{
+	rtems_status_code sc;
+
+	test_curthread("");
+	wake_up_main_thread();
+
+	sc = rtems_task_delete(RTEMS_SELF);
+	assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+test_non_bsd_thread(void)
+{
+	rtems_status_code sc;
+	rtems_id task_id;
+	rtems_resource_snapshot snapshot;
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	sc = rtems_task_create(
+		rtems_build_name('T', 'A', 'S', 'K'),
+		RTEMS_MINIMUM_PRIORITY,
+		RTEMS_MINIMUM_STACK_SIZE,
+		RTEMS_DEFAULT_MODES,
+		RTEMS_DEFAULT_ATTRIBUTES,
+		&task_id
+	);
+	assert(sc == RTEMS_SUCCESSFUL);
+
+	sc = rtems_task_start(task_id, non_bsd_thread, 0);
+	assert(sc == RTEMS_SUCCESSFUL);
+
+	wait_for_worker_thread();
+
+	assert(rtems_resource_snapshot_check(&snapshot));
+}
+
+static void
+test_kproc_start_proc(void)
+{
+	test_curthread(&test_kproc_name[0]);
+	wake_up_main_thread();
+	kproc_exit(0);
+}
+
+static void
+test_kproc_start(void)
+{
+	rtems_resource_snapshot snapshot;
+	struct proc *pr = NULL;
+	struct kproc_desc *kpd = &test_kproc_start_desc;
+
+	puts("test kproc_start()");
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	kpd->arg0 = &test_kproc_name[0];
+	kpd->func = test_kproc_start_proc,
+	kpd->global_procpp = ≺
+
+	kproc_start(kpd);
+	wait_for_worker_thread();
+
+	assert(pr != NULL);
+
+	assert(rtems_resource_snapshot_check(&snapshot));
+}
+
+static void
+test_kthread_start_thread(void)
+{
+	test_curthread(&test_kthread_name[0]);
+	wake_up_main_thread();
+	kthread_exit();
+}
+
+static void
+test_kthread_start(void)
+{
+	rtems_resource_snapshot snapshot;
+	struct thread *td = NULL;
+	struct kthread_desc *ktd = &test_kthread_start_desc;
+
+	puts("test kthread_start()");
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	ktd->arg0 = &test_kthread_name[0];
+	ktd->func = test_kthread_start_thread,
+	ktd->global_threadpp = &td;
+
+	kthread_start(ktd);
+	wait_for_worker_thread();
+
+	assert(td != NULL);
+
+	assert(rtems_resource_snapshot_check(&snapshot));
+}
+
+static void
+test_kthread_add_thread(void *arg)
+{
+	test_curthread(&test_kthread_name[0]);
+
+	assert(arg == TEST_KTHREAD_ADD);
+
+	wake_up_main_thread();
+	kthread_exit();
+}
+
+static void
+test_kthread_add(void)
+{
+	rtems_resource_snapshot snapshot;
+	uintptr_t take_away;
+	void *greedy;
+
+	puts("test kthread_add()");
+
+	greedy = rtems_workspace_greedy_allocate_all_except_largest(&take_away);
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	assert(rtems_configuration_get_unified_work_area());
+
+	while (take_away > 0) {
+		struct thread *td = NULL;
+		void *away;
+		int eno;
+
+		/*
+		 * FIXME: This direct workspace access is a hack to get
+		 * reasonable test run times with RTEMS_DEBUG enabled.
+		 */
+		_Thread_Disable_dispatch();
+		away = _Workspace_Allocate(take_away);
+		_Thread_Enable_dispatch();
+
+		eno = kthread_add(
+			test_kthread_add_thread,
+			TEST_KTHREAD_ADD,
+			NULL,
+			&td,
+			0,
+			0,
+			"%s",
+			&test_kthread_name[0]
+		);
+
+		_Thread_Disable_dispatch();
+		_Workspace_Free(away);
+		_Thread_Enable_dispatch();
+
+		if (eno == 0) {
+			wait_for_worker_thread();
+			assert(td != NULL);
+
+			take_away = 0;
+		} else {
+			assert(eno == ENOMEM);
+			assert(rtems_resource_snapshot_check(&snapshot));
+
+			--take_away;
+		}
+	}
+
+	rtems_workspace_greedy_free(greedy);
+}
+
+static void
+test_rtems_bsd_get_curthread_or_null(void)
+{
+	rtems_resource_snapshot snapshot;
+	void *greedy;
+
+	puts("test rtems_bsd_get_curthread_or_null()");
+
+	rtems_resource_snapshot_take(&snapshot);
+
+	greedy = rtems_workspace_greedy_allocate(NULL, 0);
+	assert(rtems_bsd_get_curthread_or_null() == NULL);
+	rtems_workspace_greedy_free(greedy);
+
+	rtems_resource_snapshot_take(&snapshot);
+}
+
+static void
+test_main(void)
+{
+	rtems_status_code sc;
+	rtems_task_priority prio = RTEMS_MAXIMUM_PRIORITY - 1;
+
+	main_task_id = rtems_task_self();
+
+	sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
+	assert(sc == RTEMS_SUCCESSFUL);
+
+	test_non_bsd_thread();
+	test_kproc_start();
+	test_kthread_start();
+	test_kthread_add();
+	test_rtems_bsd_get_curthread_or_null();
+
+	puts("*** END OF " TEST_NAME " TEST ***");
+	exit(0);
+}
+
+#include <rtems/bsd/test/default-init.h>
diff --git a/testsuite/timeout01/init.c b/testsuite/timeout01/init.c
index e632bb0..4afddc7 100644
--- a/testsuite/timeout01/init.c
+++ b/testsuite/timeout01/init.c
@@ -68,6 +68,8 @@ static void Init(rtems_task_argument arg)
 
 #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
 
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
+
 #define CONFIGURE_UNLIMITED_OBJECTS
 
 #define CONFIGURE_UNIFIED_WORK_AREAS
diff --git a/testsuite/usb01/init.c b/testsuite/usb01/init.c
index 517d154..ed579a1 100644
--- a/testsuite/usb01/init.c
+++ b/testsuite/usb01/init.c
@@ -295,6 +295,8 @@ static void Init(rtems_task_argument arg)
 #define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (WORKER_COUNT * 512)
 #define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 0
 
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
+
 #define CONFIGURE_UNLIMITED_OBJECTS
 
 #define CONFIGURE_UNIFIED_WORK_AREAS




More information about the vc mailing list