From 7b47f57c871da92ea81d28a18f91fae04f3072b3 Mon Sep 17 00:00:00 2001
From: batt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Date: Mon, 29 Mar 2010 13:55:34 +0000
Subject: [PATCH] Merge from trunk.

git-svn-id: https://src.develer.com/svnoss/bertos/branches/2.4@3296 38d2e660-2303-0410-9eaa-f027e97ec537
---
 bertos/cpu/arm/drv/adc_at91.c             |   2 +-
 bertos/cpu/arm/info/at91sam7.common       |   2 +-
 bertos/cpu/avr/drv/adc_avr.c              |   2 +-
 bertos/drv/ser.c                          |   4 +
 bertos/drv/ser.h                          |  16 +--
 bertos/kern/coop.c                        |  32 +++++-
 bertos/kern/preempt.c                     |  24 ++++-
 bertos/kern/proc.c                        |  34 +------
 bertos/kern/proc.h                        |   9 +-
 bertos/kern/proc_p.h                      |  31 +++++-
 bertos/kern/proc_test.c                   |   2 +-
 bertos/kern/sem.c                         |   9 +-
 bertos/kern/signal.c                      | 117 +++++++++++++++-------
 bertos/kern/signal.h                      |  11 +-
 bertos/kern/signal_test.c                 |  43 ++++----
 bertos/mware/event.c                      |   2 +-
 examples/at91sam7/at91sam7.c              |   9 +-
 examples/at91sam7/at91sam7s.mk            |   1 +
 examples/at91sam7/at91sam7x.mk            |   1 +
 examples/avr-kern/avr-kern.mk             |   1 +
 examples/avr-kern/main.c                  |   2 +
 examples/benchmark/kernel-core_avr/main.c |   2 +-
 examples/benchmark/kernel-only_arm/main.c |   2 +-
 wizard/BWizardPage.py                     |   6 +-
 wizard/bertos.py                          |  14 +--
 wizard/bertos_utils.py                    |   8 +-
 wizard/const.py                           |   8 ++
 wizard/exception_handler.py               |   3 +
 wizard/plugins/codelite.py                |   4 +-
 29 files changed, 272 insertions(+), 129 deletions(-)

diff --git a/bertos/cpu/arm/drv/adc_at91.c b/bertos/cpu/arm/drv/adc_at91.c
index 7fd50ddf..fadaa4be 100644
--- a/bertos/cpu/arm/drv/adc_at91.c
+++ b/bertos/cpu/arm/drv/adc_at91.c
@@ -86,7 +86,7 @@
 	 */
 	static DECLARE_ISR(adc_conversion_end_irq)
 	{
-		sig_signal(adc_process, SIG_ADC_COMPLETE);
+		sig_post(adc_process, SIG_ADC_COMPLETE);
 
 		/* Inform hw that we have served the IRQ */
 		AIC_EOICR = 0;
diff --git a/bertos/cpu/arm/info/at91sam7.common b/bertos/cpu/arm/info/at91sam7.common
index 3088ccff..00f3277b 100644
--- a/bertos/cpu/arm/info/at91sam7.common
+++ b/bertos/cpu/arm/info/at91sam7.common
@@ -78,7 +78,7 @@ MK_STOPDEBUG_SCRIPT = PRG_SCRIPTS_DIR + "arm/stopopenocd.sh"
 GDB_INIT_SCRIPT = PRG_SCRIPTS_DIR + "arm/openocd/gdbinit-sam7"
 
 # Common GCC flags.
-MK_CPU_CPPAFLAGS = "-O0 -g -gdwarf-2 -g -gen-debug"
+MK_CPU_CPPAFLAGS = "-g -gdwarf-2"
 MK_CPU_CPPFLAGS = "-O0 -g3 -gdwarf-2 -fverbose-asm -I" + CPU_DIR + "arm/"
 MK_CPU_LDFLAGS = "-nostartfiles -Wl,--no-warn-mismatch"
 
diff --git a/bertos/cpu/avr/drv/adc_avr.c b/bertos/cpu/avr/drv/adc_avr.c
index 20aa2a19..0aae6743 100644
--- a/bertos/cpu/avr/drv/adc_avr.c
+++ b/bertos/cpu/avr/drv/adc_avr.c
@@ -89,7 +89,7 @@
 	 */
 	ISR(ADC_vect)
 	{
-		sig_signal(adc_process, SIG_ADC_COMPLETE);
+		sig_post(adc_process, SIG_ADC_COMPLETE);
 	}
 #endif /* CONFIG_KERN */
 
diff --git a/bertos/drv/ser.c b/bertos/drv/ser.c
index a684ebba..dac277b0 100644
--- a/bertos/drv/ser.c
+++ b/bertos/drv/ser.c
@@ -410,6 +410,8 @@ static struct KFile *ser_reopen(struct KFile *fd)
 
 /**
  * Init serial driver for \a unit.
+ *
+ * Use values SER_UARTn as values for \a unit.
  */
 void ser_init(struct Serial *fds, unsigned int unit)
 {
@@ -476,6 +478,8 @@ static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
 /**
  * Init SPI serial driver \a unit in master mode.
  *
+ * Use SER_SPIn for \a unit parameter.
+ *
  * This interface implements the SPI master protocol over a serial SPI
  * driver. This is needed because normal serial driver send/receive data
  * at the same time. SPI slaves like memories and other peripherals
diff --git a/bertos/drv/ser.h b/bertos/drv/ser.h
index c264811e..fe05b4d5 100644
--- a/bertos/drv/ser.h
+++ b/bertos/drv/ser.h
@@ -62,10 +62,10 @@
 	#define SERRF_TXTIMEOUT      BV(2)  /**< Transmit timeout */
 
 	/* Hardware errors */
-	#define SERRF_RXSROVERRUN    0      /**< Unsupported in emulated serial port. */
-	#define SERRF_FRAMEERROR     0      /**< Unsupported in emulated serial port. */
-	#define SERRF_PARITYERROR    0      /**< Unsupported in emulated serial port. */
-	#define SERRF_NOISEERROR     0      /**< Unsupported in emulated serial port. */
+	#define SERRF_RXSROVERRUN    0      /**< Rx shift register overrun, unsupported in emulated serial port. */
+	#define SERRF_FRAMEERROR     0      /**< Stop bit missing, unsupported in emulated serial port. */
+	#define SERRF_PARITYERROR    0      /**< Parity error, unsupported in emulated serial port. */
+	#define SERRF_NOISEERROR     0      /**< Noise error, unsupported in emulated serial port. */
 
 	enum
 	{
@@ -93,8 +93,8 @@
 	| SERRF_RXSROVERRUN \
 	| SERRF_PARITYERROR \
 	| SERRF_FRAMEERROR \
-	| SERRF_NOISEERROR)
-#define SERRF_TX  (SERRF_TXTIMEOUT)
+	| SERRF_NOISEERROR)       /**< All possible rx errors */
+#define SERRF_TX  (SERRF_TXTIMEOUT)  /**< All possible tx errors */
 /*\}*/
 
 /**
@@ -212,8 +212,8 @@ void spimaster_init(Serial *fds, unsigned int unit);
  *
  * \{
  */
-#define ser_getstatus(h)    ((h)->status)
-#define ser_setstatus(h, x) ((h)->status = (x))
+#define ser_getstatus(serial)    ((serial)->status)
+#define ser_setstatus(serial, new_status) ((serial)->status = (new_status))
 /* \} */
 
 #endif /* DRV_SER_H */
diff --git a/bertos/kern/coop.c b/bertos/kern/coop.c
index 1b2e1bb9..542ed678 100644
--- a/bertos/kern/coop.c
+++ b/bertos/kern/coop.c
@@ -57,14 +57,42 @@
  */
 void coop_yield(void);
 void coop_switch(void);
+void coop_wakeup(Process *proc);
 
+/**
+ * Give the control of the CPU to another process.
+ *
+ * \note Assume the current process has been already added to a wait queue.
+ *
+ * \warning This should be considered an internal kernel function, even if it
+ * is allowed, usage from application code is strongly discouraged.
+ */
 void coop_switch(void)
 {
-	IRQ_ASSERT_ENABLED();
-
 	ATOMIC(proc_schedule());
 }
 
+/**
+ * Immediately wakeup a process, dispatching it to the CPU.
+ */
+void coop_wakeup(Process *proc)
+{
+	ASSERT(proc_preemptAllowed());
+	ASSERT(current_process);
+	IRQ_ASSERT_DISABLED();
+
+	if (prio_proc(proc) >= prio_curr())
+	{
+		Process *old_process = current_process;
+
+		SCHED_ENQUEUE(current_process);
+		current_process = proc;
+		proc_switchTo(current_process, old_process);
+	}
+	else
+		SCHED_ENQUEUE_HEAD(proc);
+}
+
 /**
  * Co-operative context switch
  */
diff --git a/bertos/kern/preempt.c b/bertos/kern/preempt.c
index f77dd85e..1cb5e5a0 100644
--- a/bertos/kern/preempt.c
+++ b/bertos/kern/preempt.c
@@ -121,6 +121,7 @@ void preempt_yield(void);
 int preempt_needPreempt(void);
 void preempt_preempt(void);
 void preempt_switch(void);
+void preempt_wakeup(Process *proc);
 void preempt_init(void);
 
 /**
@@ -171,11 +172,32 @@ void preempt_preempt(void)
 void preempt_switch(void)
 {
 	ASSERT(proc_preemptAllowed());
-	IRQ_ASSERT_ENABLED();
 
 	ATOMIC(preempt_schedule());
 }
 
+/**
+ * Immediately wakeup a process, dispatching it to the CPU.
+ */
+void preempt_wakeup(Process *proc)
+{
+	ASSERT(proc_preemptAllowed());
+	ASSERT(current_process);
+	IRQ_ASSERT_DISABLED();
+
+	if (prio_proc(proc) >= prio_curr())
+	{
+		Process *old_process = current_process;
+
+		SCHED_ENQUEUE(current_process);
+		_proc_quantum = CONFIG_KERN_QUANTUM;
+		current_process = proc;
+		proc_switchTo(current_process, old_process);
+	}
+	else
+		SCHED_ENQUEUE_HEAD(proc);
+}
+
 /**
  * Voluntarily release the CPU.
  */
diff --git a/bertos/kern/proc.c b/bertos/kern/proc.c
index 623c1d3f..acaf4220 100644
--- a/bertos/kern/proc.c
+++ b/bertos/kern/proc.c
@@ -62,14 +62,6 @@
 
 #define PROC_SIZE_WORDS (ROUND_UP2(sizeof(Process), sizeof(cpu_stack_t)) / sizeof(cpu_stack_t))
 
-/**
- * CPU dependent context switching routines.
- *
- * Saving and restoring the context on the stack is done by a CPU-dependent
- * support routine which usually needs to be written in assembly.
- */
-EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp);
-
 /*
  * The scheduer tracks ready processes by enqueuing them in the
  * ready list.
@@ -428,15 +420,6 @@ void proc_exit(void)
 	ASSERT(0);
 }
 
-
-/**
- * Get the pointer to the user data of the current process
- */
-iptr_t proc_currentUserData(void)
-{
-	return current_process->user_data;
-}
-
 /**
  * Call the scheduler and eventually replace the current running process.
  */
@@ -470,22 +453,7 @@ void proc_schedule(void)
 		MEMORY_BARRIER;
 		IRQ_DISABLE;
 	}
-	/*
-	 * Optimization: don't switch contexts when the active process has not
-	 * changed.
-	 */
-	if (LIKELY(current_process != old_process)) {
-		cpu_stack_t *dummy;
-
-		/*
-		 * Save context of old process and switch to new process. If
-		 * there is no old process, we save the old stack pointer into
-		 * a dummy variable that we ignore. In fact, this happens only
-		 * when the old process has just exited.
-		 */
-		asm_switch_context(&current_process->stack,
-				old_process ? &old_process->stack : &dummy);
-	}
+	proc_switchTo(current_process, old_process);
 	/* This RET resumes the execution on the new process */
 	LOG_INFO("resuming %p:%s\n", current_process, proc_currentName());
 }
diff --git a/bertos/kern/proc.h b/bertos/kern/proc.h
index 390099da..bacd052b 100644
--- a/bertos/kern/proc.h
+++ b/bertos/kern/proc.h
@@ -148,6 +148,7 @@ void proc_exit(void);
 void proc_yield(void);
 void proc_preempt(void);
 int proc_needPreempt(void);
+void proc_wakeup(Process *proc);
 
 /**
  * Dummy function that defines unimplemented scheduler class methods.
@@ -167,6 +168,7 @@ INLINE void __proc_noop(void)
 	 * Preemptive scheduler: private methods.
 	 */
 	#define preempt_switch		proc_switch
+	#define preempt_wakeup		proc_wakeup
 #else
 	/**
 	 * Co-operative scheduler: public methods.
@@ -178,6 +180,7 @@ INLINE void __proc_noop(void)
 	 * Co-operative scheduler: private methods.
 	 */
 	#define coop_switch		proc_switch
+	#define coop_wakeup		proc_wakeup
 #endif
 
 void proc_rename(struct Process *proc, const char *name);
@@ -191,7 +194,11 @@ const char *proc_currentName(void);
  * the returned pointer to the correct type.
  * \return Pointer to the user data of the current process.
  */
-iptr_t proc_currentUserData(void);
+INLINE iptr_t proc_currentUserData(void)
+{
+	extern struct Process *current_process;
+	return current_process->user_data;
+}
 
 int proc_testSetup(void);
 int proc_testRun(void);
diff --git a/bertos/kern/proc_p.h b/bertos/kern/proc_p.h
index 27d65fe2..85cb758f 100644
--- a/bertos/kern/proc_p.h
+++ b/bertos/kern/proc_p.h
@@ -50,6 +50,30 @@
 
 #include <kern/proc.h>   // struct Process
 
+/**
+ * CPU dependent context switching routines.
+ *
+ * Saving and restoring the context on the stack is done by a CPU-dependent
+ * support routine which usually needs to be written in assembly.
+ */
+EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp);
+
+/*
+ * Save context of old process and switch to new process.
+  */
+INLINE void proc_switchTo(Process *next, Process *prev)
+{
+	cpu_stack_t *dummy;
+
+	if (UNLIKELY(next == prev))
+		return;
+	/*
+	 * If there is no old process, we save the old stack pointer into a
+	 * dummy variable that we ignore.  In fact, this happens only when the
+	 * old process has just exited.
+	 */
+	asm_switch_context(&next->stack, prev ? &prev->stack : &dummy);
+}
 
 /**
  * \name Flags for Process.flags.
@@ -72,7 +96,8 @@ extern REGISTER List     proc_ready_list;
 #if CONFIG_KERN_PRI
 	#define prio_next()	(LIST_EMPTY(&proc_ready_list) ? INT_MIN : \
 					((PriNode *)LIST_HEAD(&proc_ready_list))->pri)
-	#define prio_curr()	(current_process->link.pri)
+	#define prio_proc(proc)	(proc->link.pri)
+	#define prio_curr()	prio_proc(current_process)
 
 	#define SCHED_ENQUEUE_INTERNAL(proc) \
 			LIST_ENQUEUE(&proc_ready_list, &(proc)->link)
@@ -80,6 +105,7 @@ extern REGISTER List     proc_ready_list;
 			LIST_ENQUEUE_HEAD(&proc_ready_list, &(proc)->link)
 #else
 	#define prio_next()	0
+	#define prio_proc(proc)	0
 	#define prio_curr()	0
 
 	#define SCHED_ENQUEUE_INTERNAL(proc) ADDTAIL(&proc_ready_list, &(proc)->link)
@@ -153,6 +179,9 @@ void proc_switch(void);
 /* Low level scheduling routine. */
 void proc_schedule(void);
 
+/* Low level context switch routine. */
+void proc_switchTo(Process *next, Process *prev);
+
 /* Initialize a scheduler class. */
 void proc_schedInit(void);
 
diff --git a/bertos/kern/proc_test.c b/bertos/kern/proc_test.c
index b8de22d7..b2319faa 100644
--- a/bertos/kern/proc_test.c
+++ b/bertos/kern/proc_test.c
@@ -296,7 +296,7 @@ static int preempt_worker_test(void)
 { \
 	struct Process *main_proc = (struct Process *) proc_currentUserData(); \
 	kputs("> Process: " #num "\n"); \
-	sig_signal(main_proc, SIG_USER##num); \
+	sig_send(main_proc, SIG_USER##num); \
 }
 
 // Default priority is 0
diff --git a/bertos/kern/sem.c b/bertos/kern/sem.c
index 53ef4cc1..3c645e95 100644
--- a/bertos/kern/sem.c
+++ b/bertos/kern/sem.c
@@ -157,6 +157,8 @@ void sem_obtain(struct Semaphore *s)
  */
 void sem_release(struct Semaphore *s)
 {
+	Process *proc = NULL;
+
 	proc_forbid();
 	sem_verify(s);
 
@@ -168,8 +170,6 @@ void sem_release(struct Semaphore *s)
 	 */
 	if (--s->nest_count == 0)
 	{
-		Process *proc;
-
 		/* Disown semaphore */
 		s->owner = NULL;
 
@@ -178,9 +178,10 @@ void sem_release(struct Semaphore *s)
 		{
 			s->nest_count = 1;
 			s->owner = proc;
-			ATOMIC(SCHED_ENQUEUE(proc));
 		}
 	}
-
 	proc_permit();
+
+	if (proc)
+		ATOMIC(proc_wakeup(proc));
 }
diff --git a/bertos/kern/signal.c b/bertos/kern/signal.c
index 19941f94..71ccf67a 100644
--- a/bertos/kern/signal.c
+++ b/bertos/kern/signal.c
@@ -65,10 +65,38 @@
  * particular event has occurred, because the same signal may be
  * delivered twice before the process can notice.
  *
- * Any execution context, including an interrupt handler, can deliver
- * a signal to a process using sig_signal().  Multiple independent signals
- * may be delivered at once with a single invocation of sig_signal(),
- * although this is rarely useful.
+ * Signals can be delivered synchronously via sig_send() or asynchronously via
+ * sig_post().
+ *
+ * In the synchronous case the process is awakened if it was waiting for any
+ * signal and immediately dispatched for execution via a direct context switch,
+ * if its priority is greater than the running process.
+ *
+ * <pre>
+ * - Synchronous-signal delivery:
+ *
+ *     [P1]____sig_send()____proc_wakeup()____[P2]
+ * </pre>
+ *
+ * In the asynchronous case, the process is scheduled for execution as a
+ * consequence of the delivery, but it will be dispatched by the scheduler as
+ * usual, according to the scheduling policy.
+ *
+ * <pre>
+ * - Asynchronous-signal delivery:
+ *
+ *     [P1]____sig_post()____[P1]____proc_schedule()____[P2]
+ * </pre>
+ *
+ * In this way, any execution context, including an interrupt handler, can
+ * deliver a signal to a process. However, synchronous signal delivery from a
+ * non-sleepable context (like an interrupt handler) is forbidden in order to
+ * avoid potential deadlock conditions. Instead, sig_post() can be used from
+ * any context, expecially from interrupt context or when the preemption is
+ * disabled.
+ *
+ * Multiple independent signals may be delivered at once with a single
+ * invocation of sig_send() or sig_post(), although this is rarely useful.
  *
  * \section signal_allocation Signal Allocation
  *
@@ -146,13 +174,13 @@ sigmask_t sig_wait(sigmask_t sigs)
 	ASSERT(proc_preemptAllowed());
 
 	/*
-	 * This is subtle: there's a race condition where a concurrent
-	 * process or an interrupt may call sig_signal() to set a bit in
-	 * Process.sig_recv just after we have checked for it, but before
-	 * we've set Process.sig_wait to let them know we want to be awaken.
+	 * This is subtle: there's a race condition where a concurrent process
+	 * or an interrupt may call sig_send()/sig_post() to set a bit in
+	 * Process.sig_recv just after we have checked for it, but before we've
+	 * set Process.sig_wait to let them know we want to be awaken.
 	 *
-	 * In this case, we'd deadlock with the signal bit already set
-	 * and the process never being reinserted into the ready list.
+	 * In this case, we'd deadlock with the signal bit already set and the
+	 * process never being reinserted into the ready list.
 	 */
 	IRQ_DISABLE;
 
@@ -165,20 +193,12 @@ sigmask_t sig_wait(sigmask_t sigs)
 		 */
 		current_process->sig_wait = sigs;
 
-		/*
-		 * Go to sleep and proc_switch() to another process.
-		 *
-		 * We re-enable IRQs because proc_switch() does not
-		 * guarantee to save and restore the interrupt mask.
-		 */
-		IRQ_ENABLE;
+		/* Go to sleep and proc_switch() to another process. */
 		proc_switch();
-		IRQ_DISABLE;
-
 		/*
 		 * When we come back here, the wait mask must have been
-		 * cleared by someone through sig_signal(), and at least
-		 * one of the signals we were expecting must have been
+		 * cleared by someone through sig_send()/sig_post(), and at
+		 * least one of the signals we were expecting must have been
 		 * delivered to us.
 		 */
 		ASSERT(!current_process->sig_wait);
@@ -227,18 +247,13 @@ sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout)
 
 #endif // CONFIG_TIMER_EVENTS
 
-
-/**
- * Send the signals \a sigs to the process \a proc.
- * The process will be awoken if it was waiting for any of them.
- *
- * \note This call is interrupt safe.
- */
-void sig_signal(Process *proc, sigmask_t sigs)
+INLINE void __sig_signal(Process *proc, sigmask_t sigs, bool wakeup)
 {
 	cpu_flags_t flags;
 
-	/* See comment in sig_wait() for why this protection is necessary */
+	if (UNLIKELY(proc == current_process))
+		return;
+
 	IRQ_SAVE_DISABLE(flags);
 
 	/* Set the signals */
@@ -247,17 +262,43 @@ void sig_signal(Process *proc, sigmask_t sigs)
 	/* Check if process needs to be awoken */
 	if (proc->sig_recv & proc->sig_wait)
 	{
-		/*
-		 * Wake up process and enqueue in ready list.
-		 *
-		 * Move this process to the head of the ready list, so that it
-		 * will be chosen at the next scheduling point.
-		 */
 		proc->sig_wait = 0;
-		SCHED_ENQUEUE_HEAD(proc);
+		if (wakeup)
+			proc_wakeup(proc);
+		else
+			SCHED_ENQUEUE_HEAD(proc);
 	}
-
 	IRQ_RESTORE(flags);
 }
 
+/**
+ * Send the signals \a sigs to the process \a proc and immeditaly dispatch it
+ * for execution.
+ *
+ * The process will be awoken if it was waiting for any of them and immediately
+ * dispatched for execution.
+ *
+ * \note This function can't be called from IRQ context, use sig_post()
+ * instead.
+ */
+void sig_send(Process *proc, sigmask_t sigs)
+{
+	ASSERT_USER_CONTEXT();
+	IRQ_ASSERT_ENABLED();
+	ASSERT(proc_preemptAllowed());
+
+	__sig_signal(proc, sigs, true);
+}
+
+/**
+ * Send the signals \a sigs to the process \a proc.
+ * The process will be awoken if it was waiting for any of them.
+ *
+ * \note This call is interrupt safe.
+ */
+void sig_post(Process *proc, sigmask_t sigs)
+{
+	__sig_signal(proc, sigs, false);
+}
+
 #endif /* CONFIG_KERN_SIGNALS */
diff --git a/bertos/kern/signal.h b/bertos/kern/signal.h
index 9e6a9b09..bef44a9e 100644
--- a/bertos/kern/signal.h
+++ b/bertos/kern/signal.h
@@ -53,7 +53,16 @@ struct Process;
 
 /* Inter-process Communication services */
 sigmask_t sig_check(sigmask_t sigs);
-void sig_signal(struct Process *proc, sigmask_t sig);
+void sig_send(struct Process *proc, sigmask_t sig);
+void sig_post(struct Process *proc, sigmask_t sig);
+/*
+ * XXX: this is provided for backword compatibility, consider to make this
+ * deprecated for the future.
+ */
+INLINE void sig_signal(struct Process *proc, sigmask_t sig)
+{
+	sig_post(proc, sig);
+}
 sigmask_t sig_wait(sigmask_t sigs);
 sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout);
 
diff --git a/bertos/kern/signal_test.c b/bertos/kern/signal_test.c
index 484c0338..3b5ff1cb 100644
--- a/bertos/kern/signal_test.c
+++ b/bertos/kern/signal_test.c
@@ -76,29 +76,43 @@ sigmask_t sig_to_slave;
  * These macros generate the code needed to create the test process functions.
  */
 #define PROC_TEST_SLAVE(index, signal) \
-static void NORETURN proc_signalTest##index(void) \
+static void proc_signalTest##index(void) \
 { \
-	for(;;) \
-	{ \
-		kputs("> Slave [" #index "]: Wait signal [" #signal "]\n"); \
-		sig_wait(signal); \
-		kputs("> Slave [" #index "]: send signal [" #signal "]\n"); \
-		sig_signal(proc_currentUserData(), signal); \
-	} \
+	kputs("> Slave [" #index "]: Wait signal [" #signal "]\n"); \
+	sig_wait(signal); \
+	kputs("> Slave [" #index "]: send signal [" #signal "]\n"); \
+	sig_send(proc_currentUserData(), signal); \
 }
 
 #define MAIN_CHECK_SIGNAL(index, slave) \
 	do { \
 		kprintf("> Main: send signal [%d]\n", test_signal[index]); \
-		sig_signal(slave, test_signal[index]); \
+		sig_send(slave, test_signal[index]); \
 		kprintf("> Main: wait signal [%d]\n", test_signal[index]); \
 		sig_wait(test_signal[index]); \
 		count++; \
 	} while(0) \
 
-#define PROC_TEST_SLAVE_STACK(index) PROC_DEFINE_STACK(proc_signal_test##index##_stack, KERN_MINSTACKSIZE);
+#if CONFIG_KERN_HEAP
+
+#define PROC_TEST_SLAVE_INIT(index, master_process) proc_new(proc_signalTest##index, master_process, KERN_MINSTACKSIZE * 2, NULL)
+
+#else
+
+#define PROC_TEST_SLAVE_STACK(index) PROC_DEFINE_STACK(proc_signal_test##index##_stack, KERN_MINSTACKSIZE * 2);
 #define PROC_TEST_SLAVE_INIT(index, master_process) proc_new(proc_signalTest##index, master_process, sizeof(proc_signal_test##index##_stack), proc_signal_test##index##_stack)
 
+PROC_TEST_SLAVE_STACK(0)
+PROC_TEST_SLAVE_STACK(1)
+PROC_TEST_SLAVE_STACK(2)
+PROC_TEST_SLAVE_STACK(3)
+PROC_TEST_SLAVE_STACK(4)
+PROC_TEST_SLAVE_STACK(5)
+PROC_TEST_SLAVE_STACK(6)
+PROC_TEST_SLAVE_STACK(7)
+
+#endif
+
 // Generate the code for signal test.
 PROC_TEST_SLAVE(0, SIG_USER0)
 PROC_TEST_SLAVE(1, SIG_USER1)
@@ -109,15 +123,6 @@ PROC_TEST_SLAVE(5, SIG_SYSTEM5)
 PROC_TEST_SLAVE(6, SIG_SYSTEM6)
 PROC_TEST_SLAVE(7, SIG_SINGLE)
 
-PROC_TEST_SLAVE_STACK(0)
-PROC_TEST_SLAVE_STACK(1)
-PROC_TEST_SLAVE_STACK(2)
-PROC_TEST_SLAVE_STACK(3)
-PROC_TEST_SLAVE_STACK(4)
-PROC_TEST_SLAVE_STACK(5)
-PROC_TEST_SLAVE_STACK(6)
-PROC_TEST_SLAVE_STACK(7)
-
 /**
  * Run signal test
  */
diff --git a/bertos/mware/event.c b/bertos/mware/event.c
index a0419fbf..c596e12f 100644
--- a/bertos/mware/event.c
+++ b/bertos/mware/event.c
@@ -47,7 +47,7 @@ void event_hook_ignore(UNUSED_ARG(Event *, e))
 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
 void event_hook_signal(Event *e)
 {
-	sig_signal((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit);
+	sig_post((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit);
 }
 #endif
 
diff --git a/examples/at91sam7/at91sam7.c b/examples/at91sam7/at91sam7.c
index 70e21f9c..b8ef86c8 100644
--- a/examples/at91sam7/at91sam7.c
+++ b/examples/at91sam7/at91sam7.c
@@ -50,6 +50,7 @@
 #include <cfg/macros.h>
 
 #include <kern/proc.h>
+#include <kern/signal.h>
 
 #include <cpu/detect.h>
 
@@ -176,7 +177,13 @@ int main(void)
 		kfile_printf(&ser_fd.fd, "ProcTest..ok!\n");
 	else
 		kfile_printf(&ser_fd.fd, "ProcTest..FAIL!\n");
-
+	/*
+	 * Run signal test.
+	 */
+	if(!signal_testRun())
+		kfile_printf(&ser_fd.fd, "SignalTest..ok!\n");
+	else
+		kfile_printf(&ser_fd.fd, "SignalTest..FAIL!\n");
 
 	kputs(AT91SAM7_MSG);
 
diff --git a/examples/at91sam7/at91sam7s.mk b/examples/at91sam7/at91sam7s.mk
index e0ada56b..0586ba45 100644
--- a/examples/at91sam7/at91sam7s.mk
+++ b/examples/at91sam7/at91sam7s.mk
@@ -31,6 +31,7 @@ at91sam7s_CSRC = \
 	bertos/kern/coop.c \
 	bertos/kern/preempt.c \
 	bertos/kern/proc_test.c \
+	bertos/kern/signal_test.c \
 	bertos/kern/monitor.c \
 	bertos/kern/signal.c \
 	#
diff --git a/examples/at91sam7/at91sam7x.mk b/examples/at91sam7/at91sam7x.mk
index 77e45791..436c4445 100644
--- a/examples/at91sam7/at91sam7x.mk
+++ b/examples/at91sam7/at91sam7x.mk
@@ -32,6 +32,7 @@ at91sam7x_CSRC = \
 	bertos/kern/coop.c \
 	bertos/kern/preempt.c \
 	bertos/kern/proc_test.c \
+	bertos/kern/signal_test.c \
 	bertos/kern/monitor.c \
 	bertos/kern/signal.c \
 	#
diff --git a/examples/avr-kern/avr-kern.mk b/examples/avr-kern/avr-kern.mk
index f241fd7f..d4e2891c 100644
--- a/examples/avr-kern/avr-kern.mk
+++ b/examples/avr-kern/avr-kern.mk
@@ -16,6 +16,7 @@ avr-kern_PROGRAMMER_PORT = none
 avr-kern_USER_CSRC = \
 	examples/avr-kern/main.c \
 	bertos/kern/proc_test.c \
+	bertos/kern/signal_test.c \
 	bertos/mware/sprintf.c \
 	#
 
diff --git a/examples/avr-kern/main.c b/examples/avr-kern/main.c
index b1e502c3..ed2113e7 100644
--- a/examples/avr-kern/main.c
+++ b/examples/avr-kern/main.c
@@ -4,6 +4,7 @@
 #include <cpu/irq.h>
 #include <drv/timer.h>
 #include <kern/proc.h>
+#include <kern/signal.h>
 #include <stdio.h>
 
 static void init(void)
@@ -27,6 +28,7 @@ int main(void)
 	kputs("\n");
 
 	proc_testRun();
+	signal_testRun();
 	while (1)
 		cpu_relax();
 
diff --git a/examples/benchmark/kernel-core_avr/main.c b/examples/benchmark/kernel-core_avr/main.c
index 190c3384..052e484d 100644
--- a/examples/benchmark/kernel-core_avr/main.c
+++ b/examples/benchmark/kernel-core_avr/main.c
@@ -49,7 +49,7 @@ int main(void)
 	
 	while (1)
 	{
-		sig_signal(p, SIG_USER0);
+		sig_send(p, SIG_USER0);
 		proc_yield();
 	}
 
diff --git a/examples/benchmark/kernel-only_arm/main.c b/examples/benchmark/kernel-only_arm/main.c
index 1c81b565..2455abf1 100644
--- a/examples/benchmark/kernel-only_arm/main.c
+++ b/examples/benchmark/kernel-only_arm/main.c
@@ -34,7 +34,7 @@ int main(void)
 	Msg *msg_re = msg_get(&in_port);
 	msg_reply(msg_re);
 	// generate code for signals
-	sig_signal(p, SIG_USER0);
+	sig_send(p, SIG_USER0);
 	sig_wait(SIG_USER0);
 
 	return 0;
diff --git a/wizard/BWizardPage.py b/wizard/BWizardPage.py
index 980cb45c..be667562 100644
--- a/wizard/BWizardPage.py
+++ b/wizard/BWizardPage.py
@@ -33,12 +33,16 @@
 # Author: Lorenzo Berni <duplo@develer.com>
 #
 
+import os
+
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from PyQt4 import uic
 
 import qvariant_converter
 
+import const
+
 class BWizardPage(QWizardPage):
     """
     Base class for all the wizard pages. It has the utility method used in all
@@ -47,7 +51,7 @@ class BWizardPage(QWizardPage):
     
     def __init__(self, wizardGui, parent = None):
         QWizardPage.__init__(self, parent)
-        self.pageContent = uic.loadUi(wizardGui, None)
+        self.pageContent = uic.loadUi(os.path.join(const.DATA_DIR, wizardGui), None)
         layout = QVBoxLayout()
         layout.addWidget(self.pageContent)
         self.setLayout(layout)
diff --git a/wizard/bertos.py b/wizard/bertos.py
index 05ecf7af..e4255177 100755
--- a/wizard/bertos.py
+++ b/wizard/bertos.py
@@ -61,6 +61,7 @@ from BFinalPage import BFinalPage
 from BEditingDialog import BEditingDialog, BVersionDialog, BToolchainDialog
 
 import bertos_utils
+import const
 
 from LoadException import VersionException, ToolchainException
 
@@ -79,7 +80,7 @@ def newProject():
             relevant_file = relevant_files[ide]
             QProcess.startDetached(command_line, [relevant_file,])
     sys.exit()
-    
+
 def editProject(project_file):
     info_dict = {}
     while(True):
@@ -119,19 +120,20 @@ def showStartPage():
     QApplication.instance().dialog.show()
 
 def main():
-    os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
     app = QApplication(sys.argv)
     app.settings = QSettings("Develer", "Bertos Configurator")
     app.project = BProject.BProject()
     # Development utility lines, to be removed for production
-    if not (hasattr(sys, "frozen") and sys.frozen) and newer("bertos.qrc", "bertos.rcc"):
-        os.system("rcc -binary bertos.qrc -o bertos.rcc")
-    QResource.registerResource("bertos.rcc")
+    datadir = const.DATA_DIR
+    qrc, rcc = os.path.join(datadir, 'bertos.qrc'), os.path.join(datadir, 'bertos.rcc')
+    if not (hasattr(sys, "frozen") and sys.frozen) and newer(qrc, rcc):
+        os.system("rcc -binary %s -o %s" %(qrc, rcc))
+    QResource.registerResource(rcc)
     if len(sys.argv) == 3 and sys.argv[1] == "--edit":
         editProject(sys.argv[2])
     else:
         newProject()
- 
+
 
 if __name__ == '__main__':
     main()
diff --git a/wizard/bertos_utils.py b/wizard/bertos_utils.py
index 004e67bf..5fbd6914 100644
--- a/wizard/bertos_utils.py
+++ b/wizard/bertos_utils.py
@@ -167,7 +167,7 @@ def createBertosProject(project_info, edit=False):
         mergeSources(srcdir, sources_dir, old_sources_dir)
     # Destination makefile
     makefile = directory + "/Makefile"
-    makefile = open("mktemplates/Makefile").read()
+    makefile = open(os.path.join(const.DATA_DIR, "mktemplates/Makefile"), 'r').read()
     makefile = makefileGenerator(project_info, makefile)
     open(directory + "/Makefile", "w").write(makefile)
     # Destination project dir
@@ -219,16 +219,16 @@ def createBertosProject(project_info, edit=False):
         f.close()
     if not edit:
         # Destination user mk file (only on project creation)
-        makefile = open("mktemplates/template.mk", "r").read()
+        makefile = open(os.path.join(const.DATA_DIR, "mktemplates/template.mk"), "r").read()
         makefile = mkGenerator(project_info, makefile)
         open(prjdir + "/" + os.path.basename(prjdir) + ".mk", "w").write(makefile)
     # Destination wizard mk file
-    makefile = open("mktemplates/template_wiz.mk", "r").read()
+    makefile = open(os.path.join(const.DATA_DIR, "mktemplates/template_wiz.mk"), "r").read()
     makefile = mkGenerator(project_info, makefile)
     open(prjdir + "/" + os.path.basename(prjdir) + "_wiz.mk", "w").write(makefile)
     # Destination main.c file
     if not edit:
-        main = open("srctemplates/main.c", "r").read()
+        main = open(os.path.join(const.DATA_DIR, "srctemplates/main.c"), "r").read()
         open(prjdir + "/main.c", "w").write(main)
     # Files for selected plugins
     relevants_files = {}
diff --git a/wizard/const.py b/wizard/const.py
index 4f226328..697cd463 100644
--- a/wizard/const.py
+++ b/wizard/const.py
@@ -33,6 +33,14 @@
 # Author: Lorenzo Berni <duplo@develer.com>
 #
 
+import os, sys
+
+_tmp = sys.argv[0]
+if os.path.islink(_tmp):
+    _tmp = os.readlink(_tmp)
+DATA_DIR = os.path.dirname(os.path.abspath(_tmp))
+del _tmp
+
 CPU_DEF = {
     "CPU_NAME": "",
     "CPU_DIR": "",
diff --git a/wizard/exception_handler.py b/wizard/exception_handler.py
index 1dc3405c..9e54fa69 100644
--- a/wizard/exception_handler.py
+++ b/wizard/exception_handler.py
@@ -42,6 +42,8 @@ from PyQt4.QtGui import *
 
 def _excepthook(exc_type, exc_value, exc_traceback):
     project_dir = QApplication.instance().project.info("PROJECT_PATH")
+    if not project_dir:
+        project_dir = os.getcwd()
     file_name = os.path.join(project_dir, "wizard_error.log")
     if os.path.exists(file_name):
         content = open(file_name, "r").read()
@@ -55,6 +57,7 @@ def _excepthook(exc_type, exc_value, exc_traceback):
     f.write(">"*80 + "\n")
     f.write(content)
     f.close()
+    print>>sys.stderr, message
     QMessageBox.critical(
         None,
         "Exception occurred",
diff --git a/wizard/plugins/codelite.py b/wizard/plugins/codelite.py
index f6555a8b..7f4daac8 100644
--- a/wizard/plugins/codelite.py
+++ b/wizard/plugins/codelite.py
@@ -99,7 +99,7 @@ def codeliteProjectGenerator(project_info):
     """
     Returns the string rapresenting the codelite project.
     """
-    template = open("cltemplates/bertos.project", "r").read()
+    template = open(os.path.join(const.DATA_DIR, "cltemplates/bertos.project"), "r").read()
     filelist = "\n".join(clFiles(findSources(project_info.info("PROJECT_PATH")), ""))
     debugger_path = project_info.info("TOOLCHAIN")["path"].replace("gcc", "gdb")
     init_script = project_info.info("CPU_INFOS")["GDB_INIT_SCRIPT"]
@@ -118,7 +118,7 @@ def codeliteWorkspaceGenerator(project_info):
     """
     Returns the string rapresentig the codelite workspace.
     """
-    template = open("cltemplates/bertos.workspace", "r").read()
+    template = open(os.path.join(const.DATA_DIR, "cltemplates/bertos.workspace"), "r").read()
     project_name = os.path.basename(project_info.info("PROJECT_PATH"))
     while template.find("$project") != -1:
         template = template.replace("$project", project_name)
-- 
2.34.1