Changeset 683 for trunk/kernel/kern
- Timestamp:
- Jan 13, 2021, 12:36:17 AM (4 years ago)
- Location:
- trunk/kernel/kern
- Files:
-
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/alarm.c
r669 r683 31 31 32 32 //////////////////////////////////////////////////////////////////////////////////////////// 33 // This static function registers the alarm identified ny the <new_alarm> argument33 // This static function registers the alarm identified by the <alarm> & <cxy> arguments 34 34 // in the list of alarms rooted in the core identified by the <core> argument. 35 35 // When the existing list of alarms is not empty, it scan the list to insert the new 36 36 // alarm in the right place to respect the absolute dates ordering. 37 37 //////////////////////////////////////////////////////////////////////////////////////////// 38 // @ new_alarm : local pointer on the new alarm. 39 // @ core : local pointer on the target core. 38 // @ cxy : cluster containing both the new alarm and the core. 39 // @ alarm : local pointer on the alarm. 40 // @ core : local pointer on the core. 40 41 //////////////////////////////////////////////////////////////////////////////////////////// 41 static void alarm_register( alarm_t * new_alarm, 42 static void alarm_register( cxy_t cxy, 43 alarm_t * alarm, 42 44 core_t * core ) 43 45 { 44 list_entry_t * current; // pointer on current list_entry in existing list 45 list_entry_t * previous; // pointer on previous list_entry in existing list 46 alarm_t * current_alarm; // pointer on current alarm in existing list 47 cycle_t current_date; // date of current alarm in existing list 48 49 bool_t done = false; 50 51 // get pointers on root of alarms and lock 46 // get alarm date 47 cycle_t new_date = hal_remote_l64( XPTR( cxy , &alarm->date ) ); 48 49 // build local pointer on root of alarms list 52 50 list_entry_t * root = &core->alarms_root; 53 busylock_t * lock = &core->alarms_lock; 54 55 // get pointer on new_alarm list_entry 56 list_entry_t * new_entry = &new_alarm->list; 57 58 // get new_alarm date 59 cycle_t new_date = new_alarm->date; 60 61 // take the lock 62 busylock_acquire( lock ); 51 52 // build local pointer on new alarm list_entry 53 list_entry_t * new = &alarm->list; 63 54 64 55 // insert new alarm to respect dates order 65 if( list_ is_empty( root ) )// list empty56 if( list_remote_is_empty( cxy , &core->alarms_root ) ) // list empty 66 57 { 67 list_ add_first( root , new_entry);58 list_remote_add_first( cxy , root , new ); 68 59 } 69 else // list non empty60 else // list non empty 70 61 { 71 for( current = root->next ; 72 (current != root) && (done == false) ; 73 current = current->next ) 62 list_entry_t * iter; // local pointer on current list_entry in existing list 63 alarm_t * iter_alarm; // local pointer on current alarm in existing list 64 cycle_t iter_date; // date of current alarm in existing list 65 bool_t done = false; 66 67 for( iter = hal_remote_lpt( XPTR( cxy , &root->next ) ) ; 68 (iter != root) && (done == false) ; 69 iter = hal_remote_lpt( XPTR( cxy , &iter->next ) ) ) 74 70 { 75 // get pointer on previous entry in existing list76 previous = current->pred;77 78 // get pointer on current alarm79 current_alarm = LIST_ELEMENT( current, alarm_t , list );71 // get local pointer on pred and next for iter 72 list_entry_t * prev = hal_remote_lpt( XPTR( cxy , &iter->pred ) ); 73 74 // get local pointer on current alarm 75 iter_alarm = LIST_ELEMENT( iter , alarm_t , list ); 80 76 81 77 // get date for current alarm 82 current_date = current_alarm->date; 83 84 if( current_date > new_date ) // insert new alarm just before current 78 iter_date = hal_remote_l64( XPTR( cxy , &iter_alarm->date ) ); 79 80 // insert new alarm just before current when required 81 if( iter_date > new_date ) 85 82 { 86 new_entry->next = current;87 new_entry->pred = previous;88 89 current->pred = new_entry;90 previous->next = new_entry;83 hal_remote_spt( XPTR( cxy , &new->next ) , iter ); 84 hal_remote_spt( XPTR( cxy , &new->pred ) , prev ); 85 86 hal_remote_spt( XPTR( cxy , &iter->pred ) , new ); 87 hal_remote_spt( XPTR( cxy , &prev->next ) , new ); 91 88 92 89 done = true; … … 96 93 if( done == false ) // new_date is larger than all registered dates 97 94 { 98 list_ add_last( root , new_entry);95 list_remote_add_last( cxy, root , new ); 99 96 } 100 97 } 101 98 } // end alarm_register() 99 100 101 /////////////////////////////////// 102 void alarm_init( alarm_t * alarm ) 103 { 104 alarm->linked = false; 105 list_entry_init( &alarm->list ); 106 } 107 108 /////////////////////////////////////// 109 void alarm_start( xptr_t thread_xp, 110 cycle_t date, 111 void * func_ptr, 112 xptr_t args_xp ) 113 { 114 // get cluster and local pointer on target thread 115 thread_t * tgt_ptr = GET_PTR( thread_xp ); 116 cxy_t tgt_cxy = GET_CXY( thread_xp ); 117 118 // check alarm state 119 assert( __FUNCTION__ , (hal_remote_l32( XPTR(tgt_cxy,&tgt_ptr->alarm.linked)) == false ), 120 "alarm already started"); 121 122 // get local pointer on core running target thread 123 core_t * core = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->core ) ); 124 125 // build extended pointer on lock protecting alarms list 126 xptr_t lock_xp = XPTR( tgt_cxy , &core->alarms_lock ); 127 128 // initialize alarm descriptor 129 hal_remote_s64( XPTR( tgt_cxy , &tgt_ptr->alarm.date ) , date ); 130 hal_remote_spt( XPTR( tgt_cxy , &tgt_ptr->alarm.func_ptr ) , func_ptr ); 131 hal_remote_s64( XPTR( tgt_cxy , &tgt_ptr->alarm.args_xp ) , args_xp ); 132 hal_remote_s32( XPTR( tgt_cxy , &tgt_ptr->alarm.linked ) , true ); 133 134 // take the lock 135 remote_busylock_acquire( lock_xp ); 136 137 // register alarm in core list 138 alarm_register( tgt_cxy , &tgt_ptr->alarm , core ); 139 140 //release the lock 141 remote_busylock_release( lock_xp ); 142 143 } // end alarm_start() 144 145 146 ///////////////////////////////////// 147 void alarm_stop( xptr_t thread_xp ) 148 { 149 // get cluster and local pointer on target thread 150 thread_t * tgt_ptr = GET_PTR( thread_xp ); 151 cxy_t tgt_cxy = GET_CXY( thread_xp ); 152 153 // get local pointer on core running target thread 154 core_t * core = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->core ) ); 155 156 // build extended pointer on lock protecting alarms list 157 xptr_t lock_xp = XPTR( tgt_cxy , &core->alarms_lock ); 158 159 // take the lock 160 remote_busylock_acquire( lock_xp ); 161 162 // unlink the alarm from the list rooted in core 163 list_remote_unlink( tgt_cxy , &tgt_ptr->alarm.list ); 164 165 // update alarm state 166 hal_remote_s32( XPTR( tgt_cxy , &tgt_ptr->alarm.linked ) , false ); 167 168 //release the lock 169 remote_busylock_release( lock_xp ); 170 171 } // end alarm_stop() 172 173 174 ////////////////////////////////////// 175 void alarm_update( xptr_t thread_xp, 176 cycle_t new_date ) 177 { 178 // get cluster and local pointer on target thread 179 thread_t * tgt_ptr = GET_PTR( thread_xp ); 180 cxy_t tgt_cxy = GET_CXY( thread_xp ); 181 182 // get local pointer on core running target thread 183 core_t * core = hal_remote_lpt( XPTR( tgt_cxy , &tgt_ptr->core ) ); 184 185 // build extended pointer on lock protecting alarms list 186 xptr_t lock_xp = XPTR( tgt_cxy , &core->alarms_lock ); 187 188 // take the lock 189 remote_busylock_acquire( lock_xp ); 190 191 // unlink the alarm from the core list 192 list_remote_unlink( tgt_cxy , &tgt_ptr->alarm.list ); 193 194 // update the alarm date and state 195 hal_remote_s64( XPTR( tgt_cxy , &tgt_ptr->alarm.date ) , new_date ); 196 hal_remote_s32( XPTR( tgt_cxy , &tgt_ptr->alarm.linked ) , true ); 197 198 // register alarm in core list 199 alarm_register( tgt_cxy , &tgt_ptr->alarm , core ); 200 102 201 // release the lock 103 busylock_release( lock ); 104 105 } // end alarm_register() 106 107 ////////////////////////////////////// 108 void alarm_start( cycle_t date, 109 void * func_ptr, 110 xptr_t args_xp, 111 thread_t * thread ) 112 { 113 // get pointer on alarm 114 alarm_t * alarm = &thread->alarm; 115 116 // initialize alarm descriptor 117 alarm->date = date; 118 alarm->func_ptr = func_ptr; 119 alarm->args_xp = args_xp; 120 121 // register alarm in core list 122 alarm_register( alarm , thread->core ); 123 124 } // end alarm_start() 125 126 ///////////////////////////////////// 127 void alarm_update( thread_t * thread, 128 cycle_t new_date ) 129 { 130 // get pointer on alarm 131 alarm_t * alarm = &thread->alarm; 132 133 // get pointer on core 134 core_t * core = thread->core; 135 136 // get pointer on lock protecting the alarms list 137 busylock_t * lock = &core->alarms_lock; 138 139 // unlink the alarm from the core list 140 busylock_acquire( lock ); 141 list_unlink( &alarm->list ); 142 busylock_release( lock ); 143 144 // update the alarm date 145 alarm->date = new_date; 146 147 // register alarm in core list 148 alarm_register( alarm , core ); 149 202 remote_busylock_release( lock_xp ); 203 150 204 } // end alarm_update() 151 205 152 //////////////////////////////////// 153 void alarm_stop( thread_t * thread ) 154 { 155 // get pointer on alarm 156 alarm_t * alarm = &thread->alarm; 157 158 // get pointer on core 159 core_t * core = thread->core; 160 161 // get pointer on lock protecting the alarms list 162 busylock_t * lock = &core->alarms_lock; 163 164 // unlink the alarm from the list rooted in core 165 busylock_acquire( lock ); 166 list_unlink( &alarm->list ); 167 busylock_release( lock ); 168 169 } // end alarm_stop() 170 206 -
trunk/kernel/kern/alarm.h
r669 r683 36 36 * This structure defines a generic, timer based, kernel alarm. 37 37 * 38 * - An alarm being attached to a given thread,the alarm descriptor is embedded in the38 * - An alarm is attached to a given thread, and the alarm descriptor is embedded in the 39 39 * thread descriptor. A client thread can use the alarm_start() function to dynamically 40 40 * activate the alarm. It can use the alarm_stop() function to desactivate this alarm. 41 41 * - This kernel alarm is generic, as the alarm handler (executed when the alarm rings), 42 * and the handler arguments are defined by two pointers <func_ptr> and <args_xp>.42 * and the handler arguments are defined by two pointers: <func_ptr> and <args_xp>. 43 43 * - When an alarm is created by a client thread, it is registered in the list of alarms 44 44 * rooted in the core running the client thread. When it is stopped, the alarm is simply 45 45 * removed from this list. 46 * - When creating an alarm , the client thread must define an absolute date (in cycles),47 * the func_ptr localpointer, and the args_xp extended pointer.46 * - When creating an alarm with the alarm_start() function, the client thread must define 47 * an absolute date (in cycles), the func_ptr pointer, and the args_xp extended pointer. 48 48 * - The list of alarms is ordered by increasing dates. At each TICK received by a core, 49 49 * the date of the first registered alarm is compared to the current date (in the 50 50 * core_clock() function). The alarm handler is executed when current_date >= alarm_date. 51 * - It is the handler responsability to stop a ringing alarm, or update the date. 51 * - It is the handler responsability to stop and delete a ringing alarm using the 52 * alarm_stop() function, or update the alarm date using the alarm_update() function. 53 * - The three alarm_start(), alarm_stop(), and alarm_update() access functions use 54 * the lock protecting the alarms list to handle concurrent accesses. These functions 55 * use extended pointers to access the alarm list, and can be called by a thread 56 * running in any cluster. 52 57 * 53 * This mechanism is used bi the almos_mkh implementation of the TCP protocoL. 58 * This embedded alarm mechanism is used by: 59 * 1. the socket_accept(), socket_connect(), socket_send(), socket_close() functions, 60 * to implement the TCP retransmission machanism. 61 * 2. the sys_thread_sleep() function, to implement the "sleep" mechanism. 54 62 ******************************************************************************************/ 55 63 56 64 typedef struct alarm_s 57 65 { 66 bool_t linked; /*! active when true (i.e linked to the core list) */ 58 67 cycle_t date; /*! absolute date for handler execution */ 59 68 void * func_ptr; /*! local pointer on alarm handler function */ 60 69 xptr_t args_xp; /*! local pointer on handler arguments */ 61 list_entry_t list; /*! all alarms attached to the same core*/70 list_entry_t list; /*! set of active alarms attached to the same core */ 62 71 } 63 72 alarm_t; … … 70 79 71 80 /******************************************************************************************* 81 * This function initialises the alarm state to "inactive". 82 ******************************************************************************************* 83 * @ alarm : local pointer on alarm. 84 ******************************************************************************************/ 85 void alarm_init( alarm_t * alarm ); 86 87 /******************************************************************************************* 72 88 * This function initializes the alarm descriptor embedded in the thread identified by the 73 * <thread> argument from the <date>, <func_ptr>, <args_ptr> arguments, and registers it 74 * in the ordered list rooted in the core running this <thread>. 89 * <thread_xp> argument from the <date>, <func_ptr>, <args_ptr> arguments, and registers 90 * this alarm in the ordered list rooted in the core running this thread. 91 * It takes the lock protecting the alarms list against concurrent accesses. 75 92 ******************************************************************************************* 93 * @ thread_xp : extended pointer on the target thread. 76 94 * @ date : absolute date (in cycles). 77 95 * @ func_ptr : local pointer on the handler to execute when the alarm rings. 78 96 * @ args_xp : extended pointer on the handler arguments. 79 * @ thread : local pointer on the client thread.80 97 ******************************************************************************************/ 81 void alarm_start( cycle_t date,82 void * func_ptr,83 xptr_t args_xp,84 struct thread_s * thread);98 void alarm_start( xptr_t thread_xp, 99 cycle_t date, 100 void * func_ptr, 101 xptr_t args_xp ); 85 102 86 103 /******************************************************************************************* … … 88 105 * <thread> argument. The list of alarms rooted in the core running the client thread 89 106 * is modified to respect the absolute dates ordering. 107 * It takes the lock protecting the alarms list against concurrent accesses. 90 108 ******************************************************************************************* 91 * @ thread : local pointer on the client thread.109 * @ thread_xp : extended pointer on the target thread. 92 110 * @ new_date : absolute new date (in cycles). 93 111 ******************************************************************************************/ 94 void alarm_update( struct thread_s * thread,95 cycle_t 112 void alarm_update( xptr_t thread_xp, 113 cycle_t new_date ); 96 114 97 115 /******************************************************************************************* 98 116 * This function unlink an alarm identified by the <thread> argument from the list of 99 117 * alarms rooted in the core descriptor. 118 * It takes the lock protecting the alarms list against concurrent accesses. 100 119 ******************************************************************************************* 101 * @ thread : local pointer on the client thread.120 * @ thread_xp : extended pointer on the target thread. 102 121 ******************************************************************************************/ 103 void alarm_stop( struct thread_s * thread);122 void alarm_stop( xptr_t thread_xp ); 104 123 105 124 -
trunk/kernel/kern/chdev.c
r669 r683 87 87 { 88 88 chdev_t * chdev; 89 kmem_req_t req;90 89 91 90 // allocate memory for chdev 92 req.type = KMEM_KCM; 93 req.order = bits_log2( sizeof(chdev_t) ); 94 req.flags = AF_ZERO | AF_KERNEL; 95 chdev = kmem_alloc( &req ); 91 chdev = kmem_alloc( bits_log2(sizeof(chdev_t)) , AF_ZERO | AF_KERNEL ); 96 92 97 93 if( chdev == NULL ) return NULL; … … 114 110 } // end chdev_create() 115 111 116 /////////////////////////////////// 117 void chdev_print( chdev_t * chdev ) 118 { 119 printk("\n - func = %s" 120 "\n - channel = %d" 121 "\n - base = %l" 112 ///////////////////////////////////// 113 void chdev_display( xptr_t chdev_xp ) 114 { 115 chdev_t * chdev = GET_PTR( chdev_xp ); 116 cxy_t cxy = GET_CXY( chdev_xp ); 117 118 char name[16]; 119 120 hal_remote_memcpy( XPTR( local_cxy, name ), 121 XPTR( cxy , &chdev->name ), 16 ); 122 123 printk("\n - chdev = [%x,%x]" 124 "\n - name = %s" 125 "\n - base = [%x,%x]" 122 126 "\n - cmd = %x" 123 "\n - isr = %x" 124 "\n - chdev = %x\n", 125 chdev_func_str(chdev->func), 126 chdev->channel, 127 chdev->base, 128 chdev->cmd, 129 chdev->isr, 130 chdev ); 131 } 127 "\n - isr = %x\n", 128 cxy, 129 chdev, 130 name, 131 GET_CXY( hal_remote_l64( XPTR( cxy , &chdev->base ))), 132 GET_PTR( hal_remote_l64( XPTR( cxy , &chdev->base ))), 133 hal_remote_lpt( XPTR( cxy , &chdev->cmd )), 134 hal_remote_lpt( XPTR( cxy , &chdev->isr )) ); 135 136 } // end chdev_display() 132 137 133 138 ////////////////////////////////////////////////// … … 450 455 chdev_t * chdev_ptr; 451 456 452 453 "file_xp == XPTR_NULL\n" );457 assert( __FUNCTION__, (file_xp != XPTR_NULL) , 458 "file_xp == XPTR_NULL" ); 454 459 455 460 // get cluster and local pointer on remote file descriptor … … 462 467 inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) ); 463 468 464 465 "inode type %d is not FILE_TYPE_DEV\n", inode_type );469 assert( __FUNCTION__, (inode_type == FILE_TYPE_DEV) , 470 "inode type %d is not FILE_TYPE_DEV", inode_type ); 466 471 467 472 // get chdev local pointer from inode extension -
trunk/kernel/kern/chdev.h
r669 r683 121 121 * . This busylock is also used to protect direct access to the shared 122 122 * kernel TXT0 terminal, that does not use the waiting queue. 123 * . For most d chdevs, the client waiting queue is an xlist of threads, but it is123 * . For most chdevs, the client waiting queue is a list of threads, but it is 124 124 * a list of sockets for the NIC chdevs. It is unused for ICU, PIC, and IOB. 125 125 *****************************************************************************************/ … … 190 190 191 191 /**************************************************************************************** 192 * This function display relevant values for a chdev descriptor.193 ****************************************************************************************194 * @ chdev : pointer on chdev.195 ***************************************************************************************/196 void chdev_print( chdev_t * chdev );197 198 /****************************************************************************************199 192 * This function returns a printable string for a device functionnal types. 200 193 **************************************************************************************** … … 223 216 224 217 /**************************************************************************************** 225 * This generi dfunction is executed by an user thread requesting an IOC or TXT chdev218 * This generic function is executed by an user thread requesting an IOC or TXT chdev 226 219 * service. It registers the calling thread in the waiting queue of a the remote 227 220 * chdev descriptor identified by the <chdev_xp> argument. … … 282 275 283 276 /**************************************************************************************** 277 * This function display relevant values for a remote chdev descriptor. 278 **************************************************************************************** 279 * @ chdev_xp : pointer on chdev. 280 ***************************************************************************************/ 281 void chdev_display( xptr_t chdev_xp ); 282 283 /**************************************************************************************** 284 284 * This function displays the local copy of the external chdevs directory. 285 285 * (global variable replicated in all clusters) -
trunk/kernel/kern/cluster.c
r669 r683 2 2 * cluster.c - Cluster-Manager related operations 3 3 * 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012)4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016,2017,2018,2019,2020)6 * Alain Greiner (2016,2017,2018,2019,2020) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 74 74 cluster->y_size = info->y_size; 75 75 cluster->io_cxy = info->io_cxy; 76 cluster->sys_clk = info->sys_clk; 76 77 77 78 // initialize the cluster_info[][] array … … 177 178 printk("\n[%s] PPM initialized in cluster %x / cycle %d\n", 178 179 __FUNCTION__ , local_cxy , cycle ); 179 #endif180 181 // initialises embedded KHM182 khm_init( &cluster->khm );183 184 #if( DEBUG_CLUSTER_INIT & 1 )185 cycle = (uint32_t)hal_get_cycles();186 if( DEBUG_CLUSTER_INIT < cycle )187 printk("\n[%s] KHM initialized in cluster %x at cycle %d\n",188 __FUNCTION__ , local_cxy , hal_get_cycles() );189 180 #endif 190 181 -
trunk/kernel/kern/cluster.h
r657 r683 2 2 * cluster.h - Cluster-Manager definition 3 3 * 4 * authors Ghassan Almaless (2008,2009,2010,2011,2012)4 * authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016,2017,2018,2019,2019,2020)6 * Alain Greiner (2016,2017,2018,2019,2020) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 39 39 #include <ppm.h> 40 40 #include <kcm.h> 41 #include <khm.h>42 41 #include <rpc.h> 43 42 #include <core.h> … … 105 104 uint32_t x_size; /*! number of clusters in a row (can be 1) */ 106 105 uint32_t y_size; /*! number of clusters in a column (can be 1) */ 107 cxy_t io_cxy; /*! io cluster identifier */ 106 uint32_t io_cxy; /*! io cluster identifier */ 107 uint32_t sys_clk; /*! system_clock frequency (in Hertz) */ 108 108 uint32_t dqdt_root_level; /*! index of root node in dqdt_tbl[] */ 109 109 uint32_t nb_txt_channels; /*! number of TXT channels */ … … 124 124 list_entry_t dev_root; /*! root of list of devices in cluster */ 125 125 126 // memory allocators 127 ppm_t ppm; /*! embedded kernel page manager */ 128 khm_t khm; /*! embedded kernel heap manager */ 129 kcm_t kcm[6]; /*! embedded kernel cache managers [6:11] */ 126 // physical memory allocators: one PPM and severa KCM 127 ppm_t ppm; 128 kcm_t kcm[CONFIG_PPM_PAGE_ORDER - CONFIG_CACHE_LINE_ORDER]; 130 129 131 130 // RPC -
trunk/kernel/kern/core.c
r669 r683 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017,2018)5 * Alain Greiner (2016,2017,2018,2019,2020) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 47 47 core->ticks_nr = 0; 48 48 core->usage = 0; 49 core->spurious_irqs = 0;50 49 core->fpu_owner = NULL; 51 50 core->rand_last = hal_time_stamp() & 0xFFF; … … 55 54 56 55 // initialise the alarms lock 57 busylock_init( &core->alarms_lock, LOCK_CORE_ALARMS );56 remote_busylock_init( XPTR( local_cxy , &core->alarms_lock ) , LOCK_CORE_ALARMS ); 58 57 59 58 // initialise the alarms list … … 61 60 } 62 61 63 /////////////////////////////////////// 64 void core_check_alarms( core_t * core ) 62 //////////////////////////////////////////////////////////////////////////////////// 63 // This static function checks the alarms registered in the core, and calls the 64 // relevant alarm handler for all alarms whose time is elapded. 65 // It does not take the lock protecting the alarm list, because it access only 66 // the first alarm in the list, and all modifications in he list are done 67 // the low level access functions called by the handler(s). 68 //////////////////////////////////////////////////////////////////////////////////// 69 static void core_check_alarms( core_t * core ) 65 70 { 66 71 alarm_handler_t * handler; … … 72 77 if( list_is_empty( root ) ) return; 73 78 74 // get pointer on first alarm when list non empty 75 alarm_t * alarm = LIST_FIRST( root , alarm_t , list ); 76 77 // get first alarm date 78 cycle_t alarm_date = alarm->date; 79 80 // get current date 81 cycle_t current_date = hal_get_cycles(); 82 83 if( current_date >= alarm_date ) 79 while( 1 ) 84 80 { 85 // get pointer on registered alarm handler 86 handler = (alarm_handler_t *)alarm->func_ptr; 87 88 // call alarm handler 89 handler( alarm->args_xp ); 81 // get pointer on first alarm 82 alarm_t * alarm = LIST_FIRST( root , alarm_t , list ); 83 84 // get first alarm date 85 cycle_t alarm_date = alarm->date; 86 87 // get current date 88 cycle_t current_date = hal_get_cycles(); 89 90 // call handler if delay elapsed, and retry 91 if( current_date >= alarm_date ) 92 { 93 // get pointer on registered alarm handler 94 handler = (alarm_handler_t *)alarm->func_ptr; 95 96 // call alarm handler 97 handler( alarm->args_xp ); 98 } 99 else // exit loop when first alarm delay not elapsed 100 { 101 break; 102 } 90 103 } 91 104 } // end core_check_alarms() … … 127 140 uint32_t * tm_us ) 128 141 { 129 *tm_s = (core->ticks_nr*CONFIG_SCHED_TICK_MS_PERIOD)/1000; 130 *tm_us = (core->ticks_nr*CONFIG_SCHED_TICK_MS_PERIOD*1000)%1000000; 142 // get number of cycles 143 uint64_t cycles = core->cycles; 144 145 // get number of cycles per second 146 uint32_t cycles_per_second = LOCAL_CLUSTER->sys_clk; 147 148 *tm_s = cycles / cycles_per_second; 149 *tm_us = (cycles * 1000000) % cycles_per_second; 131 150 } 132 151 … … 139 158 ticks = core->ticks_nr++; 140 159 160 // handle alarms 161 core_check_alarms( core ); 162 141 163 // handle scheduler 142 164 if( (ticks % CONFIG_SCHED_TICKS_PER_QUANTUM) == 0 ) sched_yield( "TICK"); 143 144 // handle alarms145 core_check_alarms( core );146 165 } 147 166 -
trunk/kernel/kern/core.h
r669 r683 39 39 40 40 /**************************************************************************************** 41 * This structure defines the core descriptor. 42 * Besides the core identifiers (gid,lid), it contains an embedded private scheduler. 41 * This structure defines a core descriptor. 42 * Besides the core identifiers (gid,lid), it contains an embedded private scheduler 43 * and a software cycles counter on 64 bits. 44 * It contains also the root of local list of alarms, dynamically registered by the 45 * threads running on this core. This local list is protected by a remote_busylock, 46 * because it can be accessed by any thread, running in any cluster, and using the 47 * access functions defined in the <alarm.c> & <alarm.h> files. 43 48 * It contains an architecture specific extension to store the interrupt vector(s). 44 49 * The core_init()function must allocate memory for this extension, depending on the … … 51 56 gid_t gid; /*! core global identifier (hardware index) */ 52 57 58 scheduler_t scheduler; /*! embedded private scheduler */ 59 53 60 uint64_t cycles; /*! total number of cycles (from hard reset) */ 54 61 uint32_t time_stamp; /*! previous time stamp (read from register) */ 55 62 56 63 list_entry_t alarms_root; /*! root of list of attached alarms */ 57 busylock_talarms_lock; /*! lock protecting the list of alarms */64 remote_busylock_t alarms_lock; /*! lock protecting the list of alarms */ 58 65 59 66 uint32_t ticks_nr; /*! number of elapsed ticks */ 60 67 uint32_t usage; /*! cumulated busy_percent (idle / total) */ 61 uint32_t spurious_irqs; /*! for instrumentation... */62 68 struct thread_s * fpu_owner; /*! pointer on current FPU owner thread */ 63 69 uint32_t rand_last; /*! last computed random value */ 64 65 scheduler_t scheduler; /*! embedded private scheduler */66 70 67 71 void * pic_extend; /*! PIC implementation specific extension */ -
trunk/kernel/kern/do_syscall.c
r669 r683 2 2 * do_syscall.c - architecture independant entry-point for system calls. 3 3 * 4 * Author Alain Greiner (2016,2017,2018, 2019)4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 43 43 /////////////////////////////////////////////////////////////////////////////////////// 44 44 // This array of pointers define the kernel functions implementing the syscalls. 45 // It must be kept consistent with the enum in "syscalls_numbers.h" file. 45 // It must be kept consistent with the enum in <syscalls_numbers.h> file, 46 // and with the SYS_OBJs defined in the kernel <Makefile>. 46 47 /////////////////////////////////////////////////////////////////////////////////////// 47 48 … … 94 95 sys_wait, // 39 95 96 96 sys_get _config,// 4097 sys_ get_core_id,// 4198 sys_ get_cycle,// 4299 sys_ display,// 43100 sys_ place_fork,// 44101 sys_t hread_sleep,// 45102 sys_ thread_wakeup,// 46103 sys_ trace, // 47104 sys_f g,// 48105 sys_ is_fg, // 4997 sys_get, // 40 98 sys_display, // 41 99 sys_place_fork, // 42 100 sys_thread_sleep, // 43 101 sys_thread_wakeup, // 44 102 sys_trace, // 45 103 sys_fg, // 46 104 sys_is_fg, // 47 105 sys_fbf, // 48 106 sys_undefined, // 49 // 106 107 107 108 sys_exit, // 50 108 109 sys_sync, // 51 109 110 sys_fsync, // 52 110 sys_get_best_core, // 53 111 sys_get_nb_cores, // 54 112 sys_get_thread_info, // 55 113 sys_fbf, // 56 114 sys_socket, // 57 111 sys_socket, // 53 115 112 }; 116 113 … … 164 161 case SYS_WAIT: return "WAIT"; // 39 165 162 166 case SYS_GET_CONFIG: return "GET_CONFIG"; // 40 167 case SYS_GET_CORE_ID: return "GET_CORE_ID"; // 41 168 case SYS_GET_CYCLE: return "GET_CYCLE"; // 42 169 case SYS_DISPLAY: return "DISPLAY"; // 43 170 case SYS_PLACE_FORK: return "PLACE_FORK"; // 44 171 case SYS_THREAD_SLEEP: return "THREAD_SLEEP"; // 45 172 case SYS_THREAD_WAKEUP: return "THREAD_WAKEUP"; // 46 173 case SYS_TRACE: return "TRACE"; // 47 174 case SYS_FG: return "FG"; // 48 175 case SYS_IS_FG: return "IS_FG"; // 49 163 case SYS_GET: return "GET"; // 40 164 case SYS_DISPLAY: return "DISPLAY"; // 41 165 case SYS_PLACE_FORK: return "PLACE_FORK"; // 42 166 case SYS_THREAD_SLEEP: return "THREAD_SLEEP"; // 43 167 case SYS_THREAD_WAKEUP: return "THREAD_WAKEUP"; // 44 168 case SYS_TRACE: return "TRACE"; // 45 169 case SYS_FG: return "FG"; // 46 170 case SYS_IS_FG: return "IS_FG"; // 47 171 case SYS_FBF: return "FBF"; // 48 176 172 177 173 case SYS_EXIT: return "EXIT"; // 50 178 174 case SYS_SYNC: return "SYNC"; // 51 179 175 case SYS_FSYNC: return "FSYNC"; // 52 180 case SYS_GET_BEST_CORE: return "GET_BEST_CORE"; // 53 181 case SYS_GET_NB_CORES: return "GET_NB_CORES"; // 54 182 case SYS_GET_THREAD_INFO: return "GET_THREAD_INFO"; // 55 183 case SYS_FBF: return "FBF"; // 56 184 case SYS_SOCKET: return "SOCKET"; // 57 176 case SYS_SOCKET: return "SOCKET"; // 53 185 177 186 178 default: return "undefined"; -
trunk/kernel/kern/kernel_init.c
r669 r683 3 3 * 4 4 * Authors : Mohamed Lamine Karaoui (2015) 5 * Alain Greiner (2016,2017,2018,2019,2020)5 * Alain Greiner (2016,2017,2018,2019,2020) 6 6 * 7 7 * Copyright (c) Sorbonne Universites … … 46 46 #include <memcpy.h> 47 47 #include <ppm.h> 48 #include <kcm.h> 48 49 #include <page.h> 49 50 #include <chdev.h> … … 379 380 if( func == DEV_FUNC_MMC ) 380 381 { 381 382 // check channels383 if( channels != 1 )384 {385 printk("\n[PANIC] in %s : MMC device must be single channel\n",386 __FUNCTION__ );387 hal_core_sleep();388 }389 390 382 // create chdev in local cluster 391 383 chdev_ptr = chdev_create( func, … … 394 386 false, // direction 395 387 base ); 396 397 // check memory398 388 if( chdev_ptr == NULL ) 399 389 { … … 403 393 } 404 394 395 #if (DEBUG_KERNEL_INIT & 0x1) 396 if( hal_time_stamp() > DEBUG_KERNEL_INIT ) 397 printk("\n[%s] created chdev[%x,%x] for MMC\n", 398 __FUNCTION__ , local_cxy , chdev_ptr ); 399 #endif 405 400 // make MMC specific initialisation 406 401 dev_mmc_init( chdev_ptr ); … … 423 418 #if( DEBUG_KERNEL_INIT & 0x1 ) 424 419 if( hal_time_stamp() > DEBUG_KERNEL_INIT ) 425 printk("\n[%s] : created MMC in cluster %x / chdev = %x\n",420 printk("\n[%s] initialised chdev[%x,%x] for MMC\n", 426 421 __FUNCTION__ , local_cxy , chdev_ptr ); 427 422 #endif … … 439 434 false, // direction 440 435 base ); 441 442 // check memory443 436 if( chdev_ptr == NULL ) 444 437 { … … 448 441 } 449 442 443 #if (DEBUG_KERNEL_INIT & 0x1) 444 if( hal_time_stamp() > DEBUG_KERNEL_INIT ) 445 printk("\n[%s] cxy %x : created chdev[%x,%x] for DMA[%d]\n", 446 __FUNCTION__ , local_cxy , chdev_ptr , channel ); 447 #endif 450 448 // make DMA specific initialisation 451 449 dev_dma_init( chdev_ptr ); … … 457 455 #if( DEBUG_KERNEL_INIT & 0x1 ) 458 456 if( hal_time_stamp() > DEBUG_KERNEL_INIT ) 459 printk("\n[%s] : created DMA[%d] in cluster %x / chdev = %x\n",460 __FUNCTION__ , channel , local_cxy , chdev_ptr);457 printk("\n[%s] initialised chdev[%x,%x] for DMA[%d]\n", 458 __FUNCTION__ , local_cxy , chdev_ptr , channel ); 461 459 #endif 462 460 } … … 471 469 // These chdev descriptors are distributed on all clusters, using a modulo on a global 472 470 // index, identically computed in all clusters. 473 // This function is executed in all clusters by the core[0] core, that computes a global index474 // for all external chdevs. Each core[0] core creates only the chdevs that must be placed in475 // the local cluster, because the global index matches the local index.471 // This function is executed in all clusters by the core[0], that computes a global index 472 // for all external chdevs. Each core[0] core creates only the chdevs that must be placed 473 // in the local cluster, because the global index matches the local index. 476 474 // The relevant entries in all copies of the devices directory are initialised. 477 475 /////////////////////////////////////////////////////////////////////////////////////////// … … 499 497 dev_tbl = info->ext_dev; 500 498 501 // initializes global index (PIC is already placed in cluster 0 499 // initializes global index (PIC is already placed in cluster 0) 502 500 ext_chdev_gid = 1; 503 501 … … 529 527 530 528 // check external device functionnal type 531 if( (func != DEV_FUNC_IOB) && (func != DEV_FUNC_IOC) && (func != DEV_FUNC_TXT) && 532 (func != DEV_FUNC_NIC) && (func != DEV_FUNC_FBF) ) 529 if( (func != DEV_FUNC_IOB) && 530 (func != DEV_FUNC_IOC) && 531 (func != DEV_FUNC_TXT) && 532 (func != DEV_FUNC_NIC) && 533 (func != DEV_FUNC_FBF) ) 533 534 { 534 535 printk("\n[PANIC] in %s : undefined peripheral type\n", … … 537 538 } 538 539 539 // loop son channels540 // loop on channels 540 541 for( channel = 0 ; channel < channels ; channel++ ) 541 542 { … … 547 548 548 549 // all kernel instances compute the target cluster for all chdevs, 549 // computingthe global index ext_chdev_gid[func,channel,direction]550 // and the global index ext_chdev_gid[func,channel,direction] 550 551 cxy_t target_cxy; 551 552 while( 1 ) … … 568 569 if( target_cxy == local_cxy ) 569 570 { 570 571 #if( DEBUG_KERNEL_INIT & 0x3 )572 if( hal_time_stamp() > DEBUG_KERNEL_INIT )573 printk("\n[%s] : found chdev %s / channel = %d / rx = %d / cluster %x\n",574 __FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy );575 #endif576 571 chdev = chdev_create( func, 577 572 impl, … … 587 582 } 588 583 584 #if (DEBUG_KERNEL_INIT & 0x1) 585 if( hal_time_stamp() > DEBUG_KERNEL_INIT ) 586 printk("\n[%s] created chdev[%x,%x] for %s[%d] / is_rx %d\n", 587 __FUNCTION__ , local_cxy , chdev , chdev_func_str(func) , channel , rx ); 588 #endif 589 589 // make device type specific initialisation 590 590 if ( func == DEV_FUNC_IOB ) dev_iob_init( chdev ); … … 621 621 } 622 622 623 #if( DEBUG_KERNEL_INIT & 0x3)623 #if( DEBUG_KERNEL_INIT & 1 ) 624 624 if( hal_time_stamp() > DEBUG_KERNEL_INIT ) 625 printk("\n[%s] : created chdev %s / channel = %d / rx = %d / cluster %x / chdev = %x\n", 626 __FUNCTION__ , chdev_func_str( func ), channel , rx , local_cxy , chdev ); 627 #endif 625 printk("\n[%s] initialised chdev[%x,%x] for %s\n", 626 __FUNCTION__ , local_cxy, chdev , chdev->name ); 627 #endif 628 628 629 } // end if match 629 630 … … 637 638 638 639 /////////////////////////////////////////////////////////////////////////////////////////// 639 // This function is called by core[0] in cluster 0to allocate memory and initialize the PIC640 // This function is called by core[0][0] to allocate memory and initialize the PIC 640 641 // device, namely the informations attached to the external IOPIC controller, that 641 642 // must be replicated in all clusters (struct iopic_input). … … 1102 1103 // and allocates memory for the corresponding chdev descriptors. 1103 1104 if( core_lid == 0 ) internal_devices_init( info ); 1104 1105 1105 1106 1106 // All core[0]s contribute to initialise external peripheral chdev descriptors. … … 1494 1494 " - core descriptor : %d bytes\n" 1495 1495 " - scheduler : %d bytes\n" 1496 " - socket 1496 " - socket descriptor : %d bytes\n" 1497 1497 " - rpc fifo : %d bytes\n" 1498 1498 " - page descriptor : %d bytes\n" … … 1501 1501 " - ppm manager : %d bytes\n" 1502 1502 " - kcm manager : %d bytes\n" 1503 " - khm manager : %d bytes\n"1504 1503 " - vmm manager : %d bytes\n" 1505 1504 " - vfs inode : %d bytes\n" … … 1529 1528 sizeof( ppm_t ), 1530 1529 sizeof( kcm_t ), 1531 sizeof( khm_t ),1532 1530 sizeof( vmm_t ), 1533 1531 sizeof( vfs_inode_t ), … … 1546 1544 #endif 1547 1545 1546 // number of cycles per TICK (depends on the actual system clock frequency 1547 uint32_t cycles_per_tick = cluster->sys_clk / CONFIG_SCHED_TICKS_PER_SECOND; 1548 1548 1549 // each core activates its private TICK IRQ 1549 dev_pic_enable_timer( CONFIG_SCHED_TICK_MS_PERIOD);1550 dev_pic_enable_timer( cycles_per_tick ); 1550 1551 1551 1552 ///////////////////////////////////////////////////////////////////////////////// -
trunk/kernel/kern/ksocket.c
r669 r683 1 1 /* 2 * ksocket.c - kernel socket APIimplementation.2 * ksocket.c - kernel socket implementation. 3 3 * 4 * Authors Alain Greiner (2016,2017,2018,2019,2020)4 * Authors Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 117 117 switch( sts ) 118 118 { 119 case CMD_STS_SUCCESS : return " TX_CONNECT";119 case CMD_STS_SUCCESS : return "SUCCESS"; 120 120 case CMD_STS_EOF : return "EOF"; 121 121 case CMD_STS_RST : return "RST"; … … 135 135 // and request the NIC_TX server thread to re-send the unacknowledged segment. 136 136 /////////////////////////////////////////////////////////////////////////////////////////// 137 // @ args_xp : extended pointer on the involved socket.137 // @ sock_xp : extended pointer on the involved socket. 138 138 /////////////////////////////////////////////////////////////////////////////////////////// 139 static void __attribute__((noinline)) socket_alarm_handler( xptr_t args_xp )139 static void __attribute__((noinline)) socket_alarm_handler( xptr_t sock_xp ) 140 140 { 141 141 // get cluster and local pointer on socket descriptor 142 socket_t * sock_ptr = GET_PTR( args_xp ); 143 cxy_t sock_cxy = GET_CXY( args_xp ); 142 socket_t * sock_ptr = GET_PTR( sock_xp ); 143 cxy_t sock_cxy = GET_CXY( sock_xp ); 144 145 #if DEBUG_SOCKET_ALARM 146 uint32_t cycle = (uint32_t)hal_get_cycles(); 147 #endif 148 149 // build extended pointer on lock protecting socket 150 xptr_t socket_lock_xp = XPTR( sock_cxy , &sock_ptr->lock ); 151 152 // take the socket lock 153 remote_queuelock_acquire( socket_lock_xp ); 144 154 145 155 // get relevant infos from socket descriptor … … 151 161 "illegal tx_client field for a retransmission timeout" ); 152 162 153 // get TX client thread cluster and local pointer 154 thread_t * thread_ptr = GET_PTR( thread_xp ); 163 // get TX client thread cluster 155 164 cxy_t thread_cxy = GET_CXY( thread_xp ); 156 165 … … 168 177 169 178 // update the date in alarm 170 alarm_update( thread_ ptr , hal_get_cycles() + TCP_RETRANSMISSION_TIMEOUT );179 alarm_update( thread_xp , hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT ); 171 180 172 181 ////////////////////////////// … … 175 184 176 185 #if DEBUG_SOCKET_ALARM 177 uint32_t cycle = (uint32_t)hal_get_cycles(); 178 printk("\n[%s] rings for TX_CONNECT : request a new SYN segment / cycle %d\n",186 if( DEBUG_SOCKET_ALARM < cycle ) 187 printk("\n[%s] rings for CONNECT : request a new SYN segment / cycle %d\n", 179 188 __FUNCTION__ , cycle ); 180 189 #endif … … 193 202 194 203 #if DEBUG_SOCKET_ALARM 195 uint32_t cycle = (uint32_t)hal_get_cycles(); 196 printk("\n[%s] rings for TX_ACCEPT : request a new SYN-ACK segment / cycle %d\n",204 if( DEBUG_SOCKET_ALARM < cycle ) 205 printk("\n[%s] rings for ACCEPT : request a new SYN-ACK segment / cycle %d\n", 197 206 __FUNCTION__ , cycle ); 198 207 #endif … … 211 220 212 221 #if DEBUG_SOCKET_ALARM 213 uint32_t cycle = (uint32_t)hal_get_cycles(); 214 printk("\n[%s] rings for TX_CLOSE : request a new FIN-ACK segment / cycle %d\n",222 if( DEBUG_SOCKET_ALARM < cycle ) 223 printk("\n[%s] rings for CLOSE : request a new FIN-ACK segment / cycle %d\n", 215 224 __FUNCTION__ , cycle ); 216 225 #endif … … 227 236 if( tx_cmd == CMD_TX_SEND ) 228 237 { 229 // TODO build a new TX_SEND command 230 } 238 // get get relevant infos from socket pointer 239 uint32_t tx_una = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_una )); 240 uint32_t tx_ack = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_ack )); 241 uint32_t tx_len = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_len )); 242 243 #if DEBUG_SOCKET_ALARM 244 if( DEBUG_SOCKET_ALARM < cycle ) 245 printk("\n[%s] rings for SEND : request %d bytes / cycle %d\n", 246 __FUNCTION__ , tx_len , cycle ); 247 #endif 248 // update command fields in socket 249 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_nxt ) , tx_una ); 250 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_todo ) , tx_len - tx_ack ); 251 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true ); 252 253 // unblock the NIC_TX server thread 254 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 255 } 256 257 // release the socket lock 258 remote_queuelock_release( socket_lock_xp ); 259 231 260 } // end socket_alarm_handler() 232 233 ///////////////////////////////////////////////////////////////////////////////////////////234 // This static function activates the alarm embedded in the calling thread descriptor,235 // using the <date> argument.236 ///////////////////////////////////////////////////////////////////////////////////////////237 // @ delay : number of cycles (from the current absolute date).238 ///////////////////////////////////////////////////////////////////////////////////////////239 static void socket_alarm_start( xptr_t socket_xp,240 uint32_t delay )241 {242 // compute absolute date243 cycle_t date = hal_get_cycles() + delay;244 245 // get pointer on calling threadf246 thread_t * this = CURRENT_THREAD;247 248 // start the alarm249 alarm_start( date,250 &socket_alarm_handler, // func_ptr251 socket_xp, // args_xp252 this );253 }254 255 ///////////////////////////////////////////////////////////////////////////////////////////256 // This static function activates the alarm embedded in the calling thread descriptor,257 // using the <date> argument.258 ///////////////////////////////////////////////////////////////////////////////////////////259 // @ date : absolute date for this alarm.260 ///////////////////////////////////////////////////////////////////////////////////////////261 static void socket_alarm_stop( void )262 {263 // get pointer on calling threadf264 thread_t * this = CURRENT_THREAD;265 266 // stop the alarm267 alarm_stop( this );268 }269 261 270 262 ///////////////////////////////////////////////////////////////////////////////////////// … … 470 462 // associated to a socket: file descriptor, socket descriptor, RX buffer, R2T queue, 471 463 // and CRQ queue. It allocates an fdid, and register it in the process fd_array. 472 // It initialise the thesocket desccriptor static fields, other than local_addr,464 // It initialise the socket desccriptor static fields, other than local_addr, 473 465 // local_port, remote_addr, remote_port), and set the socket state to UNBOUND. 474 466 // It returns the local pointer on socket descriptor and the fdid value in buffers … … 489 481 { 490 482 uint32_t fdid; 491 kmem_req_t req;492 483 socket_t * socket; 493 484 vfs_file_t * file; 494 485 uint32_t state; 486 void * tx_buf; 495 487 error_t error; 488 496 489 497 490 thread_t * this = CURRENT_THREAD; 498 491 process_t * process = this->process; 499 492 493 #if DEBUG_SOCKET_CREATE || DEBUG_SOCKET_ERROR 494 uint32_t cycle = (uint32_t)hal_get_cycles(); 495 #endif 496 500 497 #if DEBUG_SOCKET_CREATE 501 uint32_t cycle = (uint32_t)hal_get_cycles();502 498 if( DEBUG_SOCKET_CREATE < cycle ) 503 499 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", … … 506 502 507 503 // 1. allocate memory for socket descriptor 508 req.type = KMEM_KCM; 509 req.order = bits_log2( sizeof(socket_t) ); 510 req.flags = AF_ZERO; 511 socket = kmem_remote_alloc( cxy , &req ); 504 socket = kmem_remote_alloc( cxy , bits_log2(sizeof(socket_t)) , AF_ZERO ); 512 505 513 506 if( socket == NULL ) 514 507 { 515 printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x]\n", 516 __FUNCTION__, process->pid, this->trdid ); 517 return -1; 518 } 519 520 // 2. allocate memory for rx_buf buffer 508 509 #if DEBUG_SOCKET_ERROR 510 printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x] / cycle %d\n", 511 __FUNCTION__, process->pid, this->trdid, cycle ); 512 #endif 513 return -1; 514 } 515 516 // 2. allocate memory for rx_buf data buffer 521 517 error = remote_buf_init( XPTR( cxy , &socket->rx_buf ), 522 bits_log2( CONFIG_SOCK_RX_BUF_SIZE ));518 CONFIG_SOCK_RX_BUF_ORDER ); 523 519 524 520 if( error ) 525 521 { 526 printk("\n[ERROR] in %s : cannot allocate rx_buf / thread[%x,%x]\n", 527 __FUNCTION__, process->pid, this->trdid ); 528 req.type = KMEM_KCM; 529 req.ptr = socket; 530 kmem_remote_free( cxy , &req ); 531 return -1; 532 } 533 534 // 3. allocate memory for r2tq queue 522 523 #if DEBUG_SOCKET_ERROR 524 printk("\n[ERROR] in %s : no memory for rx_buf / thread[%x,%x] / cycle %d\n", 525 __FUNCTION__, process->pid, this->trdid, cycle ); 526 #endif 527 kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) ); // 1 528 return -1; 529 } 530 531 // 3. allocate memory for tx_buf 532 tx_buf = kmem_remote_alloc( cxy , CONFIG_SOCK_TX_BUF_ORDER , AF_NONE ); 533 534 if( tx_buf == NULL ) 535 { 536 537 #if DEBUG_SOCKET_ERROR 538 printk("\n[ERROR] in %s : no memory for tx_buf / thread[%x,%x] / cycle %d\n", 539 __FUNCTION__, process->pid, this->trdid, cycle ); 540 #endif 541 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); // 2 542 kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) ); // 1 543 return -1; 544 } 545 546 // 4. allocate memory for r2tq queue 535 547 error = remote_buf_init( XPTR( cxy , &socket->r2tq ), 536 548 bits_log2( CONFIG_SOCK_R2T_BUF_SIZE ) ); 537 549 if( error ) 538 550 { 539 printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n", 540 __FUNCTION__, process->pid, this->trdid ); 541 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); 542 req.type = KMEM_KCM; 543 req.ptr = socket; 544 kmem_remote_free( cxy , &req ); 545 return -1; 546 } 547 548 // don't allocate memory for crqq queue, as it is done by the socket_listen function 549 550 // 4. allocate memory for file descriptor 551 req.type = KMEM_KCM; 552 req.order = bits_log2( sizeof(vfs_file_t) ); 553 req.flags = AF_ZERO; 554 file = kmem_remote_alloc( cxy , &req ); 551 552 #if DEBUG_SOCKET_ERROR 553 printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x] / cycle %d\n", 554 __FUNCTION__, process->pid, this->trdid, cycle ); 555 #endif 556 kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER ); // 3 557 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); // 2 558 kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) ); // 1 559 return -1; 560 } 561 562 // don't allocate memory for CRQ queue / done by the socket_listen function 563 564 // 5. allocate memory for file descriptor 565 file = kmem_remote_alloc( cxy , bits_log2(sizeof(vfs_file_t)) , AF_ZERO ); 555 566 556 567 if( file == NULL ) 557 568 { 558 printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n", 559 __FUNCTION__, process->pid, this->trdid ); 560 remote_buf_release_data( XPTR( cxy , &socket->r2tq ) ); 561 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); 562 req.type = KMEM_KCM; 563 req.ptr = socket; 564 kmem_remote_free( cxy , &req ); 569 570 #if DEBUG_SOCKET_ERROR 571 printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x] / cycle %d\n", 572 __FUNCTION__, process->pid, this->trdid, cycle ); 573 #endif 574 remote_buf_release_data( XPTR( cxy , &socket->r2tq ) ); // 4 575 kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER ); // 3 576 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); // 2 577 kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) ); // 1 565 578 return -1; 566 579 } 567 580 568 // 5. get an fdid value, and register file descriptor in fd_array[]581 // 6. get an fdid value, and register file descriptor in fd_array[] 569 582 error = process_fd_register( process->ref_xp, 570 583 XPTR( cxy , file ), … … 572 585 if ( error ) 573 586 { 574 printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x]\n", 575 __FUNCTION__, process->pid, this->trdid ); 576 req.type = KMEM_KCM; 577 req.ptr = file; 578 kmem_free( &req ); 579 remote_buf_release_data( XPTR( cxy , &socket->r2tq ) ); 580 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); 581 req.ptr = socket; 582 kmem_free( &req ); 587 588 #if DEBUG_SOCKET_ERROR 589 if( DEBUG_SOCKET_ERROR < cycle ) 590 printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x] / cycle %d\n", 591 __FUNCTION__, process->pid, this->trdid, cycle ); 592 #endif 593 kmem_remote_free( cxy , file , bits_log2(sizeof(vfs_file_t)) ); // 5 594 remote_buf_release_data( XPTR( cxy , &socket->r2tq ) ); // 4 595 kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER ); // 3 596 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); // 2 597 kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) ); // 1 583 598 return -1; 584 599 } … … 597 612 hal_remote_s32( XPTR( cxy , &socket->rx_valid ) , false ); 598 613 hal_remote_s32( XPTR( cxy , &socket->nic_channel ) , 0 ); 614 hal_remote_spt( XPTR( cxy , &socket->tx_buf ) , tx_buf ); 599 615 600 616 // initialize file descriptor … … 606 622 607 623 #if DEBUG_SOCKET_CREATE 624 cycle = (uint32_t)hal_get_cycles(); 608 625 if( DEBUG_SOCKET_CREATE < cycle ) 609 626 printk("\n[%s] thread[%x,%x] exit / socket[%x,%d] / xptr[%x,%x] / cycle %d\n", … … 631 648 static void socket_destroy( xptr_t file_xp ) 632 649 { 633 kmem_req_t req;634 635 650 thread_t * this = CURRENT_THREAD; 636 651 process_t * process = this->process; … … 677 692 678 693 // release memory allocated for file descriptor 679 req.type = KMEM_KCM; 680 req.ptr = file_ptr; 681 kmem_remote_free( file_cxy , &req ); 694 kmem_remote_free( file_cxy , file_ptr , bits_log2(sizeof(vfs_file_t)) ); 682 695 683 696 // release memory allocated for buffers attached to socket descriptor … … 687 700 688 701 // release memory allocated for socket descriptor 689 req.type = KMEM_KCM; 690 req.ptr = socket_ptr; 691 kmem_remote_free( file_cxy , &req ); 702 kmem_remote_free( file_cxy , socket_ptr , bits_log2(sizeof(socket_t)) ); 692 703 693 704 #if DEBUG_SOCKET_DESTROY … … 702 713 //////////////////////////////////////////////// 703 714 void socket_put_r2t_request( xptr_t queue_xp, 704 uint 32_tflags,715 uint8_t flags, 705 716 uint32_t channel ) 706 717 { … … 715 726 // try to register R2T request 716 727 error_t error = remote_buf_put_from_kernel( queue_xp, 717 (uint8_t *)(&flags),728 &flags, 718 729 1 ); 719 730 if( error ) … … 740 751 } 741 752 } // end socket_put_r2t_request() 753 754 /////////////////////////////////////////////////// 755 error_t socket_get_r2t_request( xptr_t queue_xp, 756 uint8_t * flags ) 757 { 758 // get one request from R2T queue 759 return remote_buf_get_to_kernel( queue_xp, 760 flags, 761 1 ); 762 } // end socket_get_r2T_request() 742 763 743 764 /////////////////////////////////////////////////// … … 843 864 process_t * process = this->process; 844 865 866 #if DEBUG_SOCKET_BIND || DEBUG_SOCKET_ERROR 867 uint32_t cycle = (uint32_t)hal_get_cycles(); 868 #endif 869 845 870 #if DEBUG_SOCKET_BIND 846 uint32_t cycle = (uint32_t)hal_get_cycles();847 871 if( DEBUG_SOCKET_BIND < cycle ) 848 872 printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / addr %x / port %x / cycle %d\n", … … 858 882 if( file_xp == XPTR_NULL ) 859 883 { 860 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n", 861 __FUNCTION__, fdid, process->pid, this->trdid ); 884 885 #if DEBUG_SOCKET_ERROR 886 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d\n", 887 __FUNCTION__, fdid, process->pid, this->trdid, cycle ); 888 #endif 862 889 return -1; 863 890 } … … 869 896 if( file_type != FILE_TYPE_SOCK ) 870 897 { 871 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]", 872 __FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid ); 898 899 #if DEBUG_SOCKET_ERROR 900 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d", 901 __FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid, cycle ); 902 #endif 873 903 return -1; 874 904 } … … 918 948 process_t * process = this->process; 919 949 950 #if DEBUG_SOCKET_LISTEN || DEBUG_SOCKET_ERROR 951 uint32_t cycle = (uint32_t)hal_get_cycles(); 952 #endif 953 920 954 #if DEBUG_SOCKET_LISTEN 921 uint32_t cycle = (uint32_t)hal_get_cycles();922 955 if( DEBUG_SOCKET_LISTEN < cycle ) 923 956 printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / crq_depth %x / cycle %d\n", … … 933 966 if( file_xp == XPTR_NULL ) 934 967 { 935 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n", 936 __FUNCTION__, fdid, process->pid, this->trdid ); 968 969 #if DEBUG_SOCKET_ERROR 970 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d\n", 971 __FUNCTION__, fdid, process->pid, this->trdid, cycle ); 972 #endif 937 973 return -1; 938 974 } … … 944 980 if( file_type != FILE_TYPE_SOCK ) 945 981 { 946 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n", 947 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid ); 982 983 #if DEBUG_SOCKET_ERROR 984 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d\n", 985 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid, cycle ); 986 #endif 948 987 return -1; 949 988 } … … 958 997 if( socket_type != SOCK_STREAM ) 959 998 { 960 printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n", 961 __FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid ); 999 1000 #if DEBUG_SOCKET_ERROR 1001 printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x] / cycle %d\n", 1002 __FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid, cycle ); 1003 #endif 962 1004 return -1; 963 1005 } … … 966 1008 if( socket_state != TCP_STATE_BOUND ) 967 1009 { 968 printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n", 969 __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid ); 1010 1011 #if DEBUG_SOCKET_ERROR 1012 printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x] / cycle %d\n", 1013 __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid, cycle ); 1014 #endif 970 1015 return -1; 971 1016 } … … 980 1025 if( error ) 981 1026 { 982 printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x]\n", 983 __FUNCTION__, process->pid, this->trdid ); 1027 1028 #if DEBUG_SOCKET_ERROR 1029 printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x] / cycle %d\n", 1030 __FUNCTION__, process->pid, this->trdid, cycle ); 1031 #endif 984 1032 return -1; 985 1033 } … … 1011 1059 vfs_file_t * file_ptr; 1012 1060 cxy_t file_cxy; 1013 vfs_file_type_t file_type; // file descriptor type1061 vfs_file_type_t file_type; // file descriptor type 1014 1062 socket_t * socket_ptr; // local pointer on remote waiting socket 1015 1063 uint32_t socket_type; // listening socket type … … 1045 1093 process_t * process = this->process; 1046 1094 1047 #if DEBUG_SOCKET_ACCEPT 1095 #if DEBUG_SOCKET_ACCEPT || DEBUG_SOCKET_ERROR 1048 1096 uint32_t cycle = (uint32_t)hal_get_cycles(); 1097 #endif 1098 1099 #if DEBUG_SOCKET_ACCEPT 1049 1100 if( DEBUG_SOCKET_ACCEPT < cycle ) 1050 1101 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / cycle %d\n", … … 1060 1111 if( file_xp == XPTR_NULL ) 1061 1112 { 1062 printk("\n[ERROR] in %s : undefined fdid %d", 1063 __FUNCTION__, fdid ); 1113 1114 #if DEBUG_SOCKET_ERROR 1115 printk("\n[ERROR] in %s : undefined fdid %d / thead[%x,%x] / cycle %d", 1116 __FUNCTION__, fdid, process->pid, this->trdid, cycle ); 1117 #endif 1064 1118 return -1; 1065 1119 } … … 1071 1125 if( file_type != FILE_TYPE_SOCK ) 1072 1126 { 1073 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n", 1074 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid ); 1127 1128 #if DEBUG_SOCKET_ERROR 1129 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d\n", 1130 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid, cycle ); 1131 #endif 1075 1132 return -1; 1076 1133 } … … 1097 1154 if( socket_type != SOCK_STREAM ) 1098 1155 { 1099 // release listening socket lock 1156 1157 #if DEBUG_SOCKET_ERROR 1158 printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x] / cycle %d\n", 1159 __FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid, cycle ); 1160 #endif 1100 1161 remote_queuelock_release( socket_lock_xp ); 1101 1102 printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n",1103 __FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid );1104 1162 return -1; 1105 1163 } … … 1108 1166 if( socket_state != TCP_STATE_LISTEN ) 1109 1167 { 1110 // release listening socket lock 1168 1169 #if DEBUG_SOCKET_ERROR 1170 printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x] / cycle %d\n", 1171 __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid, cycle ); 1172 #endif 1111 1173 remote_queuelock_release( socket_lock_xp ); 1112 1113 printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n",1114 __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid );1115 1174 return -1; 1116 1175 } … … 1119 1178 if( (socket_rx_valid == true) || (socket_rx_client != XPTR_NULL) ) 1120 1179 { 1121 // release listening socket lock 1180 1181 #if DEBUG_SOCKET_ERROR 1182 printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1183 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 1184 #endif 1122 1185 remote_queuelock_release( socket_lock_xp ); 1123 1124 printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x]\n",1125 __FUNCTION__, process->pid, fdid, process->pid, this->trdid );1126 1186 return -1; 1127 1187 } … … 1130 1190 if( (socket_tx_valid == true) || (socket_tx_client != XPTR_NULL) ) 1131 1191 { 1132 // release socket lock 1192 1193 #if DEBUG_SOCKET_ERROR 1194 printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1195 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 1196 #endif 1133 1197 remote_queuelock_release( socket_lock_xp ); 1134 1135 printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n", 1136 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1137 return -1; 1138 } 1139 1140 // 2) build extended pointer on listening socket.crq 1198 return -1; 1199 } 1200 1201 // 2) check the listenig socket CRQ 1141 1202 crq_xp = XPTR( file_cxy , &socket_ptr->crqq ); 1142 1203 … … 1144 1205 crq_status = remote_buf_status( crq_xp ); 1145 1206 1146 // block & deschedule when CRQ empty1207 // block & deschedule to wait a client request when CRQ empty 1147 1208 if( crq_status == 0 ) 1148 1209 { 1149 // register command arguments in listening socket1210 // register command arguments for NIC_RX server in listening socket 1150 1211 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_cmd ), CMD_RX_ACCEPT ); 1151 1212 hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ), client_xp ); … … 1179 1240 crq_status = remote_buf_status( crq_xp ); 1180 1241 1181 assert( __FUNCTION__, (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)), 1242 assert( __FUNCTION__, 1243 (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)), 1182 1244 "illegal socket state when client thread resumes after RX_ACCEPT" ); 1183 1245 … … 1187 1249 if( cmd_status != CMD_STS_SUCCESS ) 1188 1250 { 1189 // release socket lock 1251 1252 #if DEBUG_SOCKET_ERROR 1253 printk("\n[ERROR] in %s : reported for RX / socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1254 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 1255 #endif 1190 1256 remote_queuelock_release( socket_lock_xp ); 1191 1192 printk("\n[ERROR] in %s for RX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n",1193 __FUNCTION__, process->pid, fdid, process->pid, this->trdid );1194 1257 return -1; 1195 1258 } 1196 1197 // extract first request from the listening socket CRQ 1198 error = socket_get_crq_request( crq_xp, 1259 } // end blocking on CRQ empty 1260 1261 // from this point, we can extract a request from listening socket CRQ 1262 error = socket_get_crq_request( crq_xp, 1199 1263 &new_remote_addr, 1200 1264 &new_remote_port, 1201 1265 &new_remote_iss, 1202 1266 &new_remote_window ); 1203 1204 1267 assert( __FUNCTION__, (error == 0), 1205 1268 "cannot get a connection request from a non-empty CRQ" ); 1206 1269 1207 // reset listening socket rx_client 1208 hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL ); 1209 1210 // release socket lock 1211 remote_queuelock_release( socket_lock_xp ); 1212 1213 } // end blocking on CRQ status 1214 1215 // from this point, we can create a new socket 1216 // and ask the NIC_TX to send a SYN-ACK segment 1270 // release listening socket lock 1271 remote_queuelock_release( socket_lock_xp ); 1217 1272 1218 1273 #if DEBUG_SOCKET_ACCEPT 1219 1274 cycle = (uint32_t)hal_get_cycles(); 1220 1275 if( DEBUG_SOCKET_ACCEPT < cycle ) 1221 printk("\n[%s] thread[%x,%x] socket[%x,%d] / got a CRQ request / cycle %d\n", 1222 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1276 printk("\n[%s] thread[%x,%x] socket[%x,%d] / CRQ request [addr %x / port %x] / cycle %d\n", 1277 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, 1278 new_remote_addr, new_remote_port, cycle ); 1223 1279 #endif 1224 1280 … … 1234 1290 if( error ) 1235 1291 { 1236 printk("\n[ERROR] in %s : cannot allocate new socket / thread[%x,%x]\n", 1237 __FUNCTION__, process->pid, this->trdid ); 1292 1293 #if DEBUG_SOCKET_ERROR 1294 printk("\n[ERROR] in %s : cannot create new socket / thread[%x,%x] / cycle %d\n", 1295 __FUNCTION__, process->pid, this->trdid, cycle ); 1296 #endif 1238 1297 return -1; 1239 1298 } … … 1287 1346 1288 1347 // start retransmission timer 1289 socket_alarm_start( new_socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1348 alarm_start( client_xp, 1349 hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT, 1350 &socket_alarm_handler, 1351 new_socket_xp ); 1290 1352 1291 1353 #if DEBUG_SOCKET_ACCEPT 1292 1354 cycle = (uint32_t)hal_get_cycles(); 1293 1355 if( DEBUG_SOCKET_ACCEPT < cycle ) 1294 printk("\n[%s] thread[%x,%x] new_socket[%x,%d] blocks on <IO> waiting ESTAB/ cycle %d\n",1356 printk("\n[%s] thread[%x,%x] for socket[%x,%d] request SYN-ACK & blocks on <IO> / cycle %d\n", 1295 1357 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle ); 1296 1358 #endif … … 1307 1369 #endif 1308 1370 1309 // stop retransmission timer 1310 socket_alarm_stop();1371 // stop retransmission timer in thread descriptor 1372 alarm_stop( client_xp ); 1311 1373 1312 1374 // get new socket state, tx_valid and tx_sts … … 1315 1377 cmd_status = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_sts )); 1316 1378 1317 assert( __FUNCTION__, (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))1318 1379 assert( __FUNCTION__, 1380 (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1319 1381 "illegal socket state when client thread resumes after TX_ACCEPT" ); 1320 1382 … … 1324 1386 if( cmd_status != CMD_STS_SUCCESS ) 1325 1387 { 1326 printk("\n[ERROR] in %s for TX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n", 1327 __FUNCTION__, process->pid, new_fdid, process->pid, this->trdid ); 1388 1389 #if DEBUG_SOCKET_ERROR 1390 printk("\n[ERROR] in %s reported for TX / socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1391 __FUNCTION__, process->pid, new_fdid, process->pid, this->trdid, cycle ); 1392 #endif 1328 1393 return -1; 1329 1394 } … … 1370 1435 trdid_t trdid = this->trdid; 1371 1436 1437 #if DEBUG_SOCKET_CONNECT || DEBUG_SOCKET_ERROR 1438 uint32_t cycle = (uint32_t)hal_get_cycles(); 1439 #endif 1440 1372 1441 // get pointers on file descriptor 1373 1442 xptr_t file_xp = process_fd_get_xptr_from_local( this->process , fdid ); … … 1378 1447 if( file_xp == XPTR_NULL ) 1379 1448 { 1380 printk("\n[ERROR] in %s : undefined fdid %d", 1381 __FUNCTION__, fdid ); 1449 1450 #if DEBUG_SOCKET_ERROR 1451 printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d", 1452 __FUNCTION__, fdid, pid, trdid, cycle ); 1453 #endif 1382 1454 return -1; 1383 1455 } … … 1388 1460 1389 1461 #if DEBUG_SOCKET_CONNECT 1390 uint32_t cycle = (uint32_t)hal_get_cycles();1391 1462 if( DEBUG_SOCKET_CONNECT < cycle ) 1392 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port % d/ cycle %d\n",1463 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port %x / cycle %d\n", 1393 1464 __FUNCTION__, pid, trdid, pid, fdid, remote_addr, remote_port, cycle ); 1394 1465 #endif … … 1397 1468 if( file_type != FILE_TYPE_SOCK ) 1398 1469 { 1399 printk("\n[ERROR] in %s : illegal file type %s", 1400 __FUNCTION__, vfs_inode_type_str( file_type ) ); 1470 1471 #if DEBUG_SOCKET_ERROR 1472 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d", 1473 __FUNCTION__, vfs_inode_type_str( file_type ), pid, trdid, cycle ); 1474 #endif 1401 1475 return -1; 1402 1476 } … … 1412 1486 if( socket_state != UDP_STATE_BOUND ) 1413 1487 { 1414 printk("\n[ERROR] in %s : illegal socket state %s for type %s", 1415 __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) ); 1488 1489 #if DEBUG_SOCKET_ERROR 1490 printk("\n[ERROR] in %s : illegal socket state %s for type %s / thread[%x,%x] / cycle %d", 1491 __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type), pid, trdid, cycle ); 1492 #endif 1416 1493 return -1; 1417 1494 } … … 1421 1498 if( socket_state != TCP_STATE_BOUND ) 1422 1499 { 1423 printk("\n[ERROR] in %s : illegal socket state %s for type %s", 1424 __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) ); 1500 1501 #if DEBUG_SOCKET_ERROR 1502 printk("\n[ERROR] in %s : illegal socket state %s for type %s / thread[%x,%x] / cycle %d", 1503 __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type), pid, trdid, cycle ); 1504 #endif 1425 1505 return -1; 1426 1506 } … … 1428 1508 else 1429 1509 { 1430 printk("\n[ERROR] in %s : illegal socket type %s", 1431 __FUNCTION__, socket_type_str(socket_type) ); 1510 1511 #if DEBUG_SOCKET_ERROR 1512 printk("\n[ERROR] in %s : illegal socket type / thread[%x,%x] / cycle %d", 1513 __FUNCTION__, pid, trdid, cycle ); 1514 #endif 1432 1515 return -1; 1433 1516 } … … 1475 1558 1476 1559 // start retransmission timer 1477 socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1560 alarm_start( client_xp, 1561 hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT, 1562 &socket_alarm_handler, 1563 socket_xp ); 1478 1564 1479 1565 #if DEBUG_SOCKET_CONNECT … … 1494 1580 #endif 1495 1581 1496 // stop retransmission timer 1497 socket_alarm_stop();1582 // stop retransmission timer in thread descriptor 1583 alarm_stop( client_xp ); 1498 1584 1499 1585 // get socket state, tx_valid and tx_sts … … 1507 1593 1508 1594 // reset socket.tx_client 1509 hal_remote_s 32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );1595 hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL ); 1510 1596 1511 1597 if( cmd_status != CMD_STS_SUCCESS ) 1512 1598 { 1513 printk("\n[ERROR] in %s : for command TX_CONNECT / socket[%x,%d] / thread[%x,%x]\n", 1514 __FUNCTION__, pid, fdid, pid, trdid ); 1599 1600 #if DEBUG_SOCKET_ERROR 1601 printk("\n[ERROR] in %s reported by server / socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1602 __FUNCTION__, pid, fdid, pid, trdid, cycle ); 1603 #endif 1515 1604 return -1; 1516 1605 } … … 1548 1637 trdid_t trdid = this->trdid; 1549 1638 1639 #if DEBUG_SOCKET_CLOSE || DEBUG_SOCKET_ERROR 1640 uint32_t cycle = (uint32_t)hal_get_cycles(); 1641 #endif 1642 1550 1643 // get pointers on socket descriptor 1551 1644 cxy_t file_cxy = GET_CXY( file_xp ); … … 1558 1651 1559 1652 #if DEBUG_SOCKET_CLOSE 1560 uint32_t cycle = (uint32_t)hal_get_cycles();1561 1653 if (DEBUG_SOCKET_CLOSE < cycle ) 1562 1654 printk("\n[%s] thread[%x,%x] enters for socket[%x,%d] / cycle %d\n", … … 1574 1666 (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) ) 1575 1667 { 1576 // release socket lock 1668 1669 #if DEBUG_SOCKET_ERROR 1670 printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1671 __FUNCTION__, pid, fdid, pid, trdid, cycle ); 1672 #endif 1577 1673 remote_queuelock_release( socket_lock_xp ); 1578 1579 printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n",1580 __FUNCTION__, pid, fdid, pid, trdid );1581 1674 return -1; 1582 1675 } … … 1645 1738 1646 1739 // start retransmission timer 1647 socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1740 alarm_start( client_xp, 1741 hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT, 1742 &socket_alarm_handler, 1743 socket_xp ); 1648 1744 1649 1745 #if DEBUG_SOCKET_CLOSE … … 1663 1759 __FUNCTION__, pid, trdid, pid, fdid, cycle ); 1664 1760 #endif 1665 // stop retransmission timer 1666 socket_alarm_stop();1761 // stop retransmission timer in thread descriptor 1762 alarm_stop( client_xp ); 1667 1763 1668 1764 // take socket lock … … 1674 1770 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ) ); 1675 1771 1676 assert( __FUNCTION__, (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS)) 1677 && (cmd_valid == false)), 1678 "illegal socket state when client thread resumes after TX_CLOSE\n" 1679 " socket_state = %s / cmd_status = %d / cmd_valid = %d\n", 1772 assert( __FUNCTION__, 1773 (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1774 " socket_state = %s / cmd_status = %d / cmd_valid = %d", 1680 1775 socket_state_str(socket_state), cmd_status, cmd_valid ); 1681 1776 1682 1777 // reset socket.tx_client 1683 hal_remote_s 32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );1778 hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL ); 1684 1779 1685 1780 if( cmd_status != CMD_STS_SUCCESS ) // error reported 1686 1781 { 1687 printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x]\n", 1688 __FUNCTION__, pid, fdid, pid, this->trdid ); 1782 1783 #if DEBUG_SOCKET_ERROR 1784 printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1785 __FUNCTION__, pid, fdid, pid, this->trdid, cycle ); 1786 #endif 1689 1787 return -1; 1690 1788 } … … 1708 1806 //////////////////////////////////////////////////////////////////////////////////////// 1709 1807 // This static function is called by the two functions socket_send() & socket_recv(). 1710 // It can beused for both UDP and TCP sockets.1808 // It is used for both UDP and TCP sockets. 1711 1809 //////////////////////////////////////////////////////////////////////////////////////// 1712 1810 // @ is_send : send when true / receive when false. 1713 1811 // @ fdid : socket identifier. 1714 1812 // @ u_buf : pointer on user buffer in user space. 1715 // @ length : number of bytes .1813 // @ length : number of bytes in buffer. 1716 1814 //////////////////////////////////////////////////////////////////////////////////////// 1717 1815 // Implementation note : The behavior is different for SEND & RECV … … 1749 1847 chdev_t * chdev_ptr; 1750 1848 cxy_t chdev_cxy; 1751 uint32_t buf_status; // number of bytes in rx_buf1752 1849 int32_t moved_bytes; // total number of moved bytes (fot return) 1753 xptr_t server_xp; // extended pointer on NIC_TX / NIC_RX server thread 1754 thread_t * server_ptr; // local pointer on NIC_TX / NIC_RX server thread 1755 kmem_req_t req; // KCM request for TX kernel buffer 1756 uint8_t * tx_buf; // kernel buffer for TX transfer 1757 bool_t cmd_valid; // from socket descriptor 1758 uint32_t cmd_status; // from socket descriptor 1759 uint32_t tx_todo; // from socket descriptor 1850 xptr_t server_xp; // ext pointer on NIC_TX / NIC_RX thread 1851 thread_t * server_ptr; // local pointer on NIC_TX / NIC_RX thread 1852 uint8_t * tx_buf; // pointer on kernel buffer for TX transfer 1853 bool_t cmd_valid; // RX or TX command from socket descriptor 1854 uint32_t cmd_sts; // RX or TX command from socket descriptor 1855 uint32_t tx_todo; // number of bytes still to send 1856 xptr_t rx_buf_xp; // extended pointer on socket rx_buf 1857 uint32_t rx_buf_sts; // current status of socket rx_buf 1760 1858 1761 1859 thread_t * this = CURRENT_THREAD; 1762 1860 process_t * process = this->process; 1861 1862 #if DEBUG_SOCKET_SEND || DEBUG_SOCKET_RECV || DEBUG_SOCKET_ERROR 1863 uint32_t cycle = (uint32_t)hal_get_cycles(); 1864 #endif 1865 1866 #if DEBUG_SOCKET_SEND || DEBUG_SOCKET_RECV 1867 if( is_send ) 1868 printk("\n[%s] thread[%x,%x] socket[%x,%d] enter : SEND / buf %x / length %d / cycle %d\n", 1869 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, u_buf, length, cycle ); 1870 else 1871 printk("\n[%s] thread[%x,%x] socket[%x,%d] enter : RECV / buf %x / length %d / cycle %d\n", 1872 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, u_buf, length, cycle ); 1873 #endif 1763 1874 1764 1875 // build extended pointer on client thread … … 1772 1883 if( file_xp == XPTR_NULL ) 1773 1884 { 1774 printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x]\n", 1775 __FUNCTION__, fdid , process->pid, this->trdid ); 1885 1886 #if DEBUG_SOCKET_ERROR 1887 printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x] / cycle %d\n", 1888 __FUNCTION__, fdid , process->pid, this->trdid, cycle ); 1889 #endif 1776 1890 return -1; 1777 1891 } … … 1787 1901 if( file_type != FILE_TYPE_SOCK ) 1788 1902 { 1789 printk("\n[ERROR] in %s : illegal file type %s / socket[%x,%d]\n", 1790 __FUNCTION__, vfs_inode_type_str(file_type), process->pid, fdid ); 1903 1904 #if DEBUG_SOCKET_ERROR 1905 printk("\n[ERROR] in %s : illegal file type thread[%x,%x] / cycle %d\n", 1906 __FUNCTION__, process->pid, this->trdid, cycle ); 1907 #endif 1791 1908 return -1; 1792 1909 } … … 1803 1920 nic_channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel )); 1804 1921 1805 ///////////// 1922 ////////////////////////////////////////////////////// 1806 1923 if( is_send ) // SEND command 1807 1924 { 1808 1925 1809 1926 #if DEBUG_SOCKET_SEND 1810 uint32_tcycle = (uint32_t)hal_get_cycles();1927 cycle = (uint32_t)hal_get_cycles(); 1811 1928 if (DEBUG_SOCKET_SEND < cycle ) 1812 printk("\n[%s] thread[%x,%x] received SEND command for socket[%x,%d]/ length %d / cycle %d\n",1929 printk("\n[%s] thread[%x,%x] / socket[%x,%d] get SEND / length %d / cycle %d\n", 1813 1930 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle ); 1814 1931 #endif 1932 1815 1933 // check no previous TX command 1816 if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true) || 1817 (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) ) 1934 if( hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true ) 1818 1935 { 1819 // release socket lock 1936 1937 #if DEBUG_SOCKET_ERROR 1938 printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x] / cycle %d\n", 1939 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 1940 #endif 1820 1941 remote_queuelock_release( socket_lock_xp ); 1821 1822 printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x]\n",1823 __FUNCTION__, process->pid, fdid, process->pid, this->trdid );1824 1942 return -1; 1825 1943 } 1826 1944 1827 // allocate a temporary kernel buffer 1828 req.type = KMEM_KCM; 1829 req.order = bits_log2( length ); 1830 req.flags = AF_NONE; 1831 tx_buf = kmem_alloc( &req ); 1832 1833 if( tx_buf == NULL ) 1834 { 1835 // release socket lock 1836 remote_queuelock_release( socket_lock_xp ); 1837 1838 printk("\n[ERROR] in %s : no memory for tx_buf / socket[%x,%d] / thread[%x,%x]\n", 1839 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 1840 return -1; 1841 } 1842 1843 // copy data from user u_buf to kernel tx_buf 1844 hal_copy_from_uspace( XPTR( local_cxy , tx_buf ), 1945 // get tx_buf pointer from socket pointer 1946 tx_buf = (uint8_t*)hal_remote_lpt( XPTR( file_cxy , &socket_ptr->tx_buf )); 1947 1948 // copy data from user u_buf to kernel socket tx_buf 1949 hal_copy_from_uspace( XPTR( file_cxy , tx_buf ), 1845 1950 u_buf, 1846 1951 length ); 1952 #if DEBUG_SOCKET_SEND 1953 if (DEBUG_SOCKET_SEND < cycle ) 1954 printk("\n[%s] thread[%x,%x] / socket[%x,%d] copied %d bytes to tx_buf (%x,%x)\n", 1955 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, file_cxy, tx_buf ); 1956 putb("tx_buf : 16 first data bytes" , tx_buf , 16 ); 1957 #endif 1847 1958 1848 1959 // register command in socket descriptor … … 1852 1963 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_len ) , length ); 1853 1964 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_todo ) , length ); 1965 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_ack ) , 0 ); 1854 1966 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid ) , true ); 1855 1967 … … 1869 1981 thread_unblock( server_xp , THREAD_BLOCKED_CLIENT ); 1870 1982 1871 // start retransmission timer 1872 socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1983 // start retransmission timer for TCP socket 1984 if( socket_type == SOCK_STREAM ) 1985 { 1986 alarm_start( client_xp, 1987 hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT, 1988 &socket_alarm_handler, 1989 socket_xp ); 1990 } 1873 1991 1874 1992 #if DEBUG_SOCKET_SEND 1875 cycle = (uint32_t)hal_get_cycles();1876 1993 if( DEBUG_SOCKET_SEND < cycle ) 1877 printk("\n[%s] thread[%x,%x] socket[%x,%d] register SEND => blocks on <IO> / cycle %d\n",1878 __FUNCTION__, process->pid, this->trdid, process->pid, fdid , cycle);1994 printk("\n[%s] thread[%x,%x] / socket[%x,%d] registers SEND => blocks on <IO>\n", 1995 __FUNCTION__, process->pid, this->trdid, process->pid, fdid ); 1879 1996 #endif 1880 1997 // client thread blocks itself and deschedules … … 1885 2002 cycle = (uint32_t)hal_get_cycles(); 1886 2003 if( DEBUG_SOCKET_SEND < cycle ) 1887 printk("\n[%s] thread[%x,%x] socket[%x,%d] for SEND resumes/ cycle %d\n",2004 printk("\n[%s] thread[%x,%x] / socket[%x,%d] resumes for SEND / cycle %d\n", 1888 2005 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1889 2006 #endif 1890 // stop retransmission timer 1891 socket_alarm_stop(); 1892 1893 // take socket lock 2007 // stop retransmission timer for TCP socket 2008 if( socket_type == SOCK_STREAM ) 2009 { 2010 alarm_stop( client_xp ); 2011 } 2012 2013 // take socket lock 1894 2014 remote_queuelock_acquire( socket_lock_xp ); 1895 2015 … … 1897 2017 tx_todo = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_todo )); 1898 2018 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )); 1899 cmd_st atus= hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts ));2019 cmd_sts = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts )); 1900 2020 1901 2021 // reset tx_client in socket descriptor … … 1906 2026 1907 2027 // check SEND command completed when TX client thread resumes 1908 assert( __FUNCTION__, (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1909 "illegal socket state when client thread resumes after TX_SEND\n" 1910 " tx_todo = %d / tx_status = %d / tx_valid = %d\n", 1911 tx_todo, cmd_status, cmd_valid ); 1912 1913 // release the tx_buf 1914 req.ptr = tx_buf; 1915 kmem_free( &req ); 1916 1917 if( cmd_status != CMD_STS_SUCCESS ) 2028 assert( __FUNCTION__, 2029 (((tx_todo == 0) || (cmd_sts != CMD_STS_SUCCESS)) && (cmd_valid == false)), 2030 "client thread resumes from SEND / bad state : tx_todo %d / tx_sts %d / tx_valid %d", 2031 tx_todo, cmd_sts, cmd_valid ); 2032 2033 if( cmd_sts != CMD_STS_SUCCESS ) 1918 2034 { 1919 2035 1920 #if DEBUG_SOCKET_SEND 1921 cycle = (uint32_t)hal_get_cycles(); 1922 if( DEBUG_SOCKET_RECV < cycle ) 1923 printk("\n[%s] error %s for TX_SEND / socket[%x,%d] / thread[%x,%x]\n", 1924 __FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid ); 2036 #if DEBUG_SOCKET_ERROR 2037 printk("\n[ERROR] in %s : reported for SEND / socket[%x,%d] / thread[%x,%x] / cycle %d\n", 2038 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 1925 2039 #endif 1926 2040 return -1; … … 1932 2046 cycle = (uint32_t)hal_get_cycles(); 1933 2047 if (DEBUG_SOCKET_SEND < cycle ) 1934 printk("\n[%s] thread[%x,%x] success for SEND / socket[%x,%d] / length%d / cycle %d\n",2048 printk("\n[%s] thread[%x,%x] SEND success / socket[%x,%d] / bytes %d / cycle %d\n", 1935 2049 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle ); 1936 2050 #endif … … 1940 2054 } // end SEND command 1941 2055 1942 //// 1943 else // RECV command2056 ///////////////////////////////////////////////////////////// 2057 else // RECV command 1944 2058 { 1945 2059 1946 2060 #if DEBUG_SOCKET_RECV 1947 uint32_t cycle = (uint32_t)hal_get_cycles(); 1948 if (DEBUG_SOCKET_SEND < cycle ) 1949 printk("\n[%s] thread[%x,%x] received RECV command for socket[%x,%d] / length %d / cycle %d\n", 2061 if (DEBUG_SOCKET_RECV < cycle ) 2062 printk("\n[%s] thread[%x,%x] / socket[%x,%d] get RECV / length %d / cycle %d\n", 1950 2063 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle ); 1951 2064 #endif 1952 2065 // check no previous RX command 1953 if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true) || 1954 (hal_remote_l64( XPTR( file_cxy , &socket_ptr->rx_client)) != XPTR_NULL) ) 2066 if( hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true ) 1955 2067 { 1956 // release socket lock 2068 2069 #if DEBUG_SOCKET_ERROR 2070 printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x] / cycle %d\n", 2071 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 2072 #endif 1957 2073 remote_queuelock_release( socket_lock_xp ); 1958 1959 printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x]\n",1960 __FUNCTION__, process->pid, fdid, process->pid, this->trdid );1961 2074 return -1; 1962 2075 } … … 1969 2082 1970 2083 #if DEBUG_SOCKET_RECV 1971 uint32_tcycle = (uint32_t)hal_get_cycles();2084 cycle = (uint32_t)hal_get_cycles(); 1972 2085 if( DEBUG_SOCKET_RECV < cycle ) 1973 printk("\n[%s] thread[%x,%x] socket[%x,%d] TCP connection closed / cycle %d\n",2086 printk("\n[%s] thread[%x,%x] / socket[%x,%d] TCP connection closed / cycle %d\n", 1974 2087 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1975 2088 #endif 1976 2089 return 0; 1977 2090 } 1978 // build extended pointer on socket.rx_buf 1979 xptr_t rx_buf_xp = XPTR( file_cxy , &socket_ptr->rx_buf ); 1980 1981 // get rx_buf status 1982 buf_status = remote_buf_status( rx_buf_xp ); 1983 1984 if( buf_status == 0 ) 2091 2092 // build extended pointer on socket rx_buf 2093 rx_buf_xp = XPTR( file_cxy , &socket_ptr->rx_buf ); 2094 2095 // get socket rx_buf status 2096 rx_buf_sts = remote_buf_status( rx_buf_xp ); 2097 2098 // register RECV command and deschedule when rx_buf empty 2099 if( rx_buf_sts == 0 ) 1985 2100 { 1986 2101 // registers RX_RECV command in socket descriptor … … 1993 2108 1994 2109 #if DEBUG_SOCKET_RECV 1995 uint32_t cycle = (uint32_t)hal_get_cycles();1996 2110 if( DEBUG_SOCKET_RECV < cycle ) 1997 printk("\n[%s] thread[%x,%x] socket[%x,%d] rx_buf empty => blocks on <IO> / cycle %d\n",1998 __FUNCTION__, process->pid, this->trdid, process->pid, fdid , cycle);2111 printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV : rx_buf empty => blocks on <IO>\n", 2112 __FUNCTION__, process->pid, this->trdid, process->pid, fdid ); 1999 2113 #endif 2000 2114 // client thread blocks itself and deschedules … … 2005 2119 cycle = (uint32_t)hal_get_cycles(); 2006 2120 if( DEBUG_SOCKET_RECV < cycle ) 2007 printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV resumes / cycle %d\n",2121 printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV : resumes / cycle %d\n", 2008 2122 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 2009 2123 #endif … … 2011 2125 remote_queuelock_acquire( socket_lock_xp ); 2012 2126 2013 // get rx_stsand rx_buf status2127 // get command status, command valid, and rx_buf status 2014 2128 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )); 2015 cmd_st atus= hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts ));2016 buf_status = remote_buf_status( rx_buf_xp );2129 cmd_sts = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts )); 2130 rx_buf_sts = remote_buf_status( rx_buf_xp ); 2017 2131 2018 assert( __FUNCTION__, (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 2019 "illegal socket state when client thread resumes after RX_RECV\n" 2020 " buf_status = %d / rx_sts = %d / rx_valid = %d\n", 2021 buf_status , cmd_status , cmd_valid ); 2022 2023 // reset rx_client in socket descriptor 2024 hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL ); 2025 2026 // reset rx_buf for an UDP socket 2027 if( socket_type == SOCK_DGRAM ) remote_buf_reset( rx_buf_xp ); 2028 2029 // release socket lock 2030 remote_queuelock_release( socket_lock_xp ); 2031 2032 if( cmd_status == CMD_STS_EOF ) // EOF (remote close) reported 2132 assert( __FUNCTION__, (cmd_valid == false), 2133 "client thread resumes from RECV but rx_valid is true" ); 2134 2135 if( cmd_sts == CMD_STS_EOF ) // EOF reported by RX server 2033 2136 { 2034 2137 2035 2138 #if DEBUG_SOCKET_RECV 2036 cycle = (uint32_t)hal_get_cycles();2037 2139 if( DEBUG_SOCKET_RECV < cycle ) 2038 printk("\n[%s] EOF for RX_RECV /socket[%x,%d] / thread[%x,%x]\n",2140 printk("\n[%s] EOF received for socket[%x,%d] / thread[%x,%x]\n", 2039 2141 __FUNCTION__, process->pid, fdid, process->pid, this->trdid ); 2040 2142 #endif 2143 // release socket lock 2144 remote_queuelock_release( socket_lock_xp ); 2145 2041 2146 return 0; 2042 2147 } 2043 else if( cmd_st atus != CMD_STS_SUCCESS ) // other error reported2148 else if( cmd_sts != CMD_STS_SUCCESS ) // error reported by RX server 2044 2149 { 2045 2150 2046 #if DEBUG_SOCKET_RECV 2047 cycle = (uint32_t)hal_get_cycles(); 2048 if( DEBUG_SOCKET_RECV < cycle ) 2049 printk("\n[%s] error %s for RX_RECV / socket[%x,%d] / thread[%x,%x]\n", 2050 __FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid ); 2051 #endif 2151 #if DEBUG_SOCKET_ERROR 2152 printk("\n[ERROR] in %s : rx_server for socket[%x,%d] / thread[%x,%x] / cycle %d\n", 2153 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 2154 #endif 2155 // release socket lock 2156 remote_queuelock_release( socket_lock_xp ); 2157 2052 2158 return -1; 2053 2159 } 2054 2160 else if( rx_buf_sts == 0 ) // annormally empty rx_buf 2161 { 2162 2163 #if DEBUG_SOCKET_ERROR 2164 printk("\n[ERROR] in %s : rx_buf empty for socket[%x,%d] / thread[%x,%x] / cycle %d\n", 2165 __FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle ); 2166 #endif 2167 // release socket lock 2168 remote_queuelock_release( socket_lock_xp ); 2169 2170 return -1; 2171 } 2055 2172 } 2056 2173 2057 2174 // number of bytes extracted from rx_buf cannot be larger than u_buf size 2058 moved_bytes = ( length < buf_status ) ? length : buf_status;2175 moved_bytes = ( length < rx_buf_sts ) ? length : rx_buf_sts; 2059 2176 2060 2177 // move data from kernel rx_buf to user u_buf … … 2062 2179 u_buf, 2063 2180 moved_bytes ); 2064 #if DEBUG_SOCKET_ SEND2065 cycle = (uint32_t)hal_get_cycles(); 2066 if (DEBUG_SOCKET_ SEND< cycle )2067 printk("\n[%s] thread[%x,%x] success for RECV / socket[%x,%d] / length%d / cycle %d\n",2181 #if DEBUG_SOCKET_RECV 2182 cycle = (uint32_t)hal_get_cycles(); 2183 if (DEBUG_SOCKET_RECV < cycle ) 2184 printk("\n[%s] thread[%x,%x] : RECV success / socket[%x,%d] / bytes %d / cycle %d\n", 2068 2185 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, moved_bytes, cycle ); 2069 2186 #endif 2187 // release socket lock 2188 remote_queuelock_release( socket_lock_xp ); 2189 2070 2190 return moved_bytes; 2071 2191 … … 2095 2215 } // end socket_recv() 2096 2216 2217 //////////////////////////////////// 2218 int socket_sendto( uint32_t fdid, 2219 uint8_t * u_buf, 2220 uint32_t length, 2221 uint32_t remote_ip, 2222 uint16_t remote_port ) 2223 { 2224 printk("\n[ERROR] in %s : this function is not implemented yet\n", 2225 __FUNCTION__, fdid, u_buf, length, remote_ip, remote_port ); 2226 return -1; 2227 2228 } // end socket_sendto() 2229 2230 ////////////////////////////////////// 2231 int socket_recvfrom( uint32_t fdid, 2232 uint8_t * u_buf, 2233 uint32_t length, 2234 uint32_t remote_ip, 2235 uint16_t remote_port ) 2236 { 2237 printk("\n[ERROR] in %s : this function is not implemented yet\n", 2238 __FUNCTION__, fdid, u_buf, length, remote_ip, remote_port ); 2239 return -1; 2240 2241 } // end socket_recvfrom() 2242 2097 2243 //////////////////////////////////////////// 2098 2244 void socket_display( xptr_t socket_xp, 2099 const char * func_str ) 2100 { 2245 const char * func_str, 2246 const char * string ) 2247 { 2248 uint32_t cycle = (uint32_t)hal_get_cycles(); 2249 2101 2250 socket_t * socket = GET_PTR( socket_xp ); 2102 2251 cxy_t cxy = GET_CXY( socket_xp ); … … 2111 2260 uint32_t remote_port = hal_remote_l32( XPTR( cxy , &socket->remote_port )); 2112 2261 uint32_t tx_valid = hal_remote_l32( XPTR( cxy , &socket->tx_valid )); 2262 xptr_t tx_client = hal_remote_l64( XPTR( cxy , &socket->tx_client )); 2113 2263 uint32_t tx_cmd = hal_remote_l32( XPTR( cxy , &socket->tx_cmd )); 2114 2264 uint32_t tx_sts = hal_remote_l32( XPTR( cxy , &socket->tx_sts )); … … 2118 2268 uint32_t tx_nxt = hal_remote_l32( XPTR( cxy , &socket->tx_nxt )); 2119 2269 uint32_t tx_wnd = hal_remote_l32( XPTR( cxy , &socket->tx_wnd )); 2270 uint32_t tx_ack = hal_remote_l32( XPTR( cxy , &socket->tx_ack )); 2120 2271 uint32_t rx_valid = hal_remote_l32( XPTR( cxy , &socket->rx_valid )); 2272 xptr_t rx_client = hal_remote_l64( XPTR( cxy , &socket->rx_client )); 2121 2273 uint32_t rx_cmd = hal_remote_l32( XPTR( cxy , &socket->rx_cmd )); 2122 2274 uint32_t rx_sts = hal_remote_l32( XPTR( cxy , &socket->rx_sts )); 2123 2275 uint32_t rx_nxt = hal_remote_l32( XPTR( cxy , &socket->rx_nxt )); 2124 2276 uint32_t rx_wnd = hal_remote_l32( XPTR( cxy , &socket->rx_wnd )); 2125 uint32_t rx_irs = hal_remote_l32( XPTR( cxy , &socket->rx_irs )); 2126 2127 if( func_str == NULL ) 2128 { 2129 printk("\n****** socket[%x,%d] / xptr[%x,%x]*****\n", 2130 pid, fdid, cxy, socket ); 2277 uint32_t rx_irs = hal_remote_l32( XPTR( cxy , &socket->rx_irs )); 2278 2279 remote_queuelock_t * lock_ptr = &socket->lock; 2280 uint32_t taken = hal_remote_l32( XPTR( cxy , &lock_ptr->taken )); 2281 2282 thread_t * tx_ptr = GET_PTR( tx_client ); 2283 cxy_t tx_cxy = GET_CXY( tx_client ); 2284 trdid_t tx_tid = hal_remote_l32( XPTR( tx_cxy , &tx_ptr->trdid )); 2285 2286 thread_t * rx_ptr = GET_PTR( rx_client ); 2287 cxy_t rx_cxy = GET_CXY( rx_client ); 2288 trdid_t rx_tid = hal_remote_l32( XPTR( rx_cxy , &rx_ptr->trdid )); 2289 2290 if( string == NULL ) 2291 { 2292 printk("\n****** socket[%x,%d] / lock %d / in %s / cycle %d *****\n", 2293 pid, fdid, taken, func_str, cycle ); 2131 2294 } 2132 2295 else 2133 2296 { 2134 printk("\n***** socket[%x,%d] / xptr[%x,%x] / from %s *****\n", 2135 pid, fdid, cxy, socket, func_str ); 2136 } 2137 printk(" - state %s / channel %d\n" 2138 " - local_addr %x / local_port %x\n" 2139 " - remote_addr %x / remote_port %x\n" 2140 " - tx_valid %d (%s) / tx_sts %d / tx_len %x / tx_todo %x\n" 2141 " - tx_una %x / tx_nxt %x / tx_wnd %x\n" 2142 " - rx_valid %d (%s) / rx_sts %d\n" 2143 " - rx_nxt %x / rx_wnd %x / rx_irs %x\n", 2144 socket_state_str(state), channel , 2145 local_addr, local_port, 2146 remote_addr, remote_port, 2147 tx_valid, socket_cmd_type_str(tx_cmd), tx_sts, tx_len, tx_todo, 2148 tx_una, tx_nxt, tx_wnd, 2149 rx_valid, socket_cmd_type_str(rx_cmd), rx_sts, 2150 rx_nxt, rx_wnd, rx_irs ); 2297 printk("\n***** socket[%x,%d] / lock %d / in %s %s / cycle %d *****\n", 2298 pid, fdid, taken, func_str, string, cycle ); 2299 } 2300 printk(" - state %s / channel %d / local [%x,%x] / remote[%x,%x]\n" 2301 " - tx : valid %d / client [%x,%x] / cmd %s \n" 2302 " sts %d / len %x / todo %x / ack %x / una %x / nxt %x / wnd %x\n" 2303 " - rx : valid %d / client [%x,%x] / cmd %s\n" 2304 " sts %d / nxt %x / wnd %x / irs %x\n", 2305 socket_state_str(state), channel, 2306 local_addr, local_port, remote_addr, remote_port, 2307 tx_valid, pid, tx_tid, socket_cmd_type_str(tx_cmd), 2308 tx_sts, tx_len, tx_todo, tx_ack, tx_una, tx_nxt, tx_wnd, 2309 rx_valid, pid, rx_tid, socket_cmd_type_str(rx_cmd), 2310 rx_sts, rx_nxt, rx_wnd, rx_irs ); 2151 2311 2152 2312 } // end socket_display() -
trunk/kernel/kern/ksocket.h
r669 r683 1 1 /* 2 * ksocket.h - kernel socket de scriptor and API definition.2 * ksocket.h - kernel socket definition. 3 3 * 4 4 * Authors Alain Greiner (2016,2017,2018,2019,2020) … … 40 40 * existing sockets is split in as many subsets as the number of NIC channels, in order 41 41 * to parallelize the transfers. The distribution key defining the channel index 42 * is computed from the (remote_addr/remote_port) couple :by the NIC hardware for the43 * RX packets; by the software for the TX packets ,using a dedicated NIC driver function.42 * is computed from the (remote_addr/remote_port) couple (by the NIC hardware for the 43 * RX packets; by the software for the TX packets) using a dedicated NIC driver function. 44 44 * All sockets that have the same key share the same channel, and each socket is 45 45 * therefore linked to two chdevs : NIC_TX[key] & NIC_RX[key]. … … 52 52 * to the associated TX server (mainly used to handle the TCP ACKs). 53 53 * - the kernel "crq" buffer allows to store concurrent remote client connect requests 54 * to a local server socket. It is allocated in socket.54 * to a local server socket. 55 55 * 56 56 * The synchronisation mechanism between the client threads and the server threads 57 57 * is different for the TX and RX directions: 58 58 * 59 * 1) TX stream59 * 1) TX direction (sent packets) 60 60 * 61 61 * - The internal API between the TX client thread and the NIC_TX server thread defines 62 62 * four command types, stored in the "tx_cmd" variable of the socket descriptor: 63 * . SOCKET_TX_CONNECT : TCP client request to start the 3 steps connection handshake.64 * . SOCKET_TX_ACCEPT : TCP server request to accept one pending connection request.63 * . SOCKET_TX_CONNECT : request to start the connection handshake (TCP client only). 64 * . SOCKET_TX_ACCEPT : request to accept one connection request (TCP server only). 65 65 * . SOCKET_TX_SEND : local (UDP/TCP) request to send data to a remote (UDP/TCP). 66 66 * . SOCKET_TX_CLOSE : local TCP socket request remote TCP socket to close connection. … … 69 69 * reset the "tx_error" field, and registers itself in the "tx_client" field. 70 70 * Then, it unblocks the TX server thread from the BLOCKED_CLIENT condition, blocks itself 71 * on the BLOCKED_IO condition, and deschedules. For a SEND, the "tx_buf" kernel buffer72 * is dynamicaly allocated by the client thread, that copies the payload from the user73 * buffer to this kernel buffer,that is used as retransmission buffer, when required.71 * on the BLOCKED_IO condition, and deschedules. For a SEND, the client thread copies 72 * the payload contained in the "u_buf" user buffer to the socket "tx_buf" kernel buffer 73 * that is used as retransmission buffer, when required. 74 74 * - A command is valid for the TX server when the socket descriptor "tx_valid" is true. 75 * For a SEND command, the "tx_valid" is reset by the NIC_TX server when the last byte has76 * b een sent, but the TX client thread is unblocked by the NIC_RX server thread only when77 * the last byte has been acknowledged, or to report an error.75 * For a SEND command, the "tx_valid" is reset by the NIC_TX server thread when the last 76 * byte has been sent, but the TX client thread is unblocked by the NIC_RX server thread 77 * only when the last byte has been acknowledged, or to report an error. 78 78 * For the CONNECT, ACCEPT and CLOSE commands, the "tx_valid" is reset by the NIC_TX server 79 79 * when the first segment of the handshake has been sent, but the TX client thread is … … 88 88 * When "tx_valid" or "r2t_valid" are true, the TX server thread build and send an UDP 89 89 * packet or TCP segment. A single SEND command can require a large number of TCP 90 * segments to move a big data buffer .90 * segments to move a big data buffer, before unblocking the client thread. 91 91 * This TX server thread blocks and deschedules on the BLOCKED_ISR condition when there 92 92 * the NIC_RX queue is full . It is unblocked by the hardware NIC_TX_ISR. 93 * - In order to detect and report error for multiple simultaneous TX accesses to the same94 * socket, the clientthread makes a double check before posting a new TX command :93 * - As multiple simultaneous TX accesses to the same socket are forbiden, the client 94 * thread makes a double check before posting a new TX command : 95 95 * the "tx_valid" field must be false, and the "tx_client" field must be XPTR_NULL. 96 96 * The "tx_valid" field is reset by the TX server thread, and the "tx_client" … … 136 136 * 3) R2T queue 137 137 * 138 * To implement the TCP "3 steps handshake" protocol for connection or to send RST, 139 * the RX server thread can directly request the associated TX server thread to send 140 * control packets in the TX stream, using a dedicate R2T (RX to TX) FIFO stored in 141 * the socket descriptor. Each R2T request occupy one byte in this R2T queue. 138 * The RX server thread can directly request the associated TX server thread to send 139 * control packets in the TX stream, using a dedicate R2T (RX to TX) queue embedded in 140 * the socket descriptor, and implemented as a remote_buf_t FIFO. 141 * It is used for TCP acknowledge and for the TCP three-steps handshake. 142 * Each R2T request occupy exactly one single byte defining the TCP flags to be set. 142 143 * 143 144 * 4) CRQ queue 144 145 * 145 146 * The remote CONNECT requests received by a TCP socket (SYN segments) are stored in a 146 * dedicated CRQ FIFO stored in the local socket descriptor. These requests are consumed147 * by the local client thread executing an ACCEPT.148 * Each CRQ request occupy sizeof(connect_request_t) bytes in this CRQqueue.147 * dedicated CRQ queue, and consumed by the local client thread executing an ACCEPT. 148 * This CRQ queue is embedded in the local socket descriptor, and implemented as a 149 * remote_buf_t FIFO. Each request occupy sizeof(connect_request_t) bytes in the queue. 149 150 * The connect_request_t structure containing the request arguments is defined below. 150 151 * … … 171 172 * This enum defines the set of command status that can be returned by the NIC_RX and 172 173 * NIC_TX server threads to the TX & RX client threads. 173 * The success must be signaled by the null value / the various failure cases are174 * signaled by a non-null value.175 174 ****************************************************************************************/ 176 175 typedef enum socket_cmd_sts_e … … 217 216 tcp_socket_state_t; 218 217 219 /**************************************************************************************** *218 /**************************************************************************************** 220 219 * This structure defines one connection request, registered in the CRQ queue. 221 *************************************************************************************** */220 ***************************************************************************************/ 222 221 typedef struct connect_request_s 223 222 { … … 229 228 connect_request_t; 230 229 231 /**************************************************************************************** *230 /**************************************************************************************** 232 231 * This structure defines the socket descriptor. 233 *************************************************************************************** */232 ***************************************************************************************/ 234 233 typedef struct socket_s 235 234 { … … 253 252 uint8_t * tx_buf; /*! pointer on TX data buffer in kernel space */ 254 253 uint32_t tx_len; /*! number of data bytes for a SEND command */ 255 uint32_t tx_todo; /*! number of bytes not yet sent 256 xlist_entry_t tx_temp; /*! temporary list of sockets (root in TX chdev)*/254 uint32_t tx_todo; /*! number of bytes not yet sent in tx_buf */ 255 uint32_t tx_ack; /*! number of bytes acknowledged in tx_buf */ 257 256 258 257 xlist_entry_t rx_list; /*! all sockets attached to same NIC_RX channel */ … … 271 270 uint32_t tx_wnd; /*! number of acceptable bytes in TX_data stream */ 272 271 uint32_t tx_una; /*! first unack byte in TX_data stream */ 272 273 273 uint32_t rx_nxt; /*! next expected byte in RX_data stream */ 274 274 uint32_t rx_wnd; /*! number of acceptable bytes in RX_data stream */ … … 319 319 320 320 /**************************************************************************************** 321 * This function is called by the dev_nic_rx_handle_tcp() function, executed by the322 * NIC_RX[channel] server thread, to register a R2T request defined by the <flags>321 * This blocking function is called by the dev_nic_rx_handle_tcp() function, executed by 322 * the NIC_RX[channel] server thread, to register a R2T request defined by the <flags> 323 323 * argument in the socket R2T queue, specified by the <queue_xp> argument. 324 324 * This function unblocks the NIC_TX[channel] server thread, identified by the <channel> 325 325 * argumentfrom the THREAD_BLOCKED_CLIENT condition. 326 * 327 * WARNING : It contains a waiting loop and return only when an empty slot has been 328 * found in the R2T queue. 326 329 **************************************************************************************** 327 330 * @ queue_xp : [in] extended pointer on the R2T qeue descriptor. … … 330 333 ***************************************************************************************/ 331 334 void socket_put_r2t_request( xptr_t queue_xp, 332 uint 32_tflags,335 uint8_t flags, 333 336 uint32_t channel ); 337 338 /**************************************************************************************** 339 * This function is called by the nic_tx_server thread to extract an R2T request 340 * (one byte) from a R2T queue, specified by the <queue_xp> argument, to the buffer 341 * defined by the <flags> argument. 342 ***************************************************************************************** 343 * @ queue_xp : [in] extended pointer on the CRQ queue descriptor. 344 * @ flags : [out] buffer for TCP flags to be set. 345 * @ return 0 if success / return -1 if queue empty. 346 ***************************************************************************************/ 347 error_t socket_get_r2t_request (xptr_t queue_xp, 348 uint8_t * flags ); 334 349 335 350 /**************************************************************************************** … … 339 354 * by the <queue_xp> argument. 340 355 **************************************************************************************** 341 * @ queue_xp : [in] extended pointer on the CRQ q eue descriptor.356 * @ queue_xp : [in] extended pointer on the CRQ queue descriptor. 342 357 * @ remote_addr : [in] remote socket IP address. 343 358 * @ remote_port : [in] remote socket port. … … 374 389 **************************************************************************************** 375 390 * @ socket_xp : [in] extended pointer on socket descriptor. 376 $ @ string : [in] name of calling function. 391 * @ func_str : [in] name of calling function. 392 * @ string : [in] string defining the calling context (can be NULL) 377 393 ***************************************************************************************/ 378 394 void socket_display( xptr_t socket_xp, 379 const char * func_str ); 395 const char * func_str, 396 const char * string ); 380 397 381 398 … … 464 481 * This blocking function contains two blocking conditions because it requests services 465 482 * to both the NIC_RX server thread, and he NIC_TX server thread. 466 * It can be splitin five steps:483 * It is structured in five steps: 467 484 * 1) It makes several checkings on the listening socket domain, type, and state. 468 485 * 2) If the socket CRQ queue is empty, the function makes an SOCKET_RX_ACCEPT command … … 529 546 * arguments, to a connected (TCP or UDP) socket, identified by the <fdid> argument. 530 547 * The work is actually done by the NIC_TX server thread, and the synchronisation 548 * between the client and the server threads uses the "tx_valid" set/reset flip-flop: 549 * The client thread registers itself in the socket descriptor, registers in the queue 550 * rooted in the NIC_TX[index] chdev, set "tx_valid", unblocks the server thread, and 551 * finally blocks on THREAD_BLOCKED_IO, and deschedules. 552 * When the TX server thread completes the command (all data has been sent for an UDP 553 * socket, or acknowledged for a TCP socket), the server thread reset "rx_valid" and 554 * unblocks the client thread. 555 * This function can be called by a thread running in any cluster. 556 * WARNING : This implementation does not support several concurent SEND commands 557 * on the same socket, as only one TX thread can register in a given socket. 558 **************************************************************************************** 559 * @ fdid : [in] file descriptor index identifying the socket. 560 * @ u_buf : [in] pointer on buffer containing packet in user space. 561 * @ length : [in] packet size in bytes. 562 * @ return number of sent bytes if success / return -1 if failure. 563 ***************************************************************************************/ 564 int socket_send( uint32_t fdid, 565 uint8_t * u_buf, 566 uint32_t length ); 567 568 /**************************************************************************************** 569 * This blocking function implements the recv() syscall. 570 * It is used to receive data that has been stored by the NIC_RX server thread in the 571 * rx_buf of a connected socket, identified by the <fdid> argument. 572 * The synchronisation between the client and the server threads uses the "rx_valid" 573 * set/reset flip-flop: If "rx_valid" is set, the client simply moves the available 574 * data from the "rx_buf" to the user buffer identified by the <u_buf> and <length> 575 * arguments, and reset the "rx_valid" flip_flop. If "rx_valid" is not set, the client 576 * thread register itself in the socket descriptor, registers in the clients queue rooted 577 * in the NIC_RX[index] chdev, and finally blocks on THREAD_BLOCKED_IO, and deschedules. 578 * The client thread is re-activated by the RX server, that set the "rx_valid" flip-flop 579 * as soon as data is available in the "rx_buf". The number of bytes actually transfered 580 * can be less than the user buffer size. 581 * This function can be called by a thread running in any cluster. 582 * WARNING : This implementation does not support several concurent RECV 583 * commands on the same socket, as only one RX thread can register in a given socket. 584 **************************************************************************************** 585 * @ fdid : [in] file descriptor index identifying the local socket. 586 * @ u_buf : [in] pointer on buffer in user space. 587 * @ length : [in] buffer size in bytes. 588 * @ return number of received bytes if success / return -1 if failure. 589 ***************************************************************************************/ 590 int socket_recv( uint32_t fdid, 591 uint8_t * u_buf, 592 uint32_t length ); 593 594 /**************************************************************************************** 595 * This blocking function implements the sendto() syscall. 596 * It is used to send data stored in the user buffer, identified the <u_buf> and <length> 597 * to a remote process identified by the <remote_ip> and <remote_port> arguments, 598 * through a local, unconnected (UDP) socket, identified by the <fdid> argument. 599 * The work is actually done by the NIC_TX server thread, and the synchronisation 531 600 * between the client and the server threads uses the "rx_valid" set/reset flip-flop: 532 601 * The client thread registers itself in the socket descriptor, registers in the queue … … 539 608 * WARNING : This implementation does not support several concurent SEND/SENDTO commands 540 609 * on the same socket, as only one TX thread can register in a given socket. 541 **************************************************************************************** 542 * @ fdid : [in] file descriptor index identifying the socket. 543 * @ u_buf : [in] pointer on buffer containing packet in user space. 544 * @ length : [in] packet size in bytes. 610 * TODO : this function is not implemented yet. 611 **************************************************************************************** 612 * @ fdid : [in] file descriptor index identifying the local socket. 613 * @ u_buf : [in] pointer on buffer containing packet in user space. 614 * @ length : [in] packet size in bytes. 615 * @ remote_ip : [in] remote socket IP address. 616 * @ remote_port : [in] remote socket port address. 545 617 * @ return number of sent bytes if success / return -1 if failure. 546 618 ***************************************************************************************/ 547 int socket_send( uint32_t fdid, 548 uint8_t * u_buf, 549 uint32_t length ); 550 551 /**************************************************************************************** 552 * This blocking function implements the recv() syscall. 619 int socket_sendto( uint32_t fdid, 620 uint8_t * u_buf, 621 uint32_t length, 622 uint32_t remote_ip, 623 uint16_t remote_port ); 624 625 /**************************************************************************************** 626 * This blocking function implements the recvfrom() syscall. 553 627 * It is used to receive data that has been stored by the NIC_RX server thread in the 554 * rx_buf of a connected (TCP or UDP) socket, identified by the <fdid> argument. 628 * rx_buf of a non connected socket, identified by the <fdid> argument, from a 629 * remote process identified by the <remote_ip> and <remote_port> arguments. 555 630 * The synchronisation between the client and the server threads uses the "rx_valid" 556 631 * set/reset flip-flop: If "rx_valid" is set, the client simply moves the available … … 565 640 * WARNING : This implementation does not support several concurent RECV/RECVFROM 566 641 * commands on the same socket, as only one RX thread can register in a given socket. 567 **************************************************************************************** 568 * @ fdid : [in] file descriptor index identifying the socket. 569 * @ u_buf : [in] pointer on buffer in user space. 570 * @ length : [in] buffer size in bytes. 642 * TODO : this function is not implemented yet. 643 **************************************************************************************** 644 * @ fdid : [in] file descriptor index identifying the local socket. 645 * @ u_buf : [in] pointer on buffer in user space. 646 * @ length : [in] buffer size in bytes. 647 * @ remote_ip : [in] remote socket IP address. 648 * @ remote_port : [in] remote socket port address. 571 649 * @ return number of received bytes if success / return -1 if failure. 572 650 ***************************************************************************************/ 573 int socket_recv( uint32_t fdid, 574 uint8_t * u_buf, 575 uint32_t length ); 651 int socket_recvfrom( uint32_t fdid, 652 uint8_t * u_buf, 653 uint32_t length, 654 uint32_t remote_ip, 655 uint16_t remote_port ); 576 656 577 657 /**************************************************************************************** -
trunk/kernel/kern/pipe.c
r669 r683 2 2 * pipe.c - single writer, single reader pipe implementation 3 3 * 4 * Author Alain Greiner (2016,2017,2018,2019,2020)4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 32 32 uint32_t size ) 33 33 { 34 kmem_req_t req;35 34 remote_buf_t * buf; 36 35 pipe_t * pipe; … … 55 54 56 55 // 3. allocate memory for pipe descriptor 57 req.type = KMEM_KCM; 58 req.order = bits_log2( sizeof(pipe_t) ); 59 req.flags = AF_ZERO; 60 pipe = kmem_remote_alloc( cxy , &req ); 56 pipe = kmem_remote_alloc( cxy , bits_log2(sizeof(pipe_t)) , AF_ZERO ); 61 57 62 58 if( pipe == NULL ) … … 76 72 void pipe_destroy( xptr_t pipe_xp ) 77 73 { 78 kmem_req_t req;79 80 74 pipe_t * pipe_ptr = GET_PTR( pipe_xp ); 81 75 cxy_t pipe_cxy = GET_CXY( pipe_xp ); … … 88 82 89 83 // release pipe descriptor 90 req.type = KMEM_KCM; 91 req.ptr = pipe_ptr; 92 kmem_remote_free( pipe_cxy , &req ); 84 kmem_remote_free( pipe_cxy , pipe_ptr , bits_log2(sizeof(pipe_t)) ); 93 85 94 86 } // end pipe_destroy() 95 96 87 97 88 ////////////////////////////////////////// -
trunk/kernel/kern/printk.c
r669 r683 41 41 ////////////////////////////////////////////////////////////////////////////////////// 42 42 // This static function is called by printk(), nolock_printk(), and snprintk(), 43 // functions to build a string from a printf-like format, and stores it 44 // in the buffer defined by the <string> and <length> arguments. 45 // It does NOT add a terminating NUL character in the <string> buffer. 46 // If success, it returns the number of bytes actually copied in the string buffer. 43 // functions to build a string from a printf-like <format>, and stores it 44 // in the buffer defined by the <string> and <size> arguments. 45 // The <format> itself is supposed to be a NUL terminated string. The <string> 46 // buffer <size> must be large enough to contains also the NUL terminating character. 47 // If success, it returns the number of bytes actually copied in the <string> buffer, 48 // but this length does NOT include the terminating NUL character. 47 49 // It returns -2 in case of illegal format, it returns -1 if the formated string 48 // exceeds the lengthargument.50 // exceeds the <size> argument. 49 51 ////////////////////////////////////////////////////////////////////////////////////// 50 52 // @ string : buffer allocated by caller. 51 // @ length: buffer size in bytes53 // @ size : buffer size in bytes 52 54 // @ format : printf like format. 53 55 // @ args : va_list of arguments. … … 55 57 ////////////////////////////////////////////////////////////////////////////////////// 56 58 static int32_t format_to_string( char * string, 57 uint32_t length,59 uint32_t size, 58 60 const char * format, 59 61 va_list * args ) 60 62 { 61 63 62 #define TO_STRING(x) do { string[ps] = (x); ps++; if(ps== length) return -1; } while(0);64 #define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==size) return -1; } while(0); 63 65 64 66 uint32_t ps = 0; // index in string buffer … … 74 76 goto format_to_string_arguments; 75 77 } 76 else // copy one char to string78 else // copy one char of format to string 77 79 { 78 80 TO_STRING( *format ); … … 81 83 } 82 84 83 TO_STRING( 0 ); 84 return ps;85 TO_STRING( 0 ); // NUL character written in buffer 86 return (ps - 1); // but not counted in length 85 87 86 88 format_to_string_arguments: … … 95 97 switch (*format) 96 98 { 97 case ('c'): // char conversion 98 { 99 int val = va_arg( *args , int ); 100 buf[0] = (char)val; 99 case ('c'): // one printable character 100 { 101 buf[0] = (char)va_arg( *args , uint32_t ); 101 102 pbuf = buf; 102 103 len = 1; 103 104 break; 104 105 } 105 case ('d'): // up to 10 digits decimal signed integer 106 case ('b'): // one ASCII code value (2 hexadecimal digits) 107 { 108 uint8_t val = (uint8_t)va_arg( *args , uint32_t ); 109 buf[1] = HexaTab[val & 0xF]; 110 buf[0] = HexaTab[(val >> 4) & 0xF]; 111 pbuf = buf; 112 len = 2; 113 break; 114 } 115 case ('d'): // one int32_t (up to 10 decimal digits after sign) 106 116 { 107 117 int32_t val = va_arg( *args , int32_t ); … … 120 130 break; 121 131 } 122 case ('u'): // up to 10 digits decimal unsigned integer132 case ('u'): // one uint32_t (up to 10 decimal digits) 123 133 { 124 134 uint32_t val = va_arg( *args , uint32_t ); … … 132 142 break; 133 143 } 134 case ('x'): // up to 8 digits hexad after "0x"135 case ('X'): // exactly 8 digits hexa after "0x" 144 case ('x'): // one uint32_t (up to 8 hexa digits after "0x") 145 136 146 { 137 147 uint32_t val = va_arg( *args , uint32_t ); … … 141 151 { 142 152 buf[7 - i] = HexaTab[val & 0xF]; 143 if( (*format == 'x') && ((val >> 4) == 0) ) break;144 153 val = val >> 4; 154 if(val == 0) break; 145 155 } 146 156 len = i + 1; … … 148 158 break; 149 159 } 150 case ('l'): // up to 16 digits hexa after "0x" 151 case ('L'): // exactly 16 digits hexa after "0x" 160 case ('X'): // one uint32_t (exactly 8 hexa digits after "0x") 161 { 162 uint32_t val = va_arg( *args , uint32_t ); 163 TO_STRING( '0' ); 164 TO_STRING( 'x' ); 165 for(i = 0 ; i < 8 ; i++) 166 { 167 buf[7 - i] = (val != 0) ? HexaTab[val & 0xF] : '0'; 168 val = val >> 4; 169 } 170 len = 8; 171 pbuf = &buf[0]; 172 break; 173 } 174 case ('l'): // one uint64_t (up to 16 digits hexa after "0x") 152 175 { 153 176 uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) | … … 158 181 { 159 182 buf[15 - i] = HexaTab[val & 0xF]; 160 if( (*format == 'l') && ((val >> 4) == 0) ) break;161 183 val = val >> 4; 184 if( val == 0) break; 162 185 } 163 186 len = i + 1; … … 165 188 break; 166 189 } 167 case ('s'): /* string */ 190 case ('L'): // one uint64_t (exactly 16 digits hexa after "0x") 191 { 192 uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) | 193 ((uint64_t)va_arg( *args, uint32_t)); 194 TO_STRING( '0' ); 195 TO_STRING( 'x' ); 196 for(i = 0 ; i < 16 ; i++) 197 { 198 buf[15 - i] = (val != 0) ? HexaTab[val & 0xF] : '0'; 199 val = val >> 4; 200 } 201 len = 16; 202 pbuf = &buf[0]; 203 break; 204 } 205 case ('s'): /* one characters string */ 168 206 { 169 207 char* str = va_arg( *args , char* ); … … 213 251 // build a string from format 214 252 length = format_to_string( buffer, 215 CONFIG_PRINTK_BUF_SIZE,216 format,217 &args );253 CONFIG_PRINTK_BUF_SIZE, 254 format, 255 &args ); 218 256 va_end( args ); 219 257 … … 258 296 // build a string from format 259 297 length = format_to_string( buffer, 260 CONFIG_PRINTK_BUF_SIZE,261 format,262 &args );298 CONFIG_PRINTK_BUF_SIZE, 299 format, 300 &args ); 263 301 va_end( args ); 264 302 … … 315 353 if( length > 0 ) // display panic message on TXT0, including formated string 316 354 { 317 printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n %s\n",355 printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n <%s>\n", 318 356 func_name, local_cxy, lid, pid, trdid, cycle, buffer ); 319 357 } … … 332 370 { 333 371 va_list args; 334 int32_t string_length;372 int32_t length; 335 373 336 374 // build args va_list … … 338 376 339 377 // build a string from format 340 string_length = format_to_string( buffer , size , format , &args ); 378 length = format_to_string( buffer , size , format , &args ); 379 380 // release args list 341 381 va_end( args ); 342 382 343 if( (string_length < 0) || (string_length == (int32_t)size) ) // failure 344 { 345 return -1; 346 } 347 else // success 348 { 349 // add NUL character 350 buffer[string_length] = 0; 351 352 return string_length; 353 } 383 if( length < 0 ) return -1; 384 else return length; 385 354 386 } // end snprintk() 355 387 -
trunk/kernel/kern/printk.h
r669 r683 24 24 /////////////////////////////////////////////////////////////////////////////////// 25 25 // The printk.c and printk.h files define the functions used by the kernel 26 // to display messages on the kernel terminal TXT0, using a busy waiting policy.27 // I t calls synchronously the TXT0 driver, without descheduling.26 // to build, or display on terminal TXT0, formated strings. 27 // In case ofdisplay, it calls synchronously the TXT0 driver, without descheduling. 28 28 // 29 // For the formated string, the supported formats are defined below :29 // The supported formats are defined below : 30 30 // %c : single ascii character (8 bits) 31 // %b : exactly 2 hexadecimal digits (8 bits) 31 32 // %d : up to 10 digits decimal integer (32 bits) 32 33 // %u : up to 10 digits unsigned decimal (32 bits) … … 47 48 48 49 /********************************************************************************** 49 * These debugfunctions display a formated string defined by the <format,...>50 * These functions display a formated string defined by the <format,...> 50 51 * argument on the kernel terminal TXT0, with or without taking the TXT0 lock. 51 52 ********************************************************************************** … … 64 65 65 66 /********************************************************************************** 66 * This debug function displays a[ASSERT] message on kernel TXT0 terminal67 * This function displays an [ASSERT] message on kernel TXT0 terminal 67 68 * if Boolean expression <expr> is false. It prints a detailed message including: 68 69 * - the calling core [cxy,lpid] … … 83 84 * This function build a formated string in a buffer defined by the <buffer> 84 85 * and <buf_size> arguments, from the format defined by the <format,...> argument. 85 * This function set the NUL terminating character in target <buffer>. 86 * This function set the NUL terminating character in target <buffer>, 87 * but the returned length does not include this NUL character. 86 88 ********************************************************************************** 87 89 * @ buffer : pointer on target buffer (allocated by caller). … … 142 144 * @ string : buffer name or identifier. 143 145 * @ buffer : local pointer on bytes array. 144 * @ size : number of bytes bytesto display.146 * @ size : number of bytes to display. 145 147 *********************************************************************************/ 146 148 void putb( char * string, -
trunk/kernel/kern/process.c
r669 r683 2 2 * process.c - process related functions definition. 3 3 * 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012)4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 5 * Mohamed Lamine Karaoui (2015) 6 * Alain Greiner (2016,2017,2018,2019,2020)6 * Alain Greiner (2016,2017,2018,2019,2020) 7 7 * 8 8 * Copyright (c) UPMC Sorbonne Universites … … 70 70 ////////////////////////////////////////////////////////////////////////////////////////// 71 71 72 /////////////////////////////////73 process_t * process_alloc( void )74 {75 76 assert( __FUNCTION__, (sizeof(process_t) < CONFIG_PPM_PAGE_SIZE),77 "process descriptor exceeds 1 page" );78 79 kmem_req_t req;80 81 req.type = KMEM_PPM;82 req.order = 0;83 req.flags = AF_KERNEL | AF_ZERO;84 return kmem_alloc( &req );85 }86 87 ////////////////////////////////////////88 void process_free( process_t * process )89 {90 kmem_req_t req;91 92 req.type = KMEM_PPM;93 req.ptr = process;94 kmem_free( &req );95 }96 97 72 //////////////////////////////////////////////////// 98 73 error_t process_reference_init( process_t * process, … … 116 91 vmm_t * vmm; 117 92 118 // build extended pointer on this reference process 93 #if DEBUG_PROCESS_REFERENCE_INIT || DEBUG_PROCESS_ERROR 94 thread_t * this = CURRENT_THREAD; 95 uint32_t cycle = (uint32_t)hal_get_cycles(); 96 #endif 97 98 // build extended pointer on reference process 119 99 process_xp = XPTR( local_cxy , process ); 120 100 … … 130 110 131 111 #if DEBUG_PROCESS_REFERENCE_INIT 132 thread_t * this = CURRENT_THREAD;133 uint32_t cycle = (uint32_t)hal_get_cycles();134 112 if( DEBUG_PROCESS_REFERENCE_INIT < cycle ) 135 113 printk("\n[%s] thread[%x,%x] enter to initialize process %x / cycle %d\n", … … 156 134 if( error ) 157 135 { 158 printk("\n[ERROR] in %s : cannot create empty GPT\n", __FUNCTION__ ); 136 137 #if DEBUG_PROCESS_ERROR 138 printk("\n[ERROR] in %s : thread[%x,%x] cannot create empty GPT / cycle %d\n", 139 __FUNCTION__, this->process->pid, this->trdid, cycle ); 140 #endif 159 141 return -1; 160 142 } … … 173 155 if( error ) 174 156 { 157 158 #if DEBUG_PROCESS_ERROR 159 printk("\n[ERROR] in %s : thread[%x,%x] cannot register kernel vsegs in VMM / cycle %d\n", 160 __FUNCTION__, this->process->pid, this->trdid, cycle ); 161 #endif 175 162 printk("\n[ERROR] in %s : cannot register kernel vsegs in VMM\n", __FUNCTION__ ); 176 163 return -1; … … 233 220 if( error ) 234 221 { 235 printk("\n[ERROR] in %s : cannot open stdout pseudo-file\n", __FUNCTION__ ); 222 223 #if DEBUG_PROCESS_ERROR 224 printk("\n[ERROR] in %s : thread[%x,%x] cannot open stdin pseudo file / cycle %d\n", 225 __FUNCTION__, this->process->pid, this->trdid, cycle ); 226 #endif 236 227 return -1; 237 228 } … … 256 247 if( error ) 257 248 { 258 printk("\n[ERROR] in %s : cannot open stdout pseudo-file\n", __FUNCTION__ ); 249 250 #if DEBUG_PROCESS_ERROR 251 printk("\n[ERROR] in %s : thread[%x,%x] cannot open stdout pseudo file / cycle %d\n", 252 __FUNCTION__, this->process->pid, this->trdid, cycle ); 253 #endif 259 254 return -1; 260 255 } … … 279 274 if( error ) 280 275 { 281 printk("\n[ERROR] in %s : cannot open stderr pseudo-file\n", __FUNCTION__ ); 276 277 #if DEBUG_PROCESS_ERROR 278 printk("\n[ERROR] in %s : thread[%x,%x] cannot open stderr pseudo file / cycle %d\n", 279 __FUNCTION__, this->process->pid, this->trdid, cycle ); 280 #endif 282 281 return -1; 283 282 } … … 302 301 303 302 // recreate all open files from parent process fd_array to child process fd_array 304 process_fd_replicate( process_xp , parent_xp ); 303 error = process_fd_replicate( process_xp , parent_xp ); 304 305 if( error ) 306 { 307 308 #if DEBUG_PROCESS_ERROR 309 printk("\n[ERROR] in %s : thread[%x,%x] cannot replicate fd_array / cycle %d\n", 310 __FUNCTION__, this->process->pid, this->trdid, cycle ); 311 #endif 312 return -1; 313 } 314 305 315 } 306 316 … … 379 389 vmm_t * vmm; 380 390 391 #if DEBUG_PROCESS_COPY_INIT || DEBUG_PROCESS_ERROR 392 thread_t * this = CURRENT_THREAD; 393 uint32_t cycle = (uint32_t)hal_get_cycles(); 394 #endif 395 381 396 // get reference process cluster and local pointer 382 397 cxy_t ref_cxy = GET_CXY( reference_process_xp ); … … 394 409 395 410 #if DEBUG_PROCESS_COPY_INIT 396 thread_t * this = CURRENT_THREAD;397 uint32_t cycle = (uint32_t)hal_get_cycles();398 411 if( DEBUG_PROCESS_COPY_INIT < cycle ) 399 412 printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n", … … 410 423 // create an empty GPT as required by the architecture 411 424 error = hal_gpt_create( &vmm->gpt ); 425 412 426 if( error ) 413 427 { 414 printk("\n[ERROR] in %s : cannot create empty GPT\n", __FUNCTION__ ); 428 429 #if DEBUG_PROCESS_ERROR 430 printk("\n[ERROR] in %s : thread[%x,%x] cannot create empty GPT / cycle %d\n", 431 __FUNCTION__, this->process->pid, this->trdid, cycle ); 432 #endif 415 433 return -1; 416 434 } … … 421 439 // register kernel vsegs in VMM as required by the architecture 422 440 error = hal_vmm_kernel_update( local_process ); 441 423 442 if( error ) 424 443 { 425 printk("\n[ERROR] in %s : cannot register kernel vsegs in VMM\n", __FUNCTION__ ); 444 445 #if DEBUG_PROCESS_ERROR 446 printk("\n[ERROR] in %s : thread[%x,%x] cannot register kernel vsegs in VMM / cycle %d\n", 447 __FUNCTION__, this->process->pid, this->trdid, cycle ); 448 #endif 426 449 return -1; 427 450 } … … 431 454 // initialize locks protecting GPT and VSL 432 455 error = vmm_user_init( local_process ); 456 433 457 if( error ) 434 458 { 435 printk("\n[ERROR] in %s : cannot register user vsegs in VMM\n", __FUNCTION__ ); 459 460 #if DEBUG_PROCESS_ERROR 461 printk("\n[ERROR] in %s : thread[%x,%x] cannot register user vsegs in VMM / cycle %d\n", 462 __FUNCTION__, this->process->pid, this->trdid, cycle ); 463 #endif 436 464 return -1; 437 465 } … … 598 626 599 627 // release memory allocated to process descriptor 600 process_free( process);628 kmem_free( process , bits_log2(sizeof(process_t)) ); 601 629 602 630 #if DEBUG_PROCESS_DESTROY … … 974 1002 { 975 1003 error_t error; 976 process_t * process _ptr;// local pointer on process1004 process_t * process; // local pointer on process 977 1005 xptr_t process_xp; // extended pointer on process 978 1006 1007 #if DEBUG_PROCESS_GET_LOCAL_COPY || DEBUG_PROCESS_ERROR 1008 thread_t * this = CURRENT_THREAD; 1009 uint32_t cycle = (uint32_t)hal_get_cycles(); 1010 #endif 1011 979 1012 cluster_t * cluster = LOCAL_CLUSTER; 980 1013 981 1014 #if DEBUG_PROCESS_GET_LOCAL_COPY 982 thread_t * this = CURRENT_THREAD;983 uint32_t cycle = (uint32_t)hal_get_cycles();984 1015 if( DEBUG_PROCESS_GET_LOCAL_COPY < cycle ) 985 1016 printk("\n[%s] thread[%x,%x] enter for process %x in cluster %x / cycle %d\n", … … 996 1027 { 997 1028 process_xp = XLIST_ELEMENT( iter , process_t , local_list ); 998 process _ptr= GET_PTR( process_xp );999 if( process _ptr->pid == pid )1029 process = GET_PTR( process_xp ); 1030 if( process->pid == pid ) 1000 1031 { 1001 1032 found = true; … … 1017 1048 1018 1049 // allocate memory for local process descriptor 1019 process _ptr = process_alloc();1020 1021 if( process _ptr== NULL ) return NULL;1050 process = kmem_alloc( bits_log2(sizeof(process_t)) , AF_ZERO ); 1051 1052 if( process == NULL ) return NULL; 1022 1053 1023 1054 // initialize local process descriptor copy 1024 error = process_copy_init( process_ptr , ref_xp ); 1025 1026 if( error ) return NULL; 1055 error = process_copy_init( process , ref_xp ); 1056 1057 if( error ) 1058 { 1059 1060 #if DEBUG_PROCESS_ERROR 1061 printk("\n[ERROR] in %s : thread[%x,%x] cannot initialize local process copy / cycle %d\n", 1062 __FUNCTION__, this->process->pid, this->trdid, cycle ); 1063 #endif 1064 return NULL; 1065 } 1027 1066 } 1028 1067 … … 1031 1070 if( DEBUG_PROCESS_GET_LOCAL_COPY < cycle ) 1032 1071 printk("\n[%s] thread[%x,%x] exit in cluster %x / process %x / cycle %d\n", 1033 __FUNCTION__, this->process->pid, this->trdid, local_cxy, process _ptr, cycle );1034 #endif 1035 1036 return process _ptr;1072 __FUNCTION__, this->process->pid, this->trdid, local_cxy, process, cycle ); 1073 #endif 1074 1075 return process; 1037 1076 1038 1077 } // end process_get_local_copy() … … 1111 1150 xptr_t max_xp; // extended pointer on max field in fd_array 1112 1151 1152 #if DEBUG_PROCESS_FD_REGISTER 1153 thread_t * this = CURRENT_THREAD; 1154 uint32_t cycle = (uint32_t)hal_get_cycles(); 1155 #endif 1156 1113 1157 // get target process cluster and local pointer 1114 1158 process_t * process_ptr = GET_PTR( process_xp ); … … 1120 1164 1121 1165 #if DEBUG_PROCESS_FD_REGISTER 1122 thread_t * this = CURRENT_THREAD; 1123 uint32_t cycle = (uint32_t)hal_get_cycles(); 1124 pid_t pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) ); 1166 pid_t tgt_pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) ); 1125 1167 if( DEBUG_PROCESS_FD_REGISTER < cycle ) 1126 1168 printk("\n[%s] thread[%x,%x] enter for process %x / cycle %d\n", 1127 __FUNCTION__, this->process->pid, this->trdid, pid, cycle );1169 __FUNCTION__, this->process->pid, this->trdid, tgt_pid, cycle ); 1128 1170 #endif 1129 1171 … … 1168 1210 if( DEBUG_PROCESS_FD_REGISTER < cycle ) 1169 1211 printk("\n[%s] thread[%x,%x] exit for process %x / fdid %d / cycle %d\n", 1170 __FUNCTION__, this->process->pid, this->trdid, pid, id, cycle );1212 __FUNCTION__, this->process->pid, this->trdid, tgt_pid, id, cycle ); 1171 1213 #endif 1172 1214 … … 1384 1426 } // end process_fd_get_xptr_from_local() 1385 1427 1386 ///////////////////////////////////////// 1387 voidprocess_fd_replicate( xptr_t dst_xp,1388 xptr_t src_xp )1428 //////////////////////////////////////////// 1429 error_t process_fd_replicate( xptr_t dst_xp, 1430 xptr_t src_xp ) 1389 1431 { 1390 1432 uint32_t fdid; // current file descriptor index … … 1435 1477 if( error ) 1436 1478 { 1437 printk("\n[ERROR] in %s : cannot create new file\n", __FUNCTION__ ); 1438 return; 1479 1480 #if DEBUG_PROCESS_ERROR 1481 thread_t * this = CURRENT_THREAD; 1482 uint32_t cycle = (uint32_t)hal_get_cycles(); 1483 printk("\n[ERROR] in %s : thread[%x,%x] cannot create file descriptor / cycle %d\n", 1484 __FUNCTION__, this->process->pid, this->trdid, cycle ); 1485 #endif 1486 return -1; 1439 1487 } 1440 1488 … … 1446 1494 // release lock on source process fd_array 1447 1495 remote_queuelock_release( src_lock_xp ); 1496 1497 return 0; 1448 1498 1449 1499 } // end process_fd_replicate() … … 1494 1544 uint32_t max = hal_remote_l32( XPTR( owner_cxy , &owner_ptr->fd_array.max )); 1495 1545 1496 printk("\n***** fd_array for pid %x in cluster %x / max %d *****\n", 1546 // get pointers on TXT0 chdev 1547 xptr_t txt0_xp = chdev_dir.txt_tx[0]; 1548 cxy_t txt0_cxy = GET_CXY( txt0_xp ); 1549 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 1550 1551 // get extended pointer on remote TXT0 lock 1552 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 1553 1554 // get TXT0 lock 1555 remote_busylock_acquire( lock_xp ); 1556 1557 nolock_printk("\n***** fd_array for pid %x in cluster %x / max %d *****\n", 1497 1558 pid, process_cxy, max ); 1498 1559 … … 1520 1581 1521 1582 // display relevant file descriptor info 1522 printk(" - %d : type %s / ptr %x (%s)\n",1583 nolock_printk(" - %d : type %s / ptr %x (%s)\n", 1523 1584 fdid, process_fd_type_str(file_type), file_ptr, name ); 1524 1585 } … … 1526 1587 { 1527 1588 // display relevant file decriptor info 1528 printk(" - %d : type %s / ptr %x\n",1589 nolock_printk(" - %d : type %s / ptr %x\n", 1529 1590 fdid , process_fd_type_str(file_type), file_ptr ); 1530 1591 } … … 1532 1593 else 1533 1594 { 1534 printk(" - %d : empty slot\n", 1535 fdid ); 1595 nolock_printk(" - %d : empty slot\n", fdid ); 1536 1596 } 1537 1597 } 1598 1599 // get TXT0 lock 1600 remote_busylock_acquire( lock_xp ); 1601 1538 1602 } // end process_fd_display() 1539 1603 … … 1548 1612 { 1549 1613 ltid_t ltid; 1614 ltid_t ltid_min; 1615 1550 1616 bool_t found = false; 1617 lpid_t lpid = LPID_FROM_PID( process->pid ); 1551 1618 1552 1619 // check arguments … … 1554 1621 assert( __FUNCTION__, (thread != NULL) , "thread argument is NULL" ); 1555 1622 1556 // get the lock protecting th_tbl for all threads 1557 // but the idle thread executing kernel_init (cannot yield) 1623 // get the lock protecting th_tbl for all threads but the idle thread 1558 1624 if( thread->type != THREAD_IDLE ) rwlock_wr_acquire( &process->th_lock ); 1559 1625 1626 // compute ltid_min : 0 for an user thread / 1 for a kernel thread 1627 ltid_min = (lpid == 0) ? 1 : 0; 1628 1560 1629 // scan th_tbl 1561 for( ltid = 0; ltid < CONFIG_THREADS_MAX_PER_CLUSTER ; ltid++ )1630 for( ltid = ltid_min ; ltid < CONFIG_THREADS_MAX_PER_CLUSTER ; ltid++ ) 1562 1631 { 1563 1632 if( process->th_tbl[ltid] == NULL ) … … 1581 1650 if( thread->type != THREAD_IDLE ) rwlock_wr_release( &process->th_lock ); 1582 1651 1583 return (found) ? 0 : 0xFFFFFFFF;1652 return (found) ? 0 : -1; 1584 1653 1585 1654 } // end process_register_thread() … … 1647 1716 "parent process must be the reference process" ); 1648 1717 1649 #if DEBUG_PROCESS_MAKE_FORK 1650 uint32_t cycle ;1718 #if DEBUG_PROCESS_MAKE_FORK || DEBUG_PROCESS_ERROR 1719 uint32_t cycle = (uint32_t)hal_get_cycles(); 1651 1720 thread_t * this = CURRENT_THREAD; 1652 1721 trdid_t trdid = this->trdid; … … 1655 1724 1656 1725 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1657 cycle = (uint32_t)hal_get_cycles();1658 1726 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1659 1727 printk("\n[%s] thread[%x,%x] enter / cluster %x / cycle %d\n", … … 1662 1730 1663 1731 // allocate a process descriptor 1664 process = process_alloc();1732 process = kmem_alloc( bits_log2(sizeof(process_t)) , AF_ZERO ); 1665 1733 1666 1734 if( process == NULL ) 1667 1735 { 1668 printk("\n[ERROR] in %s : cannot get process in cluster %x\n", 1669 __FUNCTION__, local_cxy ); 1736 1737 #if DEBUG_PROCESS_ERROR 1738 printk("\n[ERROR] in %s : thread[%x,%x] cannot allocate process descriptor / cxy %x / cycle %d\n", 1739 __FUNCTION__, pid, trdid, local_cxy, cycle ); 1740 #endif 1670 1741 return -1; 1671 1742 } … … 1675 1746 if( error ) 1676 1747 { 1677 printk("\n[ERROR] in %s : cannot get PID in cluster %x\n", 1678 __FUNCTION__, local_cxy ); 1679 process_free( process ); 1748 1749 #if DEBUG_PROCESS_ERROR 1750 printk("\n[ERROR] in %s : thread[%x,%x] cannot get PID / cxy %x / cycle %d\n", 1751 __FUNCTION__, pid, trdid, local_cxy, cycle ); 1752 #endif 1753 kmem_free( process , bits_log2(sizeof(process_t)) ); 1680 1754 return -1; 1681 1755 } 1682 1756 1683 1757 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1684 cycle = (uint32_t)hal_get_cycles();1685 1758 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1686 printk("\n[%s] thread[%x,%x] allocated child_process %x / cycle %d\n",1687 __FUNCTION__, pid, trdid, new_pid , cycle);1759 printk("\n[%s] thread[%x,%x] allocated child_process %x\n", 1760 __FUNCTION__, pid, trdid, new_pid ); 1688 1761 #endif 1689 1762 … … 1694 1767 if( error ) 1695 1768 { 1696 printk("\n[ERROR] in %s : cannot initialize child process in cluster %x\n", 1697 __FUNCTION__, local_cxy ); 1698 process_free( process ); 1769 1770 #if DEBUG_PROCESS_ERROR 1771 printk("\n[ERROR] in %s : thread[%x,%x] cannot initialize child process / cxy %x / cycle %d\n", 1772 __FUNCTION__, pid, trdid, local_cxy, cycle ); 1773 #endif 1774 cluster_pid_release( new_pid ); 1775 kmem_free( process , bits_log2(sizeof(process_t)) ); 1699 1776 return -1; 1700 1777 } 1701 1778 1702 1779 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1703 cycle = (uint32_t)hal_get_cycles();1704 1780 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1705 printk("\n[%s] thread[%x,%x] initialized child_process %x / cycle %d\n",1706 __FUNCTION__, pid, trdid, new_pid , cycle);1781 printk("\n[%s] thread[%x,%x] initialized child_process %x\n", 1782 __FUNCTION__, pid, trdid, new_pid ); 1707 1783 #endif 1708 1784 … … 1712 1788 if( error ) 1713 1789 { 1714 printk("\n[ERROR] in %s : cannot copy VMM in cluster %x\n", 1715 __FUNCTION__, local_cxy ); 1716 process_free( process ); 1790 1791 #if DEBUG_PROCESS_ERROR 1792 printk("\n[ERROR] in %s : thread[%x,%x] cannot copy VMM to child process / cxy %x / cycle %d\n", 1793 __FUNCTION__, pid, trdid, local_cxy, cycle ); 1794 #endif 1717 1795 cluster_pid_release( new_pid ); 1796 kmem_free( process , bits_log2(sizeof(process_t)) ); 1718 1797 return -1; 1719 1798 } 1720 1799 1721 1800 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1722 cycle = (uint32_t)hal_get_cycles();1723 1801 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1724 1802 { 1725 printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n",1726 __FUNCTION__, pid, trdid , cycle);1803 printk("\n[%s] thread[%x,%x] copied VMM from parent to child\n", 1804 __FUNCTION__, pid, trdid ); 1727 1805 hal_vmm_display( XPTR( local_cxy , process ) , true ); 1728 1806 } … … 1736 1814 1737 1815 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1738 cycle = (uint32_t)hal_get_cycles();1739 1816 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1740 printk("\n[%s] thread[%x,%x] / child_process %x takes TXT ownership / cycle %d\n",1741 __FUNCTION__ , pid, trdid, new_pid , cycle);1817 printk("\n[%s] thread[%x,%x] / child_process %x takes TXT ownership\n", 1818 __FUNCTION__ , pid, trdid, new_pid ); 1742 1819 #endif 1743 1820 … … 1753 1830 if( error ) 1754 1831 { 1755 printk("\n[ERROR] in %s : cannot create thread in cluster %x\n", 1756 __FUNCTION__, local_cxy ); 1757 process_free( process ); 1832 1833 #if DEBUG_PROCESS_ERROR 1834 printk("\n[ERROR] in %s : thread[%x,%x] cannot create main thread / cxy %x / cycle %d\n", 1835 __FUNCTION__, pid, trdid, local_cxy, cycle ); 1836 #endif 1758 1837 cluster_pid_release( new_pid ); 1838 kmem_free( process , bits_log2(sizeof(process_t)) ); 1759 1839 return -1; 1760 1840 } … … 1765 1845 1766 1846 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1767 cycle = (uint32_t)hal_get_cycles();1768 1847 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1769 printk("\n[%s] thread[%x,%x] created main thread %x / cycle %d\n",1770 __FUNCTION__, pid, trdid, thread , cycle);1848 printk("\n[%s] thread[%x,%x] created main thread %x\n", 1849 __FUNCTION__, pid, trdid, thread ); 1771 1850 #endif 1772 1851 … … 1787 1866 1788 1867 #if( DEBUG_PROCESS_MAKE_FORK & 1 ) 1789 cycle = (uint32_t)hal_get_cycles();1790 1868 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1791 printk("\n[%s] thread[%x,%x] set COW in DATA / ANON / REMOTE for parent and child / cycle %d\n",1792 __FUNCTION__, pid, trdid , cycle);1869 printk("\n[%s] thread[%x,%x] set COW in DATA / ANON / REMOTE for parent and child\n", 1870 __FUNCTION__, pid, trdid ); 1793 1871 #endif 1794 1872 … … 1819 1897 } // end process_make_fork() 1820 1898 1821 ////////////////////////////////////////////////i////////////////////////////////////// 1822 // This static function is called by the thread_user_exec() function : 1823 // - to register the main() arguments (args) in the <exec_info> structure. 1824 // - to register the environment variables (envs) in the <exec_info> structure. 1825 // In both cases the input is an array of NULL terminated string pointers in user 1826 // space, and the strings can be dispatched anywhere in the user process space. 1827 // This array of pointers is defined by the <u_pointers> argument. The empty slots 1828 // contain the NULL value, and the N non-empty slots are indexed from 0 to (N-1). 1829 // - The max number of envs, and the max number of args are defined by the 1830 // CONFIG_PROCESS_ARGS_NR and CONFIG_PROCESS_ENVS_MAX_NR parameters. 1831 // - The numbers of pages to store the (args) and (envs) strings are defined by the 1832 // CONFIG_VMM_ENVS_SIZE and CONFIG_VMM_STACK_SIZE parameters. 1833 /////////////////////////////////////////////////////////////////////////////////////// 1834 // Implementation note: 1835 // It allocates a kernel buffer to store a kernel copy of both the array of pointers, 1836 // and the strings. It set the pointers and copies the strings in this kernel buffer. 1837 // Finally, it registers the buffer & the actual number of strings in the process 1838 // exec_info structure (defined in the <process.h> file). 1839 /////////////////////////////////////////////////////////////////////////////////////// 1840 // @ is_args : [in] true if called for (args) / false if called for (envs). 1841 // @ u_pointers : [in] array of pointers on the strings (in user space). 1842 // @ exec_info : [out] pointer on the exec_info structure. 1843 // @ return 0 if success / non-zero if too many strings or no memory. 1844 /////////////////////////////////////////////////////////////////////////////////////// 1845 error_t process_exec_get_strings( bool_t is_args, 1846 char ** u_pointers, 1847 exec_info_t * exec_info ) 1848 { 1849 uint32_t index; // slot index in pointers array 1850 uint32_t length; // string length (in bytes) 1851 uint32_t pointers_bytes; // number of bytes to store pointers 1852 uint32_t max_index; // max size of pointers array 1853 char ** k_pointers; // base of kernel array of pointers 1854 char * k_buf_ptr; // pointer on first empty slot in strings buffer 1855 uint32_t k_buf_space; // number of bytes available in string buffer 1856 kmem_req_t req; // kernel memory allocator request 1857 char * k_buf; // kernel buffer for both pointers & strings 1858 1859 #if DEBUG_PROCESS_EXEC_GET_STRINGS 1860 thread_t * this = CURRENT_THREAD; 1861 uint32_t cycle = (uint32_t)hal_get_cycles(); 1862 #endif 1863 1864 // Allocate one block of physical memory for both the pointers and the strings 1865 // as defined by the CONFIG_VMM_ARGS_SIZE and CONFIG_VMM_ENVS_SIZE parameters 1866 // - the array of pointers is stored in the first bytes of the kernel buffer 1867 // - the strings themselve are stored in the next bytes of this buffer 1868 // Set the k_pointers, k_buf_ptr, k_buf_space, and max_index 1869 1870 if( is_args ) 1871 { 1872 req.type = KMEM_PPM; 1873 req.order = bits_log2( CONFIG_VMM_ARGS_SIZE ); 1874 req.flags = AF_KERNEL | AF_ZERO; 1875 k_buf = kmem_alloc( &req ); 1876 1877 pointers_bytes = CONFIG_PROCESS_ARGS_MAX_NR * sizeof(char *); 1878 k_pointers = (char **)k_buf; 1879 k_buf_ptr = k_buf + pointers_bytes; 1880 k_buf_space = (CONFIG_VMM_ARGS_SIZE * CONFIG_PPM_PAGE_SIZE) - pointers_bytes; 1881 max_index = CONFIG_PROCESS_ARGS_MAX_NR; 1882 1883 #if DEBUG_PROCESS_EXEC_GET_STRINGS 1884 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle ) 1885 printk("\n[%s] thread[%x,%x] for args / u_buf %x / k_buf %x\n", 1886 __FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf ); 1887 #endif 1888 1889 } 1890 else 1891 { 1892 req.type = KMEM_PPM; 1893 req.order = bits_log2( CONFIG_VMM_ENVS_SIZE ); 1894 req.flags = AF_KERNEL | AF_ZERO; 1895 k_buf = kmem_alloc( &req ); 1896 1897 pointers_bytes = CONFIG_PROCESS_ENVS_MAX_NR * sizeof(char *); 1898 k_pointers = (char **)k_buf; 1899 k_buf_ptr = k_buf + pointers_bytes; 1900 k_buf_space = (CONFIG_VMM_ENVS_SIZE * CONFIG_PPM_PAGE_SIZE) - pointers_bytes; 1901 max_index = CONFIG_PROCESS_ENVS_MAX_NR; 1902 1903 #if DEBUG_PROCESS_EXEC_GET_STRINGS 1904 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle ) 1905 printk("\n[%s] thread[%x,%x] for envs / u_buf %x / k_buf %x\n", 1906 __FUNCTION__, this->process->pid, this->trdid, u_pointers, k_buf ); 1907 #endif 1908 1909 } 1910 1911 // copy the user array of pointers to kernel buffer 1912 hal_copy_from_uspace( XPTR( local_cxy , k_pointers ), 1913 u_pointers, 1914 pointers_bytes ); 1915 1916 // WARNING : the pointers copied in the k_pointers[] array are user pointers, 1917 // after the loop below, the k_pointers[] array contains kernel pointers. 1918 1919 #if DEBUG_PROCESS_EXEC_GET_STRINGS 1920 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle ) 1921 printk("\n[%s] thread[%x,%x] copied u_ptr array to k_ptr array\n" 1922 " p0 = %x / p1 = %x / p2 = %x / p3 = %x\n", 1923 __FUNCTION__, this->process->pid, this->trdid, 1924 k_pointers[0], k_pointers[1], k_pointers[2], k_pointers[3] ); 1925 #endif 1926 1927 // scan kernel array of pointers to copy strings to kernel buffer 1928 for( index = 0 ; index < max_index ; index++ ) 1929 { 1930 // exit loop if (k_pointers[] == NUll) 1931 if( k_pointers[index] == NULL ) break; 1932 1933 // compute string length 1934 length = hal_strlen_from_uspace( k_pointers[index] ) + 1; 1935 1936 // return error if overflow in kernel buffer 1937 if( length > k_buf_space ) return -1; 1938 1939 // copy the string to kernel buffer 1940 hal_copy_from_uspace( XPTR( local_cxy , k_buf_ptr ), 1941 k_pointers[index], 1942 length ); 1943 1944 #if DEBUG_PROCESS_EXEC_GET_STRINGS 1945 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle ) 1946 printk("\n[%s] thread[%x,%x] copied string[%d] <%s> to kernel buffer / length %d\n", 1947 __FUNCTION__, this->process->pid, this->trdid, index, k_buf_ptr, length ); 1948 #endif 1949 1950 // replace the user pointer by a kernel pointer in the k_pointer[] array 1951 k_pointers[index] = k_buf_ptr; 1952 1953 // increment loop variables 1954 k_buf_ptr += length; 1955 k_buf_space -= length; 1956 1957 } // end loop on index 1958 1959 // update into exec_info structure 1960 if( is_args ) 1961 { 1962 exec_info->args_pointers = k_pointers; 1963 exec_info->args_nr = index; 1964 } 1965 else 1966 { 1967 exec_info->envs_pointers = k_pointers; 1968 exec_info->envs_buf_free = k_buf_ptr; 1969 exec_info->envs_nr = index; 1970 } 1971 1972 #if DEBUG_PROCESS_EXEC_GET_STRINGS 1973 if( DEBUG_PROCESS_EXEC_GET_STRINGS < cycle ) 1974 printk("\n[%s] thread[%x,%x] copied %d strings to kernel buffer\n", 1975 __FUNCTION__, this->process->pid, this->trdid, index ); 1976 #endif 1977 1978 return 0; 1979 1980 } // end process_exec_get_strings() 1899 #if DEBUG_PROCESS_MAKE_EXEC 1900 1901 ///////////////////////////////////////////////////////////////////////////////////////// 1902 // This static debug function displays the current state of the exec_info structure 1903 // embedded in the calling process descriptor. 1904 // 1905 // WARNING : It can be used after execution of the sys_exec function, but it cannot 1906 // be used after execution of the process_make_exec() function, because the 1907 // kernel pointers have been replaced by user pointers. 1908 ///////////////////////////////////////////////////////////////////////////////////////// 1909 static void process_exec_info_display( bool_t args_ok, 1910 bool_t envs_ok ) 1911 { 1912 uint32_t i; 1913 char * str; // local pointer on a string 1914 1915 process_t * process = CURRENT_THREAD->process; 1916 1917 // get relevant info from calling process descriptor 1918 pid_t pid = process->pid; 1919 1920 uint32_t args_nr = process->exec_info.args_nr; 1921 char ** args = process->exec_info.args_pointers; 1922 1923 uint32_t envs_nr = process->exec_info.envs_nr; 1924 char ** envs = process->exec_info.envs_pointers; 1925 1926 char * path = process->exec_info.path; 1927 1928 // get pointers on TXT0 chdev 1929 xptr_t txt0_xp = chdev_dir.txt_tx[0]; 1930 cxy_t txt0_cxy = GET_CXY( txt0_xp ); 1931 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 1932 1933 // get extended pointer on remote TXT0 lock 1934 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 1935 1936 // get TXT0 lock 1937 remote_busylock_acquire( lock_xp ); 1938 1939 nolock_printk("\n***** exec_info for process %x in cluster %x / %s\n", 1940 pid , local_cxy , path ); 1941 1942 // display arguments if required 1943 if( args_ok ) 1944 { 1945 for( i = 0 ; i < args_nr ; i++ ) 1946 { 1947 str = args[i]; 1948 if( str != NULL) // display pointer and string 1949 nolock_printk(" - &arg[%d] = %x / arg[%d] = <%s>\n", i, str, i, str ); 1950 else // display WARNING 1951 nolock_printk(" - unexpected NULL pointer for &arg[%d]\n", i ); 1952 } 1953 } 1954 1955 // display env variables if required 1956 if( envs_ok ) 1957 { 1958 for( i = 0 ; i < envs_nr ; i++ ) 1959 { 1960 str = envs[i]; 1961 if( str != NULL) // display pointer and string 1962 nolock_printk(" - &env[%d] = %x / env[%d] = <%s>\n", i, str, i, str ); 1963 else // display WARNING 1964 nolock_printk(" - unexpected NULL pointer for &env[%d]\n", i ); 1965 } 1966 } 1967 1968 // release TXT0 lock 1969 remote_busylock_release( lock_xp ); 1970 1971 } // end process_exec_info_display() 1972 1973 #endif // DEBUG_PROCESS_MAKE_EXEC 1981 1974 1982 1975 ///////////////////////////////// … … 2003 1996 uint32_t envs_size; // envs vseg size (bytes) 2004 1997 1998 #if DEBUG_PROCESS_MAKE_EXEC || DEBUG_PROCESS_ERROR 1999 uint32_t cycle = (uint32_t)hal_get_cycles(); 2000 #endif 2001 2005 2002 // get calling thread, process, pid, trdid, and ref_xp 2006 2003 this = CURRENT_THREAD; … … 2014 2011 2015 2012 #if DEBUG_PROCESS_MAKE_EXEC 2016 uint32_t cycle = (uint32_t)hal_get_cycles();2017 2013 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 2018 2014 printk("\n[%s] thread[%x,%x] enters for <%s> / cycle %d\n", … … 2032 2028 if( error ) 2033 2029 { 2034 printk("\n[ERROR] in %s : thread[%x,%x] failed to open file <%s>\n", 2035 __FUNCTION__, pid, trdid, elf_path ); 2030 2031 #if DEBUG_PROCESS_ERROR 2032 printk("\n[ERROR] in %s : thread[%x,%x] failed to open file <%s> / cycle %d\n", 2033 __FUNCTION__, pid, trdid, elf_path, cycle ); 2034 #endif 2036 2035 return -1; 2037 2036 } … … 2064 2063 #endif 2065 2064 2066 // 4. register the "args" vseg in VSL and map it in GPT, if required 2067 // this vseg contains both the array of pointers and the strings 2065 // 4. register the "args" vseg in VSL and map it in GPT, if args_nr != 0. 2066 // As this vseg contains an array of pointers, the kernel pointers 2067 // are replaced by user pointers in new process space. 2068 2068 args_nr = process->exec_info.args_nr; 2069 2069 … … 2071 2071 { 2072 2072 // get args vseg base and size in user space 2073 args_base = CONFIG_VMM_UTILS_BASE << CONFIG_PPM_PAGE_ SHIFT;2074 args_size = CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ SHIFT;2073 args_base = CONFIG_VMM_UTILS_BASE << CONFIG_PPM_PAGE_ORDER; 2074 args_size = CONFIG_VMM_ARGS_SIZE << CONFIG_PPM_PAGE_ORDER; 2075 2075 2076 2076 // create and register args vseg in VMM … … 2085 2085 if( vseg == NULL ) 2086 2086 { 2087 printk("\n[ERROR] in %s : thread[%x,%x] cannot get args vseg for <%s>\n", 2088 __FUNCTION__, pid, trdid, elf_path ); 2087 2088 #if DEBUG_PROCESS_ERROR 2089 printk("\n[ERROR] in %s : thread[%x,%x] cannot create args vseg for <%s> / cycle %d\n", 2090 __FUNCTION__, pid, trdid, elf_path, cycle ); 2091 #endif 2089 2092 return -1; 2090 2093 } … … 2098 2101 } 2099 2102 #endif 2100 // map all pages for th is"args" vseg2103 // map all pages for the "args" vseg 2101 2104 uint32_t fake_attr; // required for hal_gpt_lock_pte() 2102 2105 ppn_t fake_ppn; // required for hal_gpt_lock_pte() 2103 2106 2104 xptr_t gpt = XPTR( local_cxy , &process->vmm.gpt ); 2105 uint32_t attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE | GPT_USER | GPT_CACHABLE; 2106 vpn_t vpn = CONFIG_VMM_UTILS_BASE; 2107 ppn_t ppn = ((ppn_t)process->exec_info.args_pointers >> CONFIG_PPM_PAGE_SHIFT); 2107 xptr_t base_xp = XPTR( local_cxy , process->exec_info.args_pointers ); 2108 xptr_t gpt_xp = XPTR( local_cxy , &process->vmm.gpt ); 2109 uint32_t attr = GPT_MAPPED | GPT_SMALL | GPT_READABLE | GPT_USER | GPT_CACHABLE; 2110 vpn_t vpn = CONFIG_VMM_UTILS_BASE; 2111 ppn_t ppn = ppm_base2ppn( base_xp ); 2108 2112 2109 2113 for( n = 0 ; n < CONFIG_VMM_ARGS_SIZE ; n++ ) 2110 2114 { 2111 2115 // lock the PTE 2112 if (hal_gpt_lock_pte( gpt , vpn , &fake_attr , &fake_ppn ) )2116 if (hal_gpt_lock_pte( gpt_xp , vpn + n , &fake_attr , &fake_ppn ) ) 2113 2117 { 2114 printk("\n[ERROR] in %s : thread[%x,%x] cannot map args vpn %x for <%s>\n", 2115 __FUNCTION__, pid, trdid, vpn, elf_path ); 2118 2119 #if DEBUG_PROCESS_ERROR 2120 printk("\n[ERROR] in %s : thread[%x,%x] cannot map vpn[%x] of args vseg for <%s> / cycle %d\n", 2121 __FUNCTION__, pid, trdid, vpn + n , elf_path , cycle ); 2122 #endif 2116 2123 return -1; 2117 2124 } 2118 2125 2119 2126 // map and unlock the PTE 2120 hal_gpt_set_pte( gpt , vpn + n , attr , ppn + n );2121 2127 hal_gpt_set_pte( gpt_xp , vpn + n , attr , ppn + n ); 2128 } 2122 2129 2123 2130 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) … … 2127 2134 __FUNCTION__, pid, trdid ); 2128 2135 hal_vmm_display( ref_xp , true ); 2136 process_exec_info_display( true , false ); // args & not envs 2129 2137 } 2130 2138 #endif 2131 2139 2132 // set user space pointers in array of pointers 2133 char ** ptr = process->exec_info.args_pointers; 2134 2140 // build pointer on args buffer in kernel space 2141 char ** k_args = process->exec_info.args_pointers; 2142 2143 // build pointer on args buffer in user space 2144 char ** u_args = (char **)args_base; 2145 2146 // set user space pointers in kernel args buffer 2135 2147 for( n = 0 ; n < args_nr ; n++ ) 2136 2148 { 2137 ptr[n] = ptr[n] + args_base - (intptr_t)ptr;2149 k_args[n] = (char *)((intptr_t)k_args[n] + (intptr_t)u_args - (intptr_t)k_args); 2138 2150 } 2139 } 2140 2141 // 5. register the "envs" vseg in VSL and map it in GPT, if required 2142 // this vseg contains both the array of pointers and the strings 2151 2152 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 2153 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 2154 printk("\n[%s] thread[%x,%x] args user pointers set in exec_info\n", 2155 __FUNCTION__, pid, trdid ); 2156 #endif 2157 2158 } 2159 2160 // 5. register the "envs" vseg in VSL and map it in GPT, if envs_nr != 0. 2161 // As this vseg contains an array of pointers, the kernel pointers 2162 // are replaced by user pointers in new process space. 2163 2143 2164 envs_nr = process->exec_info.envs_nr; 2144 2165 … … 2146 2167 { 2147 2168 // get envs vseg base and size in user space from config 2148 envs_base = (CONFIG_VMM_UTILS_BASE + CONFIG_VMM_ARGS_SIZE) << CONFIG_PPM_PAGE_SHIFT; 2149 envs_size = CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_SHIFT; 2150 2151 // TODO (inspired from args) 2169 envs_base = (CONFIG_VMM_UTILS_BASE + CONFIG_VMM_ARGS_SIZE) << CONFIG_PPM_PAGE_ORDER; 2170 envs_size = CONFIG_VMM_ENVS_SIZE << CONFIG_PPM_PAGE_ORDER; 2171 2172 // TODO (should be similar to the code for args above) 2173 2174 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 2175 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 2176 printk("\n[%s] thread[%x,%x] envs user pointers set in exec_info\n", 2177 __FUNCTION__, pid, trdid ); 2178 #endif 2179 2152 2180 } 2153 2181 … … 2156 2184 // register extended pointer on .elf file in process descriptor 2157 2185 error = elf_load_process( file_xp , process ); 2186 2158 2187 if( error ) 2159 2188 { 2160 printk("\n[ERROR] in %s : thread[%x,%x] failed to access <%s>\n", 2161 __FUNCTION__, pid, trdid, elf_path ); 2189 2190 #if DEBUG_PROCESS_ERROR 2191 printk("\n[ERROR] in %s : thread[%x,%x] failed to access file <%s> / cycle %d\n", 2192 __FUNCTION__, pid, trdid , elf_path , cycle ); 2193 #endif 2162 2194 return -1; 2163 2195 } … … 2183 2215 if( vseg == NULL ) 2184 2216 { 2185 printk("\n[ERROR] in %s : thread[%x,%x] cannot set u_stack vseg for <%s>\n", 2186 __FUNCTION__, pid, trdid, elf_path ); 2217 2218 #if DEBUG_PROCESS_ERROR 2219 printk("\n[ERROR] in %s : thread[%x,%x] failed to set u_stack vseg for <%s> / cycle %d\n", 2220 __FUNCTION__, pid, trdid , elf_path , cycle ); 2221 #endif 2187 2222 return -1; 2188 2223 } … … 2205 2240 if( error ) 2206 2241 { 2207 printk("\n[ERROR] in %s : thread[%x,%x] cannot update thread for <%s>\n", 2208 __FUNCTION__ , pid, trdid, elf_path ); 2242 2243 #if DEBUG_PROCESS_ERROR 2244 printk("\n[ERROR] in %s : thread[%x,%x] failed to set main thread for <%s> / cycle %d\n", 2245 __FUNCTION__, pid, trdid , elf_path , cycle ); 2246 #endif 2209 2247 return -1; 2210 2248 } 2211 2249 2250 // should not be reached, avoid a warning 2212 2251 return 0; 2213 2252 … … 2294 2333 if( DEBUG_PROCESS_ZERO_CREATE < cycle ) 2295 2334 printk("\n[%s] initialized hal specific VMM in cluster%x\n", __FUNCTION__, local_cxy ); 2335 hal_vmm_display( XPTR( local_cxy , process ) , true ); 2296 2336 #endif 2297 2337 … … 2356 2396 2357 2397 // allocates memory for process descriptor from local cluster 2358 process = process_alloc(); 2398 process = kmem_alloc( bits_log2(sizeof(process_t)) , AF_ZERO ); 2359 2399 if( process == NULL ) 2360 2400 { … … 2506 2546 } // end process_init_create() 2507 2547 2508 ///////////////////////////////////////// 2509 void process_display( xptr_t process_xp ) 2510 { 2511 process_t * process_ptr; 2512 cxy_t process_cxy; 2548 /////////////////////////////////////////////////// 2549 uint32_t process_build_string( xptr_t process_xp, 2550 char * buffer, 2551 uint32_t size ) 2552 { 2553 int32_t length; // actual length of the string 2554 2555 process_t * process_ptr; // process descriptor local pointer 2556 cxy_t process_cxy; // process descriptor cluster identifier 2513 2557 2514 2558 xptr_t parent_xp; // extended pointer on parent process 2515 process_t * parent_ptr; 2516 cxy_t parent_cxy; 2559 process_t * parent_ptr; // parent process local pointer 2560 cxy_t parent_cxy; // parent process cluster identifier 2517 2561 2518 2562 xptr_t owner_xp; // extended pointer on owner process 2519 process_t * owner_ptr; 2520 cxy_t owner_cxy; 2521 2522 pid_t pid; 2523 pid_t ppid; 2524 lpid_t lpid; 2525 uint32_t state; 2526 uint32_t th_nr; 2563 process_t * owner_ptr; // owner process local pointer 2564 cxy_t owner_cxy; // owner process cluster identifier 2565 2566 pid_t pid; // process identifier 2567 pid_t ppid; // parent process identifier 2568 lpid_t lpid; // local process identifier 2569 uint32_t state; // terminaison state 2570 uint32_t th_nr; // number of threads 2527 2571 2528 2572 xptr_t txt_file_xp; // extended pointer on TXT_RX file descriptor … … 2540 2584 char elf_name[CONFIG_VFS_MAX_NAME_LENGTH]; 2541 2585 2586 assert( __FUNCTION__ , (size >= 80 ) , "buffer size too small" ); 2587 2542 2588 // get cluster and local pointer on process 2543 2589 process_ptr = GET_PTR( process_xp ); … … 2566 2612 if( lpid ) // user process 2567 2613 { 2568 2569 2614 // get extended pointer on file descriptor associated to TXT_RX 2570 2615 txt_file_xp = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->fd_array.array[0] ) ); 2571 2616 2572 2573 2617 assert( __FUNCTION__, (txt_file_xp != XPTR_NULL) , 2618 "process must be attached to one TXT terminal" ); 2574 2619 2575 2620 // get TXT_RX chdev pointers … … 2582 2627 XPTR( txt_chdev_cxy , txt_chdev_ptr->name ) ); 2583 2628 2629 // get TXT_owner process 2584 2630 txt_owner_xp = (xptr_t)hal_remote_l64( XPTR( txt_chdev_cxy, 2585 2631 &txt_chdev_ptr->ext.txt.owner_xp ) ); 2586 2587 2632 // get process .elf name 2588 2633 elf_file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->vfs_bin_xp ) ); … … 2594 2639 else // kernel process_zero 2595 2640 { 2596 // TXT name and .elf name are not registered in kernel process _zero2641 // TXT name and .elf name are not registered in kernel process 2597 2642 strcpy( txt_name , "txt0_rx" ); 2598 2643 txt_owner_xp = process_xp; … … 2603 2648 if( txt_owner_xp == process_xp ) 2604 2649 { 2605 nolock_printk("PID %X | %s (FG) | %X | PPID %X | TS %X | %d | %s\n", 2650 length = snprintk( buffer, size, 2651 "PID %X | %s (FG) | %X | PPID %X | TS %X | %d | %s\n", 2606 2652 pid, txt_name, process_ptr, ppid, state, th_nr, elf_name ); 2607 2653 } 2608 2654 else 2609 2655 { 2610 nolock_printk("PID %X | %s (BG) | %X | PPID %X | TS %X | %d | %s\n", 2656 length = snprintk( buffer, size, 2657 "PID %X | %s (BG) | %X | PPID %X | TS %X | %d | %s\n", 2611 2658 pid, txt_name, process_ptr, ppid, state, th_nr, elf_name ); 2612 2659 } 2660 2661 // check length 2662 if( (length < 0) ) 2663 { 2664 length = snprintk( buffer , size , 2665 "buffer too small for process %x in cluster %x", pid , process_cxy ); 2666 } 2667 2668 return length; 2669 2670 } // end process_build_string() 2671 2672 ///////////////////////////////////////// 2673 void process_display( xptr_t process_xp ) 2674 { 2675 char buffer[CONFIG_PROCESS_DISPLAY_BUF_SIZE]; 2676 2677 // build the string to be displayed 2678 process_build_string( process_xp, 2679 buffer, 2680 CONFIG_PROCESS_DISPLAY_BUF_SIZE ); 2681 // display the string 2682 nolock_puts( buffer ); 2683 2613 2684 } // end process_display() 2614 2685 -
trunk/kernel/kern/process.h
r669 r683 98 98 * This structure defines the information required by the process_make_exec() function 99 99 * to create a new reference process descriptor, and the associated main thread. 100 * All fields in this structure are filled by the sys_exec() function, using the 101 * process_exec_get_strings() function. 100 * All fields in this structure are filled by the sys_exec() function. 102 101 * 103 102 * It contains three parts: … … 106 105 * - the "envs_pointers" & "envs_nr" fields define the env variables (one env == one string). 107 106 * 108 * For both the arguments, and the environment variables, the array of pointers and the 109 * strings themselve are stored in kernel space in the same kernel buffer containing 110 * an integer number of pages, defined by CONFIG_VMM_ARGS_SIZE and CONFIG_VMM_ENVS_SIZE. 111 * This aligned kernel buffer (one or several contiguous physical pages) contains : 107 * For both the arguments and the environment variables, the array of pointers and the 108 * strings themselve are stored in the same kernel buffer. These kernel buffers contain 109 * an integer number of contiguous pages, defined by the CONFIG_VMM_ARGS_SIZE and 110 * CONFIG_VMM_ENVS_SIZE parameters respectively. 111 * Each kernel (args / envs) buffer contains : 112 112 * - in the first bytes, a fixed size kernel array of pointers on the strings. 113 113 * - in the following bytes, the strings themselves. 114 * The size of these arrays of pointers is defined by CONFIG_PROCESS_ARGS_MAX_NR 115 * and CONFIG¨PROCESS_ENVS_MAX_NR. 116 * 117 * WARNING: The "args_pointers" & "envs_pointers" kernel buffer are directly mapped to 118 * the "args" and "envs" user vsegs to be accessed by the user process. 119 * Therefore, the arrays of pointers build by the sys_exec() function contain 120 * kernel pointers, but the process_make_exec() function replace these pointers 121 * by user pointers in the new process user space. 114 * The size of these arrays of pointers is defined by the CONFIG_PROCESS_ARGS_MAX_NR and 115 * CONFIG_PROCESS_ENVS_MAX_NR parameters respectively. 116 * 117 * WARNING (1) The "args_pointers[i]" & "envs_pointers[i] stored in the dynamically 118 * allocated kernel buffers are local pointers. They must be extended by the 119 * local cluster identifier to compute a valid PPN. 120 * WARNING (2) The "args" & "envs" kernel buffers will be mapped to the "args" and "envs" 121 * user vsegs, to be accessed by the new user process. 122 * The process_make_exec() function must therefore replace the kernel pointers 123 * set by sys_exec(), by user pointers in the new process user space. 122 124 ********************************************************************************************/ 123 125 … … 232 234 * The process GPT is initialised as required by the target architecture. 233 235 * The "kcode" and "kdata" segments are registered in the process VSL. 236 * This function does not return an error code: in case of failure, it print a PANIC message 237 * on kernel terminal TXT0, and the core goes to sleep mode. 234 238 ********************************************************************************************* 235 239 * @ process : [in] pointer on process descriptor to initialize. … … 241 245 /********************************************************************************************* 242 246 * This function allocates memory and initializes the "process_init" descriptor and the 243 * associated "thread_init" descriptor. It is called once at the end of the kernel 244 * initialisation procedure. Its local process identifier is 1, and parent process 245 * is the kernel process in cluster 0. 247 * associated "thread_init" descriptor. It is called once at the end of the kernel_init() 248 * procedure. Its local process identifier is 1, and parent process is the kernel process. 246 249 * The "process_init" is the first user process, and all other user processes will be forked 247 250 * from this process. The code executed by "process_init" is stored in a .elf file, whose 248 251 * pathname is defined by the CONFIG_PROCESS_INIT_PATH configuration variable. 249 * Th e process_init does not use the [STDIN/STDOUT/STDERR] streams, but it is linked250 * to kernel TXT0, because these streams must be defined for all user processes.252 * This function does not return an error code: in case of failure, it print a PANIC message 253 * on kernel terminal TXT0, and the core goes to sleep mode. 251 254 ********************************************************************************************/ 252 255 void process_init_create( void ); … … 415 418 416 419 /********************************************************************************************* 417 * This function is called twice by the sys_exec() function :418 * - to register the main() arguments (args) in the process <exec_info> structure.419 * - to register the environment variables (envs) in the <exec_info> structure.420 * In both cases the input is an array of NULL terminated string pointers in user space,421 * identified by the <u_pointers> argument. The strings can be dispatched anywhere in422 * the calling user process space. The max number of envs, and the max number of args are423 * defined by the CONFIG_PROCESS_ARGS_NR and CONFIG_PROCESS_ENVS_MAX_NR parameters.424 *********************************************************************************************425 * Implementation Note:426 * Both the array of pointers and the strings themselve are stored in kernel space in one427 * single, dynamically allocated, kernel buffer containing an integer number of pages,428 * defined by the CONFIG_VMM_ENVS_SIZE and CONFIG_VMM_STACK_SIZE parameters.429 * This aligned kernel buffer (one or several contiguous physical pages) contains :430 * - in the first bytes a fixed size kernel array of kernel pointers on the strings.431 * - in the following bytes the strings themselves.432 * All the pointers, and the actual number of strings are stored in the process exec_info433 * structure defined in the <process.h> file.434 *********************************************************************************************435 * @ is_args : [in] true if called for (args) / false if called for (envs).436 * @ u_pointers : [in] array of pointers on the strings (in user space).437 * @ exec_info : [inout] pointer on the exec_info structure.438 * @ return 0 if success / non-zero if too many strings or no memory.439 ********************************************************************************************/440 error_t process_exec_get_strings( bool_t is_args,441 char ** u_pointers,442 exec_info_t * exec_info );443 444 /*********************************************************************************************445 420 * This function implements the "execve" system call, and is called by sys_exec() function. 446 421 * It must be called by the main thread of the calling "old" process. … … 595 570 * @ dst_xp : extended pointer on the source process descriptor (in owner cluster). 596 571 * @ src_xp : extended pointer on the destination process descriptor (in owner cluster). 597 ********************************************************************************************/ 598 void process_fd_replicate( xptr_t dst_xp, 599 xptr_t src_xp ); 572 * @ return 0 if success / return -1 if failure 573 ********************************************************************************************/ 574 error_t process_fd_replicate( xptr_t dst_xp, 575 xptr_t src_xp ); 600 576 601 577 /********************************************************************************************* … … 617 593 ********************************************************************************************/ 618 594 void process_fd_display( xptr_t process_xp ); 595 596 /********************************************************************************************* 597 * This utility function builds in the buffer defined by the <buffer> and <size> arguments 598 * a printable string describing the current state of a process descriptor identified 599 * by the <process_xp> argument, or a WARNING message if the buffer size is too small. 600 ********************************************************************************************* 601 * @ process_xp : extended pointer on target process descriptor. 602 * @ buffer : kernel buffer for string. 603 * @ size : buffer size in bytes. 604 * @ return always the string length (not including NUL), that can be a warning message. 605 ********************************************************************************************/ 606 uint32_t process_build_string( xptr_t process_xp, 607 char * buffer, 608 uint32_t size ); 619 609 620 610 /******************** Thread Related Operations *****************************************/ -
trunk/kernel/kern/scheduler.c
r669 r683 2 2 * scheduler.c - Core scheduler implementation. 3 3 * 4 * Author Alain Greiner (2016,2017,2018)4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 63 63 // @ returns pointer on selected thread descriptor 64 64 //////////////////////////////////////////////////////////////////////////////////////////// 65 static thread_t * sched_select( scheduler_t * sched )65 static thread_t * __attribute__((__noinline__))sched_select( scheduler_t * sched ) 66 66 { 67 67 thread_t * thread; … … 83 83 while( done == false ) 84 84 { 85 86 // check kernel threads list87 assert( __FUNCTION__, (count < sched->k_threads_nr), "bad kernel threads list" );88 89 85 // get next entry in kernel list 90 86 current = current->next; … … 117 113 while( done == false ) 118 114 { 119 120 // check user threads list121 assert( __FUNCTION__, (count < sched->u_threads_nr), "bad user threads list" );122 123 115 // get next entry in user list 124 116 current = current->next; -
trunk/kernel/kern/scheduler.h
r662 r683 2 2 * scheduler.h - Core scheduler definition. 3 3 * 4 * Author Alain Greiner (2016,2017,2018,2019,2020)4 * Author Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites -
trunk/kernel/kern/thread.c
r669 r683 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017,2018,2019,2020)5 * Alain Greiner (2016,2017,2018,2019,2020) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 67 67 } 68 68 } 69 70 /////////////////////////////////////////////////////////////////////////////////////71 // This static function allocates physical memory for a thread descriptor.72 // It can be called by the three functions:73 // - thread_user_create()74 // - thread_user_fork()75 // - thread_kernel_create()76 /////////////////////////////////////////////////////////////////////////////////////77 // @ return pointer on thread descriptor if success / return NULL if failure.78 /////////////////////////////////////////////////////////////////////////////////////79 static thread_t * thread_alloc( void )80 {81 kmem_req_t req; // kmem request82 83 // allocates memory for thread descriptor + kernel stack84 req.type = KMEM_PPM;85 req.order = CONFIG_THREAD_DESC_ORDER;86 req.flags = AF_KERNEL | AF_ZERO;87 88 return kmem_alloc( &req );89 90 } // end thread_alloc()91 92 69 93 70 ///////////////////////////////////////////////////////////////////////////////////// … … 144 121 145 122 #if DEBUG_BUSYLOCK 146 123 xlist_root_init( XPTR( local_cxy , &thread->busylocks_root ) ); 147 124 #endif 148 125 … … 161 138 list_entry_init( &thread->sched_list ); 162 139 163 // initialize the embedded alarm to unlink140 // initialize the embedded alarm 164 141 list_entry_init( &thread->alarm.list ); 165 142 … … 187 164 dqdt_increment_threads(); 188 165 166 // nitialize timer alarm 167 alarm_init( &thread->alarm ); 168 189 169 #if CONFIG_INSTRUMENTATION_PGFAULTS 190 191 192 193 194 195 196 197 198 170 thread->info.false_pgfault_nr = 0; 171 thread->info.false_pgfault_cost = 0; 172 thread->info.false_pgfault_max = 0; 173 thread->info.local_pgfault_nr = 0; 174 thread->info.local_pgfault_cost = 0; 175 thread->info.local_pgfault_max = 0; 176 thread->info.global_pgfault_nr = 0; 177 thread->info.global_pgfault_cost = 0; 178 thread->info.global_pgfault_max = 0; 199 179 #endif 200 180 … … 273 253 274 254 // allocate memory for thread descriptor 275 thread = thread_alloc();255 thread = kmem_alloc( CONFIG_THREAD_DESC_ORDER , AF_ZERO ); 276 256 277 257 if( thread == NULL ) … … 467 447 468 448 // allocate memory for child thread descriptor 469 child_ptr = thread_alloc();449 child_ptr = kmem_alloc( CONFIG_THREAD_DESC_ORDER , AF_ZERO ); 470 450 471 451 if( child_ptr == NULL ) … … 677 657 uint32_t cycle = (uint32_t)hal_get_cycles(); 678 658 if( DEBUG_THREAD_USER_EXEC < cycle ) 679 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",680 __FUNCTION__, process->pid, thread->trdid, cycle );659 printk("\n[%s] thread[%x,%x] enter / argc %d / argv %x / cycle %d\n", 660 __FUNCTION__, process->pid, thread->trdid, argc, argv, cycle ); 681 661 #endif 682 662 … … 727 707 #endif 728 708 729 // restore CPU registers ... andjump to user code709 // restore CPU registers => jump to user code 730 710 hal_do_cpu_restore( thread->cpu_context ); 731 711 … … 759 739 760 740 // allocate memory for new thread descriptor 761 thread = thread_alloc();741 thread = kmem_alloc( CONFIG_THREAD_DESC_ORDER , AF_ZERO ); 762 742 763 743 if( thread == NULL ) … … 839 819 840 820 // check arguments 841 assert( __FUNCTION__, (type == THREAD_IDLE) , "illegal thread type" ); 842 assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" ); 821 assert( __FUNCTION__, (type == THREAD_IDLE), 822 "illegal thread type" ); 823 824 assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr), 825 "illegal core index" ); 843 826 844 827 // set type in thread descriptor … … 848 831 error = process_register_thread( &process_zero , thread , &trdid ); 849 832 850 assert( __FUNCTION__, (error == 0), "cannot register idle_thread in kernel process" ); 833 assert( __FUNCTION__, (error == 0), 834 "cannot register idle_thread in kernel process" ); 851 835 852 836 // set trdid in thread descriptor … … 863 847 NULL ); // no user stack for a kernel thread 864 848 865 assert( __FUNCTION__, (error == 0), "cannot initialize idle_thread" ); 849 assert( __FUNCTION__, (error == 0), 850 "cannot initialize idle_thread" ); 866 851 867 852 // allocate CPU context 868 853 error = hal_cpu_context_alloc( thread ); 869 854 870 assert( __FUNCTION__, (error == 0), "cannot allocate CPU context" ); 855 assert( __FUNCTION__,(error == 0), 856 "cannot allocate CPU context" ); 871 857 872 858 // initialize CPU context … … 963 949 964 950 // release memory for thread descriptor (including kernel stack) 965 kmem_req_t req; 966 req.type = KMEM_PPM; 967 req.ptr = thread; 968 kmem_free( &req ); 951 kmem_free( thread , CONFIG_THREAD_DESC_ORDER ); 969 952 970 953 #if DEBUG_THREAD_DESTROY … … 1091 1074 } // end thread_unblock() 1092 1075 1093 ////////////////////////////////////// 1076 ////////////////////////////////////////////// 1094 1077 void thread_delete_request( xptr_t target_xp, 1095 bool_t is_forced )1078 bool_t is_forced ) 1096 1079 { 1097 1080 reg_t save_sr; // for critical section … … 1475 1458 thread->busylocks - 1, (uint32_t)hal_get_cycles() ); 1476 1459 1477 #if DEBUG_BUSYLOCK 1460 #if DEBUG_BUSYLOCK_TYPE 1478 1461 1479 1462 // scan list of busylocks -
trunk/kernel/kern/thread.h
r669 r683 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017,2018,2019,2020)5 * Alain Greiner (2016,2017,2018,2019,2020) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 96 96 #define THREAD_BLOCKED_LOCK 0x1000 /*! ANY : wait queuelock or rwlock */ 97 97 #define THREAD_BLOCKED_CLIENT 0x2000 /*! DEV : wait clients queue non empty */ 98 #define THREAD_BLOCKED_ ALARM0x4000 /*! ANY : wait a timer based alarm */98 #define THREAD_BLOCKED_SLEEP 0x4000 /*! ANY : wait a timer based alarm */ 99 99 100 100 /***************************************************************************************
Note: See TracChangeset
for help on using the changeset viewer.