Index: trunk/kernel/kern/thread.c
===================================================================
--- trunk/kernel/kern/thread.c	(revision 5)
+++ trunk/kernel/kern/thread.c	(revision 14)
@@ -24,5 +24,5 @@
  */
 
-#include <almos_config.h>
+#include <kernel_config.h>
 #include <hal_types.h>
 #include <hal_context.h>
@@ -76,45 +76,67 @@
 
 /////////////////////////////////////////////////////////////////////////////////////
-// This static function makes the actual allocation and initialisation for a thread
-// descriptor. It is called by the three functions:
+// This static function allocates physical memory for a thread descriptor.
+// It can be called by the three functions:
 // - thread_user_create()
-// - thread_user_copy()
+// - thread_user_fork()
 // - thread_kernel_create()
 /////////////////////////////////////////////////////////////////////////////////////
-// @ new_thread : buffer for new thread pointer.
-// @ process    : local pointer on process descriptor.
-// @ type       : thread type.
-// @ func       : local pointer on thread entry function.
-// @ args       : local pointer on thread entry function arguments.
-// @ core_lid   : target core local index.
+// @ return pointer on thread descriptor if success / return NULL if failure.
 /////////////////////////////////////////////////////////////////////////////////////
-static error_t thread_create( thread_t     ** new_thread,
-                              process_t     * process,
-                              thread_type_t   type,
-                              void          * func,
-                              void          * args,
-                              lid_t           core_lid,
-                              intptr_t        u_stack_base,
-                              uint32_t        u_stack_size )
-{
-    error_t        error;
-	thread_t     * thread;     // pointer on thread descriptor
+static thread_t * thread_alloc()
+{
 	page_t       * page;       // pointer on page descriptor containing thread descriptor
 	kmem_req_t     req;        // kmem request 
-    trdid_t        trdid;      // allocated thread identifier
-
-	cluster_t    * local_cluster = LOCAL_CLUSTER;
 
 	// allocates memory for thread descriptor + kernel stack
 	req.type  = KMEM_PAGE;
-	req.size  = CONFIG_THREAD_PAGE_ORDER;
+	req.size  = CONFIG_THREAD_DESC_ORDER;
 	req.flags = AF_KERNEL | AF_ZERO;
 	page      = kmem_alloc( &req );
-	if( page == NULL ) return ENOMEM;
-
-    // get pointer on new thread descriptor
-	thread = (thread_t *)ppm_page2base( page );
-
-    // register new thread in local process descriptor, and get a TRDID
+
+    // return pointer on new thread descriptor
+	if( page == NULL ) 
+    {
+        printk("\n[ERROR] in %s : no memory for thread descriptor\n", __FUNCTION__ );
+        return NULL;
+    }
+    else
+    {
+        return (thread_t *)ppm_page2base( page );
+    }
+}  // end thread_alloc()
+
+/////////////////////////////////////////////////////////////////////////////////////
+// This static function initializes a thread descriptor (kernel or user).
+// It can be called by the four functions:
+// - thread_user_create()
+// - thread_user_fork()
+// - thread_kernel_create()
+// - thread_user_init()
+/////////////////////////////////////////////////////////////////////////////////////
+// @ thread       : pointer on thread descriptor
+// @ process      : pointer on process descriptor.
+// @ type         : thread type.
+// @ func         : pointer on thread entry function.
+// @ args         : pointer on thread entry function arguments.
+// @ core_lid     : target core local index.
+// @ u_stack_base : stack base (user thread only)
+// @ u_stack_size : stack base (user thread only)
+/////////////////////////////////////////////////////////////////////////////////////
+static error_t thread_init( thread_t      * thread,
+                            process_t     * process,
+                            thread_type_t   type,
+                            void          * func,
+                            void          * args,
+                            lid_t           core_lid,
+                            intptr_t        u_stack_base,
+                            uint32_t        u_stack_size )
+{
+    error_t        error;
+    trdid_t        trdid;      // allocated thread identifier
+
+	cluster_t    * local_cluster = LOCAL_CLUSTER;
+
+    // register new thread in process descriptor, and get a TRDID
     spinlock_lock( &process->th_lock );
     error = process_register_thread( process, thread , &trdid );
@@ -123,11 +145,8 @@
     if( error ) 
     {
-        // release allocated memory for thread descriptor 
-	    req.type  = KMEM_PAGE;
-        req.ptr   = page;
-        kmem_free( &req );
-        return EAGAIN;
-    }
- 
+        printk("\n[ERROR] in %s : cannot get TRDID\n", __FUNCTION__ );
+        return EINVAL;
+    }
+
 	// Initialize new thread descriptor
     thread->trdid           = trdid;
@@ -138,5 +157,4 @@
 	thread->core            = &local_cluster->core_tbl[core_lid];
 	thread->process         = process;
-    thread->page            = page;
 
     thread->local_locks     = 0;
@@ -149,5 +167,5 @@
     thread->u_stack_size    = u_stack_size;
     thread->k_stack_base    = (intptr_t)thread;     
-    thread->k_stack_size    = CONFIG_PPM_PAGE_SIZE << CONFIG_THREAD_PAGE_ORDER;
+    thread->k_stack_size    = CONFIG_THREAD_DESC_SIZE;
 
     thread->entry_func      = func;         // thread entry point
@@ -182,7 +200,7 @@
     sched_register_thread( thread->core , thread );
 
-    *new_thread = thread;
 	return 0;
-} // end thread_create()
+
+} // end thread_init()
 
 
@@ -197,7 +215,7 @@
     process_t    * process;      // pointer to local process descriptor
     lid_t          core_lid;     // selected core local index
-
-    thread_dmsg("\n[INFO] %s : enters\n", 
-                __FUNCTION__ );
+	kmem_req_t     req;          // kmem request (for release) 
+
+    thread_dmsg("\n[INFO] %s : enters\n", __FUNCTION__ );
 
 	cluster_t    * local_cluster = LOCAL_CLUSTER;
@@ -214,17 +232,31 @@
     if( process == NULL ) return ENOMEM;
 
-    // make allocation / initialisation
-    error = thread_create( &thread,
-                           process,
-                           THREAD_USER,
-                           attr->entry_func,
-                           attr->entry_args,
-                           core_lid,
-                           u_stack_base,
-                           u_stack_size );
-    if( error ) return ENOMEM;
-
-    // set LOADABLE flag / set ATTACHED flag if required
+    // allocates memory tor thread descriptor
+    thread = thread_alloc();
+
+    if( thread == NULL ) return ENOMEM;
+
+    // initializes thread descriptor
+    error = thread_init( thread,
+                         process,
+                         THREAD_USER,
+                         attr->entry_func,
+                         attr->entry_args,
+                         core_lid,
+                         u_stack_base,
+                         u_stack_size );
+
+    if( error )  // release allocated memory for thread descriptor 
+    {
+	    req.type  = KMEM_PAGE;
+        req.ptr   = ppm_base2page( thread );
+        kmem_free( &req );
+        return EINVAL;
+    }
+
+    // set LOADABLE flag 
     thread->flags = THREAD_FLAG_LOADABLE;
+
+    // set DETACHED flag if required
     if( attr->flags & PT_FLAG_DETACH ) thread->flags |= THREAD_FLAG_DETACHED;
 
@@ -242,4 +274,5 @@
     *new_thread = thread;
 	return 0;
+
 } // end thread_user_create()
 
@@ -252,9 +285,9 @@
 {
     error_t        error;
-	thread_t     * new;          // pointer on thread descriptor
+	thread_t     * thread;       // pointer on new thread descriptor
     lid_t          core_lid;     // selected core local index
-
-    thread_dmsg("\n[INFO] %s : enters\n", 
-                __FUNCTION__ );
+	kmem_req_t     req;          // kmem request (for release) 
+
+    thread_dmsg("\n[INFO] %s : enters\n", __FUNCTION__ );
 
     // select a target core in local cluster
@@ -264,30 +297,42 @@
     thread_t * this = CURRENT_THREAD;
 
-    // make allocation / initialisation
-    error = thread_create( &new,
-                           process,
-                           THREAD_USER,
-                           this->entry_func,
-                           this->entry_args,
-                           core_lid,
-                           u_stack_base,
-                           u_stack_size );
+    // allocated memory for new thread descriptor
+    thread = thread_alloc();
+
+    if( thread == NULL ) return ENOMEM;
+
+    // initializes thread descriptor
+    error = thread_init( thread,
+                         process,
+                         THREAD_USER,
+                         this->entry_func,
+                         this->entry_args,
+                         core_lid,
+                         u_stack_base,
+                         u_stack_size );
+
+    if( error ) // release allocated memory for thread descriptor 
+    {
+	    req.type  = KMEM_PAGE;
+        req.ptr   = ppm_base2page( thread );
+        kmem_free( &req );
+        return EINVAL;
+    }
+
+    // set ATTACHED flag if set in this thread
+    if( this->flags & THREAD_FLAG_DETACHED ) thread->flags = THREAD_FLAG_DETACHED;
+
+    // allocate & initialise CPU context from calling thread
+	error = hal_cpu_context_copy( thread , this ); 
     if( error ) return ENOMEM;
 
-    // set ATTACHED flag if set in this thread
-    if( this->signals & THREAD_FLAG_DETACHED ) new->signals = THREAD_FLAG_DETACHED;
-
-    // allocate & initialise CPU context from calling thread
-	error = hal_cpu_context_copy( new , this ); 
+    // allocate & initialise FPU context from calling thread
+	error = hal_fpu_context_copy( thread , this ); 
     if( error ) return ENOMEM;
 
-    // allocate & initialise FPU context from calling thread
-	error = hal_fpu_context_copy( new , this ); 
-    if( error ) return ENOMEM;
-
     thread_dmsg("INFO : %s thread %x for process %x on core %d in cluster %x\n", 
-                 __FUNCTION__, new->trdid, process->pid, core_lid, local_cxy );
-
-    *new_thread = new;
+                 __FUNCTION__, thread->trdid, process->pid, core_lid, local_cxy );
+
+    *new_thread = thread;
 	return 0;
 
@@ -304,7 +349,8 @@
 {
     error_t        error;
-	thread_t     * new;        // pointer on new thread descriptor
-
-    thread_dmsg("\n[INFO] %s : enters for %s in cluster %x\n",
+	thread_t     * thread;       // pointer on new thread descriptor
+	kmem_req_t     req;          // kmem request (for release) 
+
+    thread_dmsg("\n[INFO] %s : enters for type %s in cluster %x\n",
                 __FUNCTION__ , thread_type_str( type ) , local_cxy );
 
@@ -316,29 +362,70 @@
             __FUNCTION__ , "illegal core_lid" );
 
-    // make allocation / initialisation
-    error = thread_create( &new,
-                           &process_zero,
-                           type,
-                           func,
-                           args,
-                           core_lid,
-                           0 , 0 );  // no user stack for a kernel thread
-    if( error ) 
-    {
-        printk("\n[ERROR] in %s : cannot create thread\n", __FUNCTION__ );
-        return ENOMEM;
-    }
+    // allocated memory for new thread descriptor
+    thread = thread_alloc();
+
+    if( thread == NULL ) return ENOMEM;
+
+    // initializes thread descriptor
+    error = thread_init( thread,
+                         &process_zero,
+                         type,
+                         func,
+                         args,
+                         core_lid,
+                         0 , 0 );  // no user stack for a kernel thread
+
+    if( error ) // release allocated memory for thread descriptor 
+    {
+	    req.type  = KMEM_PAGE;
+        req.ptr   = ppm_base2page( thread );
+        kmem_free( &req );
+        return EINVAL;
+    }
+
 
     // allocate & initialise CPU context
-	hal_cpu_context_create( new ); 
-
-    thread_dmsg("\n[INFO] %s : sucessfully exit / trdid = %x / core = %d\n", 
-                 __FUNCTION__ , new->trdid , core_lid );
-
-    *new_thread = new; 
+	hal_cpu_context_create( thread ); 
+
+    thread_dmsg("\n[INFO] %s : exit in cluster %x / trdid = %x / core_lid = %d\n", 
+                 __FUNCTION__ , local_cxy , thread->trdid , core_lid );
+
+    *new_thread = thread; 
 	return 0;
 
 } // end thread_kernel_create()
 
+///////////////////////////////////////////////////
+error_t thread_kernel_init( thread_t      * thread,
+                            thread_type_t   type,
+                            void          * func, 
+                            void          * args, 
+				            lid_t           core_lid )
+{
+    assert( ( (type == THREAD_KERNEL) || (type == THREAD_RPC) || 
+              (type == THREAD_IDLE)   || (type == THREAD_DEV) ) ,
+              __FUNCTION__ , "illegal thread type" );
+
+    if( core_lid >= LOCAL_CLUSTER->cores_nr ) 
+    {
+        printk("\n[PANIC] in %s : illegal core_lid / cores = %d / lid = %d / cxy = %x\n", 
+               __FUNCTION__ , LOCAL_CLUSTER->cores_nr , core_lid , local_cxy );
+        hal_core_sleep();
+    }
+
+    error_t  error = thread_init( thread,
+                                  &process_zero,
+                                  type,
+                                  func,
+                                  args,
+                                  core_lid,
+                                  0 , 0 );   // no user stack for a kernel thread
+
+    // allocate & initialize CPU context if success
+    if( error == 0 ) hal_cpu_context_create( thread );
+     
+    return error;
+
+}  // end thread_kernel_init()
 
 ///////////////////////////////////////////////////////////////////////////////////////
@@ -592,19 +679,24 @@
 
 
-/////////////////////////
-void * thread_idle_func()
-{
+///////////////////////
+void thread_idle_func()
+{
+    lid_t  lid = CURRENT_CORE->lid;
+
     while( 1 )
     {
-        thread_dmsg("\n[INFO] %s : core %d in cluster %x goes to sleeping state at cycle\n",
-                    __FUNCTION__ , core->lid , local_cxy , hal_time_stamp() );
+        thread_dmsg("\n[INFO] %s : core[%x][%d] goes to sleep at cycle %d\n",
+                    __FUNCTION__ , local_cxy , lid , hal_time_stamp() );
 
         // force core to sleeping state
         hal_core_sleep();
 
-        thread_dmsg("\n[INFO] %s : core %d in cluster %x wake up at cycle %d\n",
-                    __FUNCTION__ , core->lid , local_cxy , hal_time_stamp() );
-
-        // force scheduling at wake-up
+        thread_dmsg("\n[INFO] %s : core[%x][%d] wake up at cycle %d\n",
+                    __FUNCTION__ , local_cxy , lid , hal_time_stamp() );
+
+		// acknowledge IRQ
+        dev_icu_irq_handler();
+
+        // force scheduling
         sched_yield();
    }
