Changeset 669
- Timestamp:
- Nov 19, 2020, 11:44:34 PM (4 years ago)
- Location:
- trunk/kernel/kern
- Files:
-
- 2 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/kern/alarm.c
r494 r669 1 1 /* 2 * kern/time.c - thread time related management 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 2 * alarm.c - timer based kernel alarm implementation 6 3 * 7 * This file is part of ALMOS-kernel.4 * Author Alain Greiner (2016,2017,2018,2019,2020) 8 5 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 6 * Copyright (c) UPMC Sorbonne Universites 7 * 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * You should have received a copy of the GNU General Public License 19 * along with ALMOS- kernel; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #include <types.h> 24 #include <kernel_config.h> 25 #include <hal_kernel_types.h> 26 #include <printk.h> 27 #include <list.h> 24 28 #include <thread.h> 25 #include <task.h> 26 #include <scheduler.h> 27 #include <time.h> 28 #include <list.h> 29 #include <rt_timer.h> 30 #include <kmagics.h> 29 #include <core.h> 30 #include <alarm.h> 31 31 32 error_t alarm_wait(struct alarm_info_s *info, uint_t msec) 32 //////////////////////////////////////////////////////////////////////////////////////////// 33 // This static function registers the alarm identified ny the <new_alarm> argument 34 // in the list of alarms rooted in the core identified by the <core> argument. 35 // When the existing list of alarms is not empty, it scan the list to insert the new 36 // alarm in the right place to respect the absolute dates ordering. 37 //////////////////////////////////////////////////////////////////////////////////////////// 38 // @ new_alarm : local pointer on the new alarm. 39 // @ core : local pointer on the target core. 40 //////////////////////////////////////////////////////////////////////////////////////////// 41 static void alarm_register( alarm_t * new_alarm, 42 core_t * core ) 33 43 { 34 register uint_t tm_now; 35 struct cpu_s *cpu; 36 struct alarm_s *alarm_mgr; 37 struct list_entry *iter; 38 struct alarm_info_s *current; 39 uint_t irq_state; 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 40 48 41 cpu = current_cpu; 42 alarm_mgr = &cpu->alarm_mgr; 49 bool_t done = false; 43 50 44 cpu_disable_all_irq(&irq_state); 51 // get pointers on root of alarms and lock 52 list_entry_t * root = &core->alarms_root; 53 busylock_t * lock = &core->alarms_lock; 45 54 46 tm_now = cpu_get_ticks(cpu) * MSEC_PER_TICK; 47 info->signature = ALRM_INFO_ID; 48 info->tm_wakeup = tm_now + msec; 55 // get pointer on new_alarm list_entry 56 list_entry_t * new_entry = &new_alarm->list; 49 57 50 if(list_empty(&alarm_mgr->wait_queue)) 51 list_add_first(&alarm_mgr->wait_queue, &info->list); 52 else 53 { 54 list_foreach_forward(&alarm_mgr->wait_queue, iter) 55 { 56 current = list_element(iter, struct alarm_info_s, list); 57 58 if(info->tm_wakeup <= current->tm_wakeup) 59 { 60 list_add_pred(iter, &info->list); 61 goto NEXT_TRAITMENT; 62 } 63 } 64 list_add_last(&alarm_mgr->wait_queue, &info->list); 65 } 58 // get new_alarm date 59 cycle_t new_date = new_alarm->date; 66 60 67 NEXT_TRAITMENT: 68 cpu_restore_irq(irq_state); 69 return 0; 70 } 61 // take the lock 62 busylock_acquire( lock ); 71 63 72 void alarm_clock(struct alarm_s *alarm, uint_t ticks_nr) 64 // insert new alarm to respect dates order 65 if( list_is_empty( root ) ) // list empty 66 { 67 list_add_first( root , new_entry ); 68 } 69 else // list non empty 70 { 71 for( current = root->next ; 72 (current != root) && (done == false) ; 73 current = current->next ) 74 { 75 // get pointer on previous entry in existing list 76 previous = current->pred; 77 78 // get pointer on current alarm 79 current_alarm = LIST_ELEMENT( current , alarm_t , list ); 80 81 // get date for current alarm 82 current_date = current_alarm->date; 83 84 if( current_date > new_date ) // insert new alarm just before current 85 { 86 new_entry->next = current; 87 new_entry->pred = previous; 88 89 current->pred = new_entry; 90 previous->next = new_entry; 91 92 done = true; 93 } 94 } // end for 95 96 if( done == false ) // new_date is larger than all registered dates 97 { 98 list_add_last( root , new_entry ); 99 } 100 } 101 102 // 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 ) 73 112 { 74 register uint_t tm_msec; 75 register struct list_entry *iter; 76 register struct alarm_info_s *info; 77 78 tm_msec = ticks_nr * MSEC_PER_TICK; 113 // get pointer on alarm 114 alarm_t * alarm = &thread->alarm; 79 115 80 list_foreach_forward(&alarm->wait_queue, iter) 81 { 82 info = list_element(iter, struct alarm_info_s, list); 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 ); 83 123 84 assert((info->signature == ALRM_INFO_ID), "Not an ALRM info object"); 124 } // end alarm_start() 85 125 86 if(tm_msec < info->tm_wakeup) 87 break; 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 ); 88 149 89 list_unlink(iter); 90 event_send(info->event, current_cpu->gid); 91 } 92 } 150 } // end alarm_update() 93 151 94 error_t alarm_manager_init(struct alarm_s *alarm) 152 //////////////////////////////////// 153 void alarm_stop( thread_t * thread ) 95 154 { 96 list_root_init(&alarm->wait_queue); 97 return 0; 98 } 155 // get pointer on alarm 156 alarm_t * alarm = &thread->alarm; 99 157 158 // get pointer on core 159 core_t * core = thread->core; 100 160 101 #if CONFIG_THREAD_TIME_STAT 161 // get pointer on lock protecting the alarms list 162 busylock_t * lock = &core->alarms_lock; 102 163 103 inline void tm_sleep_compute(struct thread_s *thread) 104 { 105 uint_t tm_now; 164 // unlink the alarm from the list rooted in core 165 busylock_acquire( lock ); 166 list_unlink( &alarm->list ); 167 busylock_release( lock ); 106 168 107 if(thread->type == TH_IDLE) 108 return; 169 } // end alarm_stop() 109 170 110 rt_timer_read(&tm_now);111 thread->info.tm_sleep += (tm_now - thread->info.tm_tmp);112 thread->info.tm_tmp = tm_now;113 }114 115 inline void tm_usr_compute(struct thread_s *thread)116 {117 uint_t tm_now;118 119 rt_timer_read(&tm_now);120 thread->info.tm_usr += (tm_now - thread->info.tm_tmp);121 thread->info.tm_tmp = tm_now;122 }123 124 inline void tm_sys_compute(struct thread_s *thread)125 {126 uint_t tm_now;127 128 rt_timer_read(&tm_now);129 thread->info.tm_sys += (tm_now - thread->info.tm_tmp);130 thread->info.tm_tmp = tm_now;131 }132 133 inline void tm_wait_compute(struct thread_s *thread)134 {135 uint_t tm_now;136 137 if(thread->type == TH_IDLE)138 return;139 140 rt_timer_read(&tm_now);141 thread->info.tm_wait += (tm_now - thread->info.tm_tmp);142 thread->info.tm_tmp = tm_now;143 thread->info.tm_exec = tm_now;144 }145 146 inline void tm_exit_compute(struct thread_s *thread)147 {148 uint_t tm_now;149 150 rt_timer_read(&tm_now);151 thread->info.tm_sys += tm_now - thread->info.tm_tmp;152 thread->info.tm_dead = tm_now;153 }154 155 inline void tm_born_compute(struct thread_s *thread)156 {157 uint_t tm_now;158 159 rt_timer_read(&tm_now);160 thread->info.tm_born = tm_now;161 thread->info.tm_tmp = tm_now;162 thread->info.tm_exec = tm_now;163 }164 165 inline void tm_create_compute(struct thread_s *thread)166 {167 rt_timer_read(&thread->info.tm_create);168 }169 170 171 #endif /* CONFIG_THREAD_TIME_STAT */ -
trunk/kernel/kern/alarm.h
r23 r669 1 1 /* 2 * time.h: thread time related management 3 * 4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless 5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites 2 * alarm.h - timer based kernel alarm specification 6 3 * 7 * This file is part of ALMOS-kernel.4 * Author Alain Greiner (2016,2017,2018,2019,2020) 8 5 * 9 * ALMOS-kernel is free software; you can redistribute it and/or modify it 6 * Copyright (c) UPMC Sorbonne Universites 7 * 8 * This file is part of ALMOS-MKH. 9 * 10 * ALMOS-MKH is free software; you can redistribute it and/or modify it 10 11 * under the terms of the GNU General Public License as published by 11 12 * the Free Software Foundation; version 2.0 of the License. 12 13 * 13 * ALMOS- kernelis distributed in the hope that it will be useful, but14 * ALMOS-MKH is distributed in the hope that it will be useful, but 14 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU … … 17 18 * 18 19 * You should have received a copy of the GNU General Public License 19 * along with ALMOS- kernel; if not, write to the Free Software Foundation,20 * along with ALMOS-MKH; if not, write to the Free Software Foundation, 20 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22 */ 22 23 23 #ifndef _TIME_H_24 #define _TIME_H_25 24 26 #include <types.h> 25 #ifndef _ALARM_H_ 26 #define _ALARM_H_ 27 28 #include <hal_kernel_types.h> 27 29 #include <list.h> 28 #include <device.h>29 30 30 struct event_s; 31 /**** Forward declarations ****/ 31 32 32 struct alarm_info_s 33 struct thread_s; 34 35 /****************************************************************************************** 36 * This structure defines a generic, timer based, kernel alarm. 37 * 38 * - An alarm being attached to a given thread, the alarm descriptor is embedded in the 39 * thread descriptor. A client thread can use the alarm_start() function to dynamically 40 * activate the alarm. It can use the alarm_stop() function to desactivate this alarm. 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>. 43 * - When an alarm is created by a client thread, it is registered in the list of alarms 44 * rooted in the core running the client thread. When it is stopped, the alarm is simply 45 * removed from this list. 46 * - When creating an alarm, the client thread must define an absolute date (in cycles), 47 * the func_ptr local pointer, and the args_xp extended pointer. 48 * - The list of alarms is ordered by increasing dates. At each TICK received by a core, 49 * the date of the first registered alarm is compared to the current date (in the 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. 52 * 53 * This mechanism is used bi the almos_mkh implementation of the TCP protocoL. 54 ******************************************************************************************/ 55 56 typedef struct alarm_s 33 57 { 34 uint_t signature; 58 cycle_t date; /*! absolute date for handler execution */ 59 void * func_ptr; /*! local pointer on alarm handler function */ 60 xptr_t args_xp; /*! local pointer on handler arguments */ 61 list_entry_t list; /*! all alarms attached to the same core */ 62 } 63 alarm_t; 35 64 36 /* Public members */ 37 struct event_s *event; 65 /******************************************************************************************* 66 * This defines the generic prototype for an alarm handler. 67 ******************************************************************************************/ 38 68 39 /* Private members */ 40 uint_t tm_wakeup; 41 struct list_entry list; 42 }; 69 typedef void (alarm_handler_t) ( xptr_t args_xp ); 43 70 44 struct alarm_s 45 { 46 struct list_entry wait_queue; 47 }; 71 /******************************************************************************************* 72 * 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>. 75 ******************************************************************************************* 76 * @ date : absolute date (in cycles). 77 * @ func_ptr : local pointer on the handler to execute when the alarm rings. 78 * @ args_xp : extended pointer on the handler arguments. 79 * @ thread : local pointer on the client thread. 80 ******************************************************************************************/ 81 void alarm_start( cycle_t date, 82 void * func_ptr, 83 xptr_t args_xp, 84 struct thread_s * thread ); 85 86 /******************************************************************************************* 87 * This function updates the date of the alarm attached to the thread identified by the 88 * <thread> argument. The list of alarms rooted in the core running the client thread 89 * is modified to respect the absolute dates ordering. 90 ******************************************************************************************* 91 * @ thread : local pointer on the client thread. 92 * @ new_date : absolute new date (in cycles). 93 ******************************************************************************************/ 94 void alarm_update( struct thread_s * thread, 95 cycle_t new_date ); 96 97 /******************************************************************************************* 98 * This function unlink an alarm identified by the <thread> argument from the list of 99 * alarms rooted in the core descriptor. 100 ******************************************************************************************* 101 * @ thread : local pointer on the client thread. 102 ******************************************************************************************/ 103 void alarm_stop( struct thread_s * thread ); 48 104 49 105 50 struct timeb { 51 time_t time; 52 unsigned short millitm; 53 short timezone; 54 short dstflag; 55 }; 56 57 struct timeval { 58 clock_t tv_sec; /* secondes */ 59 clock_t tv_usec; /* microsecondes */ 60 }; 61 62 struct timezone { 63 int tz_minuteswest; /* minutes west of Greenwich */ 64 int tz_dsttime; /* type of DST correction */ 65 }; 66 67 68 struct tms 69 { 70 clock_t tms_utime; /* user time */ 71 clock_t tms_stime; /* system time */ 72 clock_t tms_cutime; /* user time of children */ 73 clock_t tms_cstime; /* system time of children */ 74 }; 75 76 77 error_t alarm_manager_init(struct alarm_s *alarm); 78 error_t alarm_wait(struct alarm_info_s *info, uint_t msec); 79 80 void alarm_clock(struct alarm_s *alarm, uint_t ticks_nr); 81 82 int sys_clock (uint64_t *val); 83 int sys_alarm (unsigned nb_sec); 84 int sys_ftime (struct timeb *utime); 85 int sys_times(struct tms *utms); 86 int sys_gettimeofday(struct timeval *tv, struct timezone *tz); 87 88 #if CONFIG_THREAD_TIME_STAT 89 struct thread_s; 90 inline void tm_sleep_compute(struct thread_s *thread); 91 inline void tm_usr_compute(struct thread_s *thread); 92 inline void tm_sys_compute(struct thread_s *thread); 93 inline void tm_wait_compute(struct thread_s *thread); 94 inline void tm_exit_compute(struct thread_s *thread); 95 inline void tm_born_compute(struct thread_s *thread); 96 inline void tm_create_compute(struct thread_s *thread); 97 98 #else 99 100 #define tm_sleep_compute(thread) 101 #define tm_usr_compute(thread) 102 #define tm_sys_compute(thread) 103 #define tm_wait_compute(thread) 104 #define tm_exit_compute(thread) 105 #define tm_born_compute(thread) 106 #define tm_create_compute(thread) 107 108 #endif /* CONFIG_SCHED_STAT */ 109 110 #endif /* _TIME_H_ */ 106 #endif /* _ALARM_H_ */ -
trunk/kernel/kern/chdev.c
r662 r669 450 450 chdev_t * chdev_ptr; 451 451 452 assert( (file_xp != XPTR_NULL) ,452 assert( __FUNCTION__, (file_xp != XPTR_NULL) , 453 453 "file_xp == XPTR_NULL\n" ); 454 454 … … 462 462 inode_ptr = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) ); 463 463 464 assert( (inode_type == INODE_TYPE_DEV) ,465 "inode type %d is not INODE_TYPE_DEV\n", inode_type );464 assert( __FUNCTION__, (inode_type == FILE_TYPE_DEV) , 465 "inode type %d is not FILE_TYPE_DEV\n", inode_type ); 466 466 467 467 // get chdev local pointer from inode extension -
trunk/kernel/kern/chdev.h
r662 r669 66 66 67 67 /**************************************************************************************** 68 * This define the generic prototypes for the three functions that must be defined69 * by thedrivers implementing a generic device:68 * This defines the generic prototypes for the functions that must be defined 69 * by all drivers implementing a generic device: 70 70 * - "cmd" : start a blocking I/O operation. 71 71 * - "isr" : complete an I/O operation. … … 272 272 /**************************************************************************************** 273 273 * This function returns an extended pointer on the chdev associated to a pseudo file 274 * descriptor (type INODE_TYPE_DEV) identified by the <file_xp> argument.274 * descriptor (type FILE_TYPE_DEV) identified by the <file_xp> argument. 275 275 * It can be called by a thread running in any cluster. 276 276 * It enters kernel panic if the inode has not the expected type. -
trunk/kernel/kern/cluster.c
r657 r669 533 533 534 534 // check lpid 535 assert( (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER),535 assert( __FUNCTION__, (lpid < CONFIG_MAX_PROCESS_PER_CLUSTER), 536 536 "illegal LPID = %d" , lpid ); 537 537 538 538 // check owner cluster 539 assert( (owner_cxy == local_cxy) ,539 assert( __FUNCTION__, (owner_cxy == local_cxy) , 540 540 "local_cluster %x != owner_cluster %x" , local_cxy , owner_cxy ); 541 541 … … 732 732 uint32_t pref_nr; // number of owned processes in cluster cxy 733 733 734 assert( (cluster_is_active( cxy ) ), "illegal cluster index" );734 assert( __FUNCTION__, (cluster_is_active( cxy ) ), "illegal cluster index" ); 735 735 736 736 // get extended pointer on root and lock for local process list in cluster -
trunk/kernel/kern/core.c
r657 r669 26 26 #include <hal_kernel_types.h> 27 27 #include <hal_special.h> 28 #include <errno.h>29 28 #include <printk.h> 30 29 #include <thread.h> 31 30 #include <chdev.h> 31 #include <alarm.h> 32 32 #include <dev_pic.h> 33 33 #include <rpc.h> 34 34 #include <cluster.h> 35 35 #include <kmem.h> 36 #include <dqdt.h>37 36 #include <core.h> 38 37 … … 52 51 core->rand_last = hal_time_stamp() & 0xFFF; 53 52 54 // initialize scheduler53 // initialize the scheduler 55 54 sched_init( core ); 55 56 // initialise the alarms lock 57 busylock_init( &core->alarms_lock , LOCK_CORE_ALARMS ); 58 59 // initialise the alarms list 60 list_root_init( &core->alarms_root ); 56 61 } 62 63 /////////////////////////////////////// 64 void core_check_alarms( core_t * core ) 65 { 66 alarm_handler_t * handler; 67 68 // get pointer on root of alarms list 69 list_entry_t * root = &core->alarms_root; 70 71 // does nothing if list is empty 72 if( list_is_empty( root ) ) return; 73 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 ) 84 { 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 ); 90 } 91 } // end core_check_alarms() 57 92 58 93 ////////////////////// … … 73 108 } 74 109 75 assert( false , "core not found" ); 110 assert( __FUNCTION__, false , "core not found" ); 111 112 return 0; 76 113 } 77 114 … … 104 141 // handle scheduler 105 142 if( (ticks % CONFIG_SCHED_TICKS_PER_QUANTUM) == 0 ) sched_yield( "TICK"); 143 144 // handle alarms 145 core_check_alarms( core ); 106 146 } 107 147 -
trunk/kernel/kern/core.h
r657 r669 28 28 #include <kernel_config.h> 29 29 #include <hal_kernel_types.h> 30 #include <busylock.h> 30 31 #include <list.h> 31 32 #include <rpc.h> … … 36 37 struct thread_s; 37 38 struct chdev_s; 38 enum pic_impl_e;39 39 40 40 /**************************************************************************************** … … 54 54 uint32_t time_stamp; /*! previous time stamp (read from register) */ 55 55 56 list_entry_t alarms_root; /*! root of list of attached alarms */ 57 busylock_t alarms_lock; /*! lock protecting the list of alarms */ 58 56 59 uint32_t ticks_nr; /*! number of elapsed ticks */ 57 60 uint32_t usage; /*! cumulated busy_percent (idle / total) */ … … 70 73 * It makes the association [gid] <=> [lid], as defined in arch_info, via the 71 74 * boot_info_t structure build by the bootloader in each cluster. 72 * It allocates memory for the PIC infrastructure specific core extension.73 * It does NOT initialize the <thread_idle> and the <pic_extend> fields,74 * that must be completed later.75 * It initializes the core scheduler structures, and the alarms list and lock. 76 * It allocates memory for the PIC infrastructure specific core extension, 77 * but it does NOT initialize the <pic_extend> fields, that must be completed later. 75 78 *************************************************************************************** 76 79 * @ core : pointer on core descriptor to initialise. … … 84 87 /*************************************************************************************** 85 88 * This function returns the calling core local index (lid), making an associative 86 * in the local core_tbl[] arraybased on the hardwired (gid).89 * search in the local core_tbl[] array, based on the hardwired (gid). 87 90 *************************************************************************************** 88 91 * @ returns always the lid value. … … 113 116 /*************************************************************************************** 114 117 * This function must be called at each TICK. 115 * It updates the cycles and ticks counter in the calling core descriptor. 116 * It handles all pending alarms depending on the ticks counter value. 117 * It handles the scheduling, depending on the ticks counter value. 118 * It handles the global DQDT update, depending on the ticks counter vakue. 118 * - it updates the ticks counter in the calling core descriptor. 119 * - it checks the registered alarms depending on the ticks counter value. 120 * - it calls the scheduler, depending on the ticks counter value. 119 121 *************************************************************************************** 120 122 * @ core : pointer on core descriptor. -
trunk/kernel/kern/do_syscall.c
r657 r669 37 37 int sys_undefined( void ) 38 38 { 39 assert( false , "undefined system call" );39 assert( __FUNCTION__, false , "undefined system call" ); 40 40 return 0; 41 41 } … … 199 199 int error = 0; 200 200 201 assert( (this == CURRENT_THREAD),201 assert( __FUNCTION__, (this == CURRENT_THREAD), 202 202 "wrong <this> argument\n" ); 203 203 … … 223 223 224 224 // check kernel stack overflow 225 assert( (CURRENT_THREAD->signature == THREAD_SIGNATURE),225 assert( __FUNCTION__, (CURRENT_THREAD->signature == THREAD_SIGNATURE), 226 226 "kernel stack overflow after for thread %x in cluster %x\n", CURRENT_THREAD, local_cxy ); 227 227 -
trunk/kernel/kern/dqdt.c
r637 r669 119 119 xptr_t parent_xp ) 120 120 { 121 assert( (level <= 5) , __FUNCTION__, "illegal DQDT level %d\n", level);121 assert( __FUNCTION__, (level <= 5) , "illegal DQDT level\n" ); 122 122 123 123 uint32_t node_x; // node X coordinate … … 344 344 uint32_t y_size = cluster->y_size; 345 345 346 assert( ((x_size <= 16) && (y_size <= 16)) , "illegal mesh size\n");346 assert( __FUNCTION__, ((x_size <= 16) && (y_size <= 16)) , "illegal mesh size\n"); 347 347 348 348 // compute level_max … … 533 533 uint32_t current_level; 534 534 535 assert( (level <= 5) , __FUNCTION__, "illegal DQDT level %d\n", level);535 assert( __FUNCTION__, (level <= 5) , "illegal DQDT level\n" ); 536 536 537 537 #if DEBUG_DQDT_GET_ROOT -
trunk/kernel/kern/kernel_init.c
r662 r669 140 140 "KHM_STATE", // 6 141 141 "HTAB_STATE", // 7 142 143 "VFS_CTX", // 8 144 "PPM_FREE", // 9 145 "THREAD_JOIN", // 10 146 "XHTAB_STATE", // 11 147 "CHDEV_QUEUE", // 12 148 "CHDEV_TXT0", // 13 149 "CHDEV_TXTLIST", // 14 150 "PAGE_STATE", // 15 151 "MUTEX_STATE", // 16 152 "CONDVAR_STATE", // 17 153 "SEM_STATE", // 18 154 "PROCESS_CWD", // 19 155 "BARRIER_STATE", // 20 156 "LISTEN_SOCKET", // 21 157 158 "CLUSTER_PREFTBL", // 22 159 160 "SOCKET_STATE", // 23 161 "PPM_DIRTY", // 24 162 "CLUSTER_LOCALS", // 25 163 "CLUSTER_COPIES", // 26 164 "PROCESS_CHILDREN", // 27 165 "PROCESS_USERSYNC", // 28 166 "PROCESS_FDARRAY", // 29 167 "PROCESS_DIR", // 30 168 "VMM_VSL", // 31 169 170 "PROCESS_THTBL", // 32 171 172 "MAPPER_STATE", // 33 173 "VFS_SIZE", // 34 174 "VFS_FILE", // 35 175 "VFS_MAIN", // 36 176 "FATFS_FAT", // 37 177 "FBF_WINDOWS", // 38 142 "CORE_ALARMS", // 8 143 144 "VFS_CTX", // 9 145 "PPM_FREE", // 10 146 "THREAD_JOIN", // 11 147 "XHTAB_STATE", // 12 148 "CHDEV_QUEUE", // 13 149 "CHDEV_TXT0", // 14 150 "CHDEV_TXTLIST", // 15 151 "PAGE_STATE", // 16 152 "MUTEX_STATE", // 17 153 "CONDVAR_STATE", // 18 154 "SEM_STATE", // 19 155 "PROCESS_CWD", // 20 156 "BARRIER_STATE", // 21 157 "LISTEN_SOCKET", // 22 158 159 "CLUSTER_PREFTBL", // 23 160 161 "SOCKET_STATE", // 24 162 "PPM_DIRTY", // 25 163 "CLUSTER_LOCALS", // 26 164 "CLUSTER_COPIES", // 27 165 "PROCESS_CHILDREN", // 28 166 "PROCESS_USERSYNC", // 29 167 "PROCESS_FDARRAY", // 30 168 "PROCESS_DIR", // 31 169 "VMM_VSL", // 32 170 171 "PROCESS_THTBL", // 33 172 173 "MAPPER_STATE", // 34 174 "VFS_SIZE", // 35 175 "VFS_FILE", // 36 176 "VFS_MAIN", // 37 177 "FATFS_FAT", // 38 178 "FBF_WINDOWS", // 39 178 179 }; 179 180 … … 303 304 LOCK_CHDEV_TXT0 ); 304 305 306 // make TXT specific initialisations 307 dev_txt_init( &txt0_tx_chdev ); 308 305 309 // initialize TXT_RX[0] chdev 306 310 txt0_rx_chdev.func = func; … … 313 317 314 318 // make TXT specific initialisations 315 dev_txt_init( &txt0_tx_chdev );316 319 dev_txt_init( &txt0_rx_chdev ); 317 320 … … 1228 1231 1229 1232 hal_remote_s32( XPTR( CONFIG_VFS_ROOT_CXY , &vfs_root_inode_ptr->type ), 1230 INODE_TYPE_DIR );1233 FILE_TYPE_DIR ); 1231 1234 1232 1235 hal_remote_spt( XPTR( CONFIG_VFS_ROOT_CXY , &vfs_root_inode_ptr->extend ), … … 1372 1375 1373 1376 // check local FATFS and VFS context copies 1374 assert( (((fatfs_ctx_t *)vfs_fat_ctx_ptr->extend)->sectors_per_cluster == 8),1375 "illegal FATFS context in cluster %x\n", local_cxy);1377 assert( __FUNCTION__, (((fatfs_ctx_t *)vfs_fat_ctx_ptr->extend)->sectors_per_cluster == 8), 1378 "illegal FATFS context" ); 1376 1379 1377 1380 } … … 1468 1471 if( (core_lid == 0) && (local_cxy == 0) ) 1469 1472 { 1470 process_init_create();1473 process_init_create(); 1471 1474 } 1472 1475 -
trunk/kernel/kern/ksocket.c
r668 r669 34 34 #include <thread.h> 35 35 #include <vfs.h> 36 #include <alarm.h> 37 #include <dev_nic.h> 36 38 #include <ksocket.h> 37 #include <dev_nic.h>38 39 39 40 ////////////////////////////////////////////////////////////////////////////////////// … … 127 128 } 128 129 130 /////////////////////////////////////////////////////////////////////////////////////////// 131 // This static function implements the alarm handler used by a TX client thread to 132 // handle a retransmission timeout for a TX command (ACCEPT / CONNECT / CLOSE / SEND). 133 // The <args_xp> argument is actually an extended pointer on the involved socket. 134 // First, it updates the retransmission timeout. Then, it get the type of TX command, 135 // and request the NIC_TX server thread to re-send the unacknowledged segment. 136 /////////////////////////////////////////////////////////////////////////////////////////// 137 // @ args_xp : extended pointer on the involved socket. 138 /////////////////////////////////////////////////////////////////////////////////////////// 139 static void __attribute__((noinline)) socket_alarm_handler( xptr_t args_xp ) 140 { 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 ); 144 145 // get relevant infos from socket descriptor 146 uint32_t tx_cmd = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_cmd )); 147 uint32_t channel = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->nic_channel )); 148 xptr_t thread_xp = hal_remote_l64( XPTR( sock_cxy , &sock_ptr->tx_client )); 149 150 assert( __FUNCTION__, (thread_xp != XPTR_NULL), 151 "illegal tx_client field for a retransmission timeout" ); 152 153 // get TX client thread cluster and local pointer 154 thread_t * thread_ptr = GET_PTR( thread_xp ); 155 cxy_t thread_cxy = GET_CXY( thread_xp ); 156 157 assert( __FUNCTION__, (thread_cxy == local_cxy), 158 "the client thread must be running in the same cluster as the alarm handler" ); 159 160 // get pointers on NIC_TX[index] chdev 161 xptr_t tx_chdev_xp = chdev_dir.nic_tx[channel]; 162 chdev_t * tx_chdev_ptr = GET_PTR( tx_chdev_xp ); 163 cxy_t tx_chdev_cxy = GET_CXY( tx_chdev_xp ); 164 165 // get pointers on NIC_TX[channel] server thread 166 thread_t * tx_server_ptr = hal_remote_lpt( XPTR( tx_chdev_cxy , &tx_chdev_ptr->server )); 167 xptr_t tx_server_xp = XPTR( tx_chdev_cxy , tx_server_ptr ); 168 169 // update the date in alarm 170 alarm_update( thread_ptr , hal_get_cycles() + TCP_RETRANSMISSION_TIMEOUT ); 171 172 ////////////////////////////// 173 if( tx_cmd == CMD_TX_CONNECT ) 174 { 175 176 #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", 179 __FUNCTION__ , cycle ); 180 #endif 181 // set tx_valid to request the NIC_TX server to send a new SYN segment 182 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true ); 183 184 // update socket state 185 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->state ) , TCP_STATE_BOUND ); 186 187 // unblock the NIC_TX server thread 188 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 189 } 190 ///////////////////////////// 191 if( tx_cmd == CMD_TX_ACCEPT ) 192 { 193 194 #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", 197 __FUNCTION__ , cycle ); 198 #endif 199 // set tx_valid to request the NIC_TX server to send a new SYN-ACK segment 200 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true ); 201 202 // update socket state 203 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->state ) , TCP_STATE_SYN_RCVD ); 204 205 // unblock the NIC_TX server thread 206 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 207 } 208 //////////////////////////// 209 if( tx_cmd == CMD_TX_CLOSE ) 210 { 211 212 #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", 215 __FUNCTION__ , cycle ); 216 #endif 217 // set tx_valid to request the NIC_TX server to send a new FIN-ACK segment 218 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid ) , true ); 219 220 // update socket state 221 hal_remote_s32( XPTR( sock_cxy , &sock_ptr->state ) , TCP_STATE_ESTAB ); 222 223 // unblock the NIC_TX server thread 224 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 225 } 226 /////////////////////////// 227 if( tx_cmd == CMD_TX_SEND ) 228 { 229 // TODO build a new TX_SEND command 230 } 231 } // 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 date 243 cycle_t date = hal_get_cycles() + delay; 244 245 // get pointer on calling threadf 246 thread_t * this = CURRENT_THREAD; 247 248 // start the alarm 249 alarm_start( date, 250 &socket_alarm_handler, // func_ptr 251 socket_xp, // args_xp 252 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 threadf 264 thread_t * this = CURRENT_THREAD; 265 266 // stop the alarm 267 alarm_stop( this ); 268 } 269 129 270 ///////////////////////////////////////////////////////////////////////////////////////// 130 271 // This static function registers the socket defined by the <socket_xp> argument into … … 222 363 223 364 // build various TX extended pointers 224 xptr_t tx_lock_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock ); 225 xptr_t tx_list_xp = XPTR( socket_cxy , &socket_ptr->tx_list ); 365 xptr_t tx_lock_xp = XPTR( tx_chdev_cxy , &tx_chdev_ptr->wait_lock ); 366 xptr_t tx_list_xp = XPTR( socket_cxy , &socket_ptr->tx_list ); 367 xptr_t tx_list_next = hal_remote_l64( tx_list_xp ); 368 xptr_t tx_list_pred = hal_remote_l64( tx_list_xp + sizeof(xptr_t) ); 226 369 227 370 // get pointers on NIC_RX[channel] chdev … … 231 374 232 375 // build various RX extended pointers 233 xptr_t rx_lock_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock ); 234 xptr_t rx_list_xp = XPTR( socket_cxy , &socket_ptr->rx_list ); 235 236 // remove socket from the NIC_TX[channel] chdev clients queue 237 remote_busylock_acquire( tx_lock_xp ); 238 xlist_unlink( tx_list_xp ); 239 remote_busylock_release( tx_lock_xp ); 240 241 // remove socket from the NIC_RX[channel] chdev clients queue 242 remote_busylock_acquire( rx_lock_xp ); 243 xlist_unlink( rx_list_xp ); 244 remote_busylock_release( rx_lock_xp ); 376 xptr_t rx_lock_xp = XPTR( rx_chdev_cxy , &rx_chdev_ptr->wait_lock ); 377 xptr_t rx_list_xp = XPTR( socket_cxy , &socket_ptr->rx_list ); 378 xptr_t rx_list_next = hal_remote_l64( rx_list_xp ); 379 xptr_t rx_list_pred = hal_remote_l64( rx_list_xp + sizeof(xptr_t) ); 380 381 // remove socket from the NIC_TX[channel] chdev clients queue if registered 382 if( (tx_list_next != XPTR_NULL) || (tx_list_pred != XPTR_NULL) ) 383 { 384 remote_busylock_acquire( tx_lock_xp ); 385 xlist_unlink( tx_list_xp ); 386 remote_busylock_release( tx_lock_xp ); 387 } 388 389 // remove socket from the NIC_RX[channel] chdev clients queue if registered 390 if( (rx_list_next != XPTR_NULL) || (rx_list_pred != XPTR_NULL) ) 391 { 392 remote_busylock_acquire( rx_lock_xp ); 393 xlist_unlink( rx_list_xp ); 394 remote_busylock_release( rx_lock_xp ); 395 } 245 396 246 397 #if DEBUG_SOCKET_LINK … … 253 404 } // end socket_unlink_from_servers() 254 405 406 ///////////////////////////////////////////////////////////////////////////////////////// 407 // This function registers the socket defined by the <socket_xp> argument into the 408 // list of listening sockets rooted in the nic_rx[0] chdev. 409 ///////////////////////////////////////////////////////////////////////////////////////// 410 // @ socket_xp : [in] extended pointer on socket descriptor 411 ///////////////////////////////////////////////////////////////////////////////////////// 412 static void socket_link_to_listen( xptr_t socket_xp ) 413 { 414 // get socket cluster and local pointer 415 socket_t * socket_ptr = GET_PTR( socket_xp ); 416 cxy_t socket_cxy = GET_CXY( socket_xp ); 417 418 // get pointers on NIC_RX[0] chdev 419 xptr_t rx0_chdev_xp = chdev_dir.nic_rx[0]; 420 chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp ); 421 cxy_t rx0_chdev_cxy = GET_CXY( rx0_chdev_xp ); 422 423 // build extended pointers on list of listening sockets 424 xptr_t rx0_root_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.root ); 425 xptr_t rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock ); 426 427 // build extended pointer on socket rx_list field 428 xptr_t list_entry_xp = XPTR( socket_cxy , &socket_ptr->rx_list ); 429 430 // register socket in listening sockets list 431 remote_busylock_acquire( rx0_lock_xp ); 432 xlist_add_last( rx0_root_xp , list_entry_xp ); 433 remote_busylock_release( rx0_lock_xp ); 434 435 } // end socket_link_to_listen() 436 437 ///////////////////////////////////////////////////////////////////////////////////////// 438 // This function removes the socket defined by the <socket_xp> argument from the 439 // list of listening sockets rooted in the nic_rx[0] chdev. 440 ///////////////////////////////////////////////////////////////////////////////////////// 441 // @ socket_xp : [in] extended pointer on socket descriptor 442 ///////////////////////////////////////////////////////////////////////////////////////// 443 static void socket_unlink_from_listen( xptr_t socket_xp ) 444 { 445 // get socket cluster and local pointer 446 socket_t * socket_ptr = GET_PTR( socket_xp ); 447 cxy_t socket_cxy = GET_CXY( socket_xp ); 448 449 // get pointers on NIC_RX[0] chdev 450 xptr_t rx0_chdev_xp = chdev_dir.nic_rx[0]; 451 chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp ); 452 cxy_t rx0_chdev_cxy = GET_CXY( rx0_chdev_xp ); 453 454 // build extended pointers on lock protecting list of listening sockets 455 xptr_t rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock ); 456 457 // build extended pointer on socket rx_list field 458 xptr_t list_entry_xp = XPTR( socket_cxy , &socket_ptr->rx_list ); 459 460 // register socket in listening sockets list 461 remote_busylock_acquire( rx0_lock_xp ); 462 xlist_unlink( list_entry_xp ); 463 remote_busylock_release( rx0_lock_xp ); 464 465 } // end socket_unlink_from_listen() 466 255 467 ///////////////////////////////////////////////////////////////////////////////////////// 256 468 // This static function is called by the socket_build() and socket_accept() functions. … … 276 488 uint32_t * fdid_ptr ) 277 489 { 278 uint32_t fdid; 279 280 thread_t * this = CURRENT_THREAD; 281 process_t * process = this->process; 282 490 uint32_t fdid; 283 491 kmem_req_t req; 284 492 socket_t * socket; … … 287 495 error_t error; 288 496 497 thread_t * this = CURRENT_THREAD; 498 process_t * process = this->process; 499 289 500 #if DEBUG_SOCKET_CREATE 290 501 uint32_t cycle = (uint32_t)hal_get_cycles(); … … 294 505 #endif 295 506 296 // allocate memory for socket descriptor507 // 1. allocate memory for socket descriptor 297 508 req.type = KMEM_KCM; 298 509 req.order = bits_log2( sizeof(socket_t) ); … … 307 518 } 308 519 309 // allocate memory for rx_buf buffer520 // 2. allocate memory for rx_buf buffer 310 521 error = remote_buf_init( XPTR( cxy , &socket->rx_buf ), 311 NIC_RX_BUF_SIZE);522 bits_log2( CONFIG_SOCK_RX_BUF_SIZE ) ); 312 523 313 524 if( error ) … … 321 532 } 322 533 323 // allocate memory for r2tq queue534 // 3. allocate memory for r2tq queue 324 535 error = remote_buf_init( XPTR( cxy , &socket->r2tq ), 325 NIC_R2T_QUEUE_SIZE);536 bits_log2( CONFIG_SOCK_R2T_BUF_SIZE ) ); 326 537 if( error ) 327 538 { 328 539 printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n", 329 540 __FUNCTION__, process->pid, this->trdid ); 330 remote_buf_ destroy( XPTR( cxy , &socket->rx_buf ) );541 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); 331 542 req.type = KMEM_KCM; 332 543 req.ptr = socket; … … 337 548 // don't allocate memory for crqq queue, as it is done by the socket_listen function 338 549 339 // allocate memory for file descriptor550 // 4. allocate memory for file descriptor 340 551 req.type = KMEM_KCM; 341 552 req.order = bits_log2( sizeof(vfs_file_t) ); … … 347 558 printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n", 348 559 __FUNCTION__, process->pid, this->trdid ); 349 remote_buf_ destroy( XPTR( cxy , &socket->r2tq ) );350 remote_buf_ destroy( XPTR( cxy , &socket->rx_buf ) );560 remote_buf_release_data( XPTR( cxy , &socket->r2tq ) ); 561 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); 351 562 req.type = KMEM_KCM; 352 563 req.ptr = socket; … … 355 566 } 356 567 357 // get an fdid value, and register file descriptor in fd_array[]568 // 5. get an fdid value, and register file descriptor in fd_array[] 358 569 error = process_fd_register( process->ref_xp, 359 570 XPTR( cxy , file ), … … 366 577 req.ptr = file; 367 578 kmem_free( &req ); 368 remote_buf_ destroy( XPTR( cxy , &socket->r2tq ) );369 remote_buf_ destroy( XPTR( cxy , &socket->rx_buf ) );579 remote_buf_release_data( XPTR( cxy , &socket->r2tq ) ); 580 remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) ); 370 581 req.ptr = socket; 371 582 kmem_free( &req ); … … 388 599 389 600 // initialize file descriptor 390 hal_remote_s32( XPTR( cxy , &file->type ) , INODE_TYPE_SOCK );601 hal_remote_s32( XPTR( cxy , &file->type ) , FILE_TYPE_SOCK ); 391 602 hal_remote_spt( XPTR( cxy , &file->socket ) , socket ); 392 hal_remote_s32( XPTR( cxy , &file->refcount ) , 1 );393 603 394 604 // initialize socket lock … … 414 624 // It remove the associated file from the reference process fd_array. It unlink the 415 625 // socket from the NIC_TX [k] and NIC_RX[k] chdevs. It release all memory allocated 416 // for the structures associated to the target socket socket : file descriptor,417 // socketdescriptor, RX buffer, R2T queue, CRQ queue.626 // for the structures associated to the target socket : file descriptor, socket 627 // descriptor, RX buffer, R2T queue, CRQ queue. 418 628 ///////////////////////////////////////////////////////////////////////////////////////// 419 629 // @ file_xp : extended pointer on the file descriptor. … … 427 637 428 638 // check file_xp argument 429 assert( (file_xp != XPTR_NULL), "illegal argument\n" );639 assert( __FUNCTION__, (file_xp != XPTR_NULL), "illegal argument\n" ); 430 640 431 641 // get cluster & local pointer for file descriptor 432 642 vfs_file_t * file_ptr = GET_PTR( file_xp ); 433 643 cxy_t file_cxy = GET_CXY( file_xp ); 434 435 #if DEBUG_SOCKET_DESTROY436 uint32_t cycle = (uint32_t)hal_get_cycles();437 if( DEBUG_SOCKET_DESTROY < cycle )438 printk("\n[%s] thread[%x,%x] enter / file[%x,%x] / cycle %d\n",439 __FUNCTION__, process->pid, this->trdid, file_cxy, file_ptr, cycle );440 #endif441 644 442 645 // get local pointer for socket and file type … … 445 648 446 649 // check file descriptor type 447 assert( (file_type == INODE_TYPE_SOCK), "illegal file type\n" );448 449 // get socket nic_channel and fdid450 uint32_t channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel));650 assert( __FUNCTION__, (file_type == FILE_TYPE_SOCK), "illegal file type\n" ); 651 652 // get socket nic_channel, state, pid and fdid 653 uint32_t state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 451 654 uint32_t fdid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )); 452 453 // remove socket from NIC_TX & NIC_RX chdev queues when socket is connected 454 if( channel < LOCAL_CLUSTER->nb_nic_channels ) 655 656 #if DEBUG_SOCKET_DESTROY 657 uint32_t cycle = (uint32_t)hal_get_cycles(); 658 pid_t pid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->pid )); 659 if( DEBUG_SOCKET_DESTROY < cycle ) 660 printk("\n[%s] thread[%x,%x] enter / file[%x,%x] / cycle %d\n", 661 __FUNCTION__, process->pid, this->trdid, pid, fdid, cycle ); 662 #endif 663 664 // remove socket from NIC_TX & NIC_RX chdev queues 665 // or from the listening sockets list 666 if( state == TCP_STATE_LISTEN ) 667 { 668 socket_unlink_from_listen( XPTR( file_cxy , socket_ptr ) ); 669 } 670 else 455 671 { 456 672 socket_unlink_from_servers( XPTR( file_cxy , socket_ptr ) ); … … 466 682 467 683 // release memory allocated for buffers attached to socket descriptor 468 remote_buf_ destroy( XPTR( file_cxy , &socket_ptr->crqq ) );469 remote_buf_ destroy( XPTR( file_cxy , &socket_ptr->r2tq ) );470 remote_buf_ destroy( XPTR( file_cxy , &socket_ptr->rx_buf ) );684 remote_buf_release_data( XPTR( file_cxy , &socket_ptr->crqq ) ); 685 remote_buf_release_data( XPTR( file_cxy , &socket_ptr->r2tq ) ); 686 remote_buf_release_data( XPTR( file_cxy , &socket_ptr->rx_buf ) ); 471 687 472 688 // release memory allocated for socket descriptor … … 619 835 uint16_t port ) 620 836 { 621 vfs_ inode_type_t file_type;837 vfs_file_type_t file_type; 622 838 socket_t * socket; 623 839 uint32_t socket_type; … … 651 867 652 868 // check file descriptor type 653 if( file_type != INODE_TYPE_SOCK )869 if( file_type != FILE_TYPE_SOCK ) 654 870 { 655 871 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]", … … 691 907 vfs_file_t * file_ptr; 692 908 cxy_t file_cxy; 693 vfs_ inode_type_t file_type;909 vfs_file_type_t file_type; 694 910 socket_t * socket_ptr; 695 911 uint32_t socket_type; … … 726 942 727 943 // check file descriptor type 728 if( file_type != INODE_TYPE_SOCK )944 if( file_type != FILE_TYPE_SOCK ) 729 945 { 730 946 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n", … … 733 949 } 734 950 735 // get relevant infos from <fdid>socket descriptor951 // get relevant infos from socket descriptor 736 952 socket_type = hal_remote_l32( XPTR( file_cxy , &socket_ptr->type )); 737 953 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); … … 755 971 } 756 972 757 // compute CRQ queue depth : max( crq_depth , NIC_CRQ_QUEUE_SIZE ) 758 uint32_t depth = ( crq_depth > NIC_CRQ_QUEUE_SIZE ) ? crq_depth : NIC_CRQ_QUEUE_SIZE; 973 // compute CRQ queue depth : max( crq_depth , CONFIG_SOCK_CRQ_BUF_SIZE ) 974 uint32_t depth = ( crq_depth > CONFIG_SOCK_CRQ_BUF_SIZE ) ? 975 crq_depth : CONFIG_SOCK_CRQ_BUF_SIZE; 759 976 760 977 // allocate memory for the CRQ queue 761 978 error = remote_buf_init( XPTR( file_cxy , &socket_ptr->crqq ), 762 depth * sizeof(connect_request_t) );979 bits_log2( depth * sizeof(connect_request_t)) ); 763 980 if( error ) 764 981 { … … 771 988 hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ) , TCP_STATE_LISTEN ); 772 989 773 // get pointers on NIC_RX[0] chdev 774 xptr_t rx0_chdev_xp = chdev_dir.nic_rx[0]; 775 chdev_t * rx0_chdev_ptr = GET_PTR( rx0_chdev_xp ); 776 cxy_t rx0_chdev_cxy = GET_CXY( rx0_chdev_xp ); 777 778 // build extended pointers on list of listening sockets 779 xptr_t rx0_root_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.root ); 780 xptr_t rx0_lock_xp = XPTR( rx0_chdev_cxy , &rx0_chdev_ptr->ext.nic.lock ); 781 782 // build extended pointer on socket rx_list field 783 xptr_t list_entry_xp = XPTR( file_cxy , &socket_ptr->rx_list ); 784 785 // register <fdid> socket in listening sockets list 786 remote_busylock_acquire( rx0_lock_xp ); 787 xlist_add_last( rx0_root_xp , list_entry_xp ); 788 remote_busylock_release( rx0_lock_xp ); 990 // register socket in the list of listening socket 991 socket_link_to_listen( XPTR( file_cxy , socket_ptr ) ); 789 992 790 993 #if DEBUG_SOCKET_LISTEN … … 808 1011 vfs_file_t * file_ptr; 809 1012 cxy_t file_cxy; 810 vfs_ inode_type_t file_type; // file descriptor type1013 vfs_file_type_t file_type; // file descriptor type 811 1014 socket_t * socket_ptr; // local pointer on remote waiting socket 812 1015 uint32_t socket_type; // listening socket type … … 866 1069 867 1070 // check file descriptor type 868 if( file_type != INODE_TYPE_SOCK )1071 if( file_type != FILE_TYPE_SOCK ) 869 1072 { 870 1073 printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n", … … 976 1179 crq_status = remote_buf_status( crq_xp ); 977 1180 978 assert( (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),1181 assert( __FUNCTION__, (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)), 979 1182 "illegal socket state when client thread resumes after RX_ACCEPT" ); 980 1183 … … 999 1202 &new_remote_window ); 1000 1203 1001 assert( (error == 0),1204 assert( __FUNCTION__, (error == 0), 1002 1205 "cannot get a connection request from a non-empty CRQ" ); 1003 1206 … … 1082 1285 // unblock NIC_TX server thread 1083 1286 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 1084 1287 1288 // start retransmission timer 1289 socket_alarm_start( new_socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1290 1085 1291 #if DEBUG_SOCKET_ACCEPT 1086 1292 cycle = (uint32_t)hal_get_cycles(); … … 1100 1306 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle ); 1101 1307 #endif 1308 1309 // stop retransmission timer 1310 socket_alarm_stop(); 1102 1311 1103 1312 // get new socket state, tx_valid and tx_sts … … 1106 1315 cmd_status = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_sts )); 1107 1316 1108 assert( (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))1317 assert( __FUNCTION__, (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) 1109 1318 && (cmd_valid == false)), 1110 1319 "illegal socket state when client thread resumes after TX_ACCEPT" ); … … 1143 1352 uint16_t remote_port ) 1144 1353 { 1145 vfs_inode_type_t file_type; 1146 socket_t * socket_ptr; // local pointer on thread descriptor 1354 vfs_file_type_t file_type; 1355 xptr_t socket_xp; // extended pointer on socket descriptor 1356 socket_t * socket_ptr; // local pointer on socket descriptor 1147 1357 volatile uint32_t socket_state; // socket state (modified by the NIC_TX thread) 1148 1358 uint32_t socket_type; // socket type … … 1175 1385 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 1176 1386 socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 1387 socket_xp = XPTR( file_cxy , socket_ptr ); 1177 1388 1178 1389 #if DEBUG_SOCKET_CONNECT … … 1184 1395 1185 1396 // check file descriptor type 1186 if( file_type != INODE_TYPE_SOCK )1397 if( file_type != FILE_TYPE_SOCK ) 1187 1398 { 1188 1399 printk("\n[ERROR] in %s : illegal file type %s", … … 1263 1474 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 1264 1475 1476 // start retransmission timer 1477 socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1478 1265 1479 #if DEBUG_SOCKET_CONNECT 1266 1480 cycle = (uint32_t)hal_get_cycles(); … … 1279 1493 __FUNCTION__, pid, trdid, pid, fdid, cycle ); 1280 1494 #endif 1495 1496 // stop retransmission timer 1497 socket_alarm_stop(); 1281 1498 1282 1499 // get socket state, tx_valid and tx_sts … … 1285 1502 socket_state = hal_remote_l32( XPTR( file_cxy , &socket_ptr->state )); 1286 1503 1287 assert( (((socket_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))1504 assert( __FUNCTION__, (((socket_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) 1288 1505 && (cmd_valid == false)), 1289 1506 "illegal socket state when client thread resumes after TX_CONNECT" ); … … 1331 1548 trdid_t trdid = this->trdid; 1332 1549 1333 // get pointer on socket descriptor1334 cxy_t file_cxy 1335 vfs_file_t * file_ptr 1550 // get pointers on socket descriptor 1551 cxy_t file_cxy = GET_CXY( file_xp ); 1552 vfs_file_t * file_ptr = GET_PTR( file_xp ); 1336 1553 socket_t * socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 1337 1338 assert( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )) == fdid), 1554 xptr_t socket_xp = XPTR( file_cxy , socket_ptr ); 1555 1556 assert( __FUNCTION__, (hal_remote_l32( XPTR( file_cxy , &socket_ptr->fdid )) == fdid), 1339 1557 "unconsistent file_xp & fdid arguments"); 1340 1558 … … 1380 1598 cycle = (uint32_t)hal_get_cycles(); 1381 1599 if( cycle > DEBUG_DEV_NIC_TX ) 1382 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s /destroy socket / cycle %d\n",1600 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s => directly destroy socket / cycle %d\n", 1383 1601 __FUNCTION__, pid, trdid, pid, fdid, socket_state_str( socket_state ), cycle ); 1384 1602 #endif … … 1396 1614 cycle = (uint32_t)hal_get_cycles(); 1397 1615 if( cycle > DEBUG_DEV_NIC_TX ) 1398 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s /destroy socket / cycle %d\n",1616 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s => directly destroy socket / cycle %d\n", 1399 1617 __FUNCTION__, pid, trdid, pid, fdid, socket_state_str( socket_state ), cycle ); 1400 1618 #endif … … 1420 1638 hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid ), true ); 1421 1639 1640 // release socket lock 1641 remote_queuelock_release( socket_lock_xp ); 1642 1422 1643 // unblock NIC_TX server thread 1423 1644 thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT ); 1424 1425 // release socket lock1426 remote_queuelock_release( socket_lock_xp);1645 1646 // start retransmission timer 1647 socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1427 1648 1428 1649 #if DEBUG_SOCKET_CLOSE 1429 1650 cycle = (uint32_t)hal_get_cycles(); 1430 1651 if( DEBUG_SOCKET_CLOSE < cycle ) 1431 printk("\n[%s] thread[%x,%x] socket[%x,%d] blocks on <IO> waiting close / cycle %d \n",1432 __FUNCTION__, pid, trdid, pid, fdid, cycle );1433 #endif 1434 // block itself and deschedule1652 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s => blocks on <IO> waiting close / cycle %d \n", 1653 __FUNCTION__, pid, trdid, pid, fdid, socket_state_str( socket_state ), cycle ); 1654 #endif 1655 // client thread block itself and deschedule 1435 1656 thread_block( client_xp , THREAD_BLOCKED_IO ); 1436 1657 sched_yield( "blocked in close" ); … … 1442 1663 __FUNCTION__, pid, trdid, pid, fdid, cycle ); 1443 1664 #endif 1665 // stop retransmission timer 1666 socket_alarm_stop(); 1667 1444 1668 // take socket lock 1445 1669 remote_queuelock_acquire( socket_lock_xp ); … … 1450 1674 cmd_valid = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ) ); 1451 1675 1452 assert( (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS))1676 assert( __FUNCTION__, (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS)) 1453 1677 && (cmd_valid == false)), 1454 1678 "illegal socket state when client thread resumes after TX_CLOSE\n" … … 1483 1707 1484 1708 //////////////////////////////////////////////////////////////////////////////////////// 1485 // This static and blocking function is executed by an user thread calling one of the 1486 // four functions: socket_send() / socket_recv() / socket_sendto() / socket_recvfrom() 1709 // This static function is called by the two functions socket_send() & socket_recv(). 1487 1710 // It can be used for both UDP and TCP sockets. 1488 1711 //////////////////////////////////////////////////////////////////////////////////////// … … 1491 1714 // @ u_buf : pointer on user buffer in user space. 1492 1715 // @ length : number of bytes. 1493 // @ explicit : explicit remote IP address and port when true.1494 1716 //////////////////////////////////////////////////////////////////////////////////////// 1495 1717 // Implementation note : The behavior is different for SEND & RECV … … 1512 1734 uint32_t fdid, 1513 1735 uint8_t * u_buf, 1514 uint32_t length, 1515 bool_t explicit, 1516 uint32_t explicit_addr, 1517 uint32_t explicit_port ) 1518 { 1519 vfs_inode_type_t file_type; // file descriptor type 1736 uint32_t length ) 1737 { 1738 vfs_file_type_t file_type; // file descriptor type 1739 xptr_t socket_xp; // extended pointer on socket descriptor 1520 1740 socket_t * socket_ptr; // local pointer on socket descriptor 1521 1741 uint32_t socket_state; // current socket state … … 1529 1749 chdev_t * chdev_ptr; 1530 1750 cxy_t chdev_cxy; 1531 uint32_t remote_addr;1532 uint32_t remote_port;1533 1751 uint32_t buf_status; // number of bytes in rx_buf 1534 1752 int32_t moved_bytes; // total number of moved bytes (fot return) … … 1562 1780 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) ); 1563 1781 1564 // get local pointeron socket1782 // get pointers on socket 1565 1783 socket_ptr = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) ); 1784 socket_xp = XPTR( file_cxy , socket_ptr ); 1566 1785 1567 1786 // check file descriptor type 1568 if( file_type != INODE_TYPE_SOCK )1787 if( file_type != FILE_TYPE_SOCK ) 1569 1788 { 1570 1789 printk("\n[ERROR] in %s : illegal file type %s / socket[%x,%d]\n", … … 1584 1803 nic_channel = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel )); 1585 1804 1586 // handle the explicit remote address and port 1587 if( socket_type == SOCK_DGRAM ) // UDP socket 1588 { 1589 if( socket_state == UDP_STATE_UNBOUND ) 1590 { 1591 // release socket lock 1592 remote_queuelock_release( socket_lock_xp ); 1593 1594 printk("\n[ERROR] in %s : SEND/RECV for socket[%x,%d] in state %s\n", 1595 __FUNCTION__, process->pid, fdid, socket_state_str(socket_state) ); 1596 return -1; 1597 } 1598 1599 if( explicit ) 1600 { 1601 // update remote IP address and port into socket descriptor 1602 hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_addr ), explicit_addr ); 1603 hal_remote_s32( XPTR( file_cxy , &socket_ptr->remote_port ), explicit_port ); 1604 1605 // update socket state if required 1606 if( socket_state == UDP_STATE_BOUND ) 1607 { 1608 hal_remote_s32( XPTR( file_cxy , &socket_ptr->state ), UDP_STATE_ESTAB ); 1609 } 1610 } 1611 } 1612 else // TCP socket 1613 { 1614 if( explicit ) 1615 { 1616 // get remote IP address and port from socket descriptor 1617 remote_addr = hal_remote_l32( XPTR( file_cxy , &socket_ptr->remote_addr )); 1618 remote_port = hal_remote_l32( XPTR( file_cxy , &socket_ptr->remote_port )); 1619 1620 if( (remote_addr != explicit_addr) || (remote_port != explicit_port) ) 1621 { 1622 // release socket lock 1623 remote_queuelock_release( socket_lock_xp ); 1624 1625 printk("\n[ERROR] in %s : wrong expliciy access for socket[%x,%d]\n", 1626 __FUNCTION__, process->pid, fdid ); 1627 return -1; 1628 } 1629 } 1630 } 1631 1632 /////////////////////////////////////////////////////// 1633 if( is_send ) // TX_SEND command 1805 ///////////// 1806 if( is_send ) // SEND command 1634 1807 { 1635 1808 … … 1696 1869 thread_unblock( server_xp , THREAD_BLOCKED_CLIENT ); 1697 1870 1871 // start retransmission timer 1872 socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT ); 1873 1698 1874 #if DEBUG_SOCKET_SEND 1699 1875 cycle = (uint32_t)hal_get_cycles(); … … 1712 1888 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle ); 1713 1889 #endif 1890 // stop retransmission timer 1891 socket_alarm_stop(); 1892 1714 1893 // take socket lock 1715 1894 remote_queuelock_acquire( socket_lock_xp ); … … 1727 1906 1728 1907 // check SEND command completed when TX client thread resumes 1729 assert( (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),1908 assert( __FUNCTION__, (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1730 1909 "illegal socket state when client thread resumes after TX_SEND\n" 1731 1910 " tx_todo = %d / tx_status = %d / tx_valid = %d\n", … … 1759 1938 } 1760 1939 1761 } // end TX_SEND command1762 1763 //// ////////////////////////////////////////////////////1764 else // R X_RECV command1940 } // end SEND command 1941 1942 //// 1943 else // RECV command 1765 1944 { 1766 1945 … … 1837 2016 buf_status = remote_buf_status( rx_buf_xp ); 1838 2017 1839 assert( (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),2018 assert( __FUNCTION__, (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 1840 2019 "illegal socket state when client thread resumes after RX_RECV\n" 1841 2020 " buf_status = %d / rx_sts = %d / rx_valid = %d\n", … … 1891 2070 return moved_bytes; 1892 2071 1893 } // end R X_RECV command2072 } // end RECV command 1894 2073 } // end socket_move_data() 1895 1896 2074 1897 2075 /////////////////////////////////// … … 1900 2078 uint32_t length ) 1901 2079 { 1902 int nbytes = socket_move_data( true, // SEND 1903 fdid, 1904 u_buf, 1905 length, 1906 false, 0, 0 ); // no explicit remote socket 1907 return nbytes; 1908 2080 return socket_move_data( true, // SEND 2081 fdid, 2082 u_buf, 2083 length ); 1909 2084 } // end socket_send() 1910 1911 /////////////////////////////////////1912 int socket_sendto( uint32_t fdid,1913 uint8_t * u_buf,1914 uint32_t length,1915 uint32_t remote_addr,1916 uint32_t remote_port )1917 {1918 int nbytes = socket_move_data( true, // SEND1919 fdid,1920 u_buf,1921 length,1922 true, // explicit remote socket1923 remote_addr,1924 remote_port );1925 return nbytes;1926 1927 } // end socket_sendto()1928 2085 1929 2086 /////////////////////////////////// … … 1932 2089 uint32_t length ) 1933 2090 { 1934 int nbytes = socket_move_data( false, // RECV 1935 fdid, 1936 u_buf, 1937 length, 1938 false, 0, 0 ); // no explicit remote socket 1939 return nbytes; 1940 2091 return socket_move_data( false, // RECV 2092 fdid, 2093 u_buf, 2094 length ); 1941 2095 } // end socket_recv() 1942 1943 1944 ///////////////////////////////////////1945 int socket_recvfrom( uint32_t fdid,1946 uint8_t * u_buf,1947 uint32_t length,1948 uint32_t remote_addr,1949 uint32_t remote_port )1950 {1951 int nbytes = socket_move_data( false, // RECV1952 fdid,1953 u_buf,1954 length,1955 true, // explicit remote socket1956 remote_addr,1957 remote_port );1958 return nbytes;1959 1960 } // end socket_recvfrom()1961 2096 1962 2097 //////////////////////////////////////////// -
trunk/kernel/kern/ksocket.h
r668 r669 440 440 * @ fdid : [in] file descriptor index identifying the local server socket. 441 441 * @ crq_depth : [in] depth of CRQ queue of pending connection requests. 442 * @ return 0 if success / return -1 if failure 442 443 ***************************************************************************************/ 443 444 int socket_listen( uint32_t fdid, … … 549 550 550 551 /**************************************************************************************** 551 * This blocking function implements the sendto() syscall.552 * It registers the <remote_addr> and <remote_port> arguments in the local socket553 * descriptor, and does the same thing as the socket_send() function above,554 * but can be called on an unconnected UDP socket.555 ****************************************************************************************556 * @ fdid : [in] file descriptor index identifying the socket.557 * @ u_buf : [in] pointer on buffer containing packet in user space.558 * @ length : [in] packet size in bytes.559 * @ remote_addr : [in] destination IP address.560 * @ remote_port : [in] destination port.561 * @ return number of sent bytes if success / return -1 if failure.562 ***************************************************************************************/563 int socket_sendto( uint32_t fdid,564 uint8_t * u_buf,565 uint32_t length,566 uint32_t remote_addr,567 uint32_t remote_port );568 569 /****************************************************************************************570 552 * This blocking function implements the recv() syscall. 571 553 * It is used to receive data that has been stored by the NIC_RX server thread in the … … 594 576 595 577 /**************************************************************************************** 596 * This blocking function implements the recvfrom() syscall.597 * It registers the <remote_addr> and <remote_port> arguments in the local socket598 * descriptor, and does the same thing as the socket_recv() function above,599 * but can be called on an unconnected UDP socket.600 ****************************************************************************************601 * @ fdid : [in] file descriptor index identifying the socket.602 * @ u_buf : [in] pointer on buffer containing packet in user space.603 * @ length : [in] packet size in bytes.604 * @ remote_addr : [in] destination IP address.605 * @ remote_port : [in] destination port.606 * @ return number of received bytes if success / return -1 if failure.607 ***************************************************************************************/608 int socket_recvfrom( uint32_t fdid,609 uint8_t * u_buf,610 uint32_t length,611 uint32_t remote_addr,612 uint32_t remote_port );613 614 /****************************************************************************************615 578 * This blocking function implements the close() syscall for a socket. 616 579 * - For a UDP socket, it simply calls the static socket_destroy() function to release -
trunk/kernel/kern/printk.c
r662 r669 2 2 * printk.c - Kernel Log & debug messages API implementation. 3 3 * 4 * authors Alain Greiner (2016,2017,2018 )4 * authors Alain Greiner (2016,2017,2018,2019,2020) 5 5 * 6 6 * Copyright (c) UPMC Sorbonne Universites … … 34 34 35 35 /////////////////////////////////////////////////////////////////////////////////// 36 // Extern variables36 // Extern 37 37 /////////////////////////////////////////////////////////////////////////////////// 38 38 39 39 extern chdev_directory_t chdev_dir; // defined in chdev.h / allocated in kernel_init.c 40 40 41 ///////////////////////////////////// 42 uint32_t snprintf( char * string, 43 uint32_t length, 44 char * format, ... ) 45 { 46 47 #define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0); 48 49 va_list args; // printf arguments 50 uint32_t ps; // pointer to the string buffer 51 52 ps = 0; 53 va_start( args , format ); 54 55 xprintf_text: 56 41 ////////////////////////////////////////////////////////////////////////////////////// 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. 47 // It returns -2 in case of illegal format, it returns -1 if the formated string 48 // exceeds the length argument. 49 ////////////////////////////////////////////////////////////////////////////////////// 50 // @ string : buffer allocated by caller. 51 // @ length : buffer size in bytes 52 // @ format : printf like format. 53 // @ args : va_list of arguments. 54 // @ return string length if success / -1 if buffer too small / -2 if illegal format. 55 ////////////////////////////////////////////////////////////////////////////////////// 56 static int32_t format_to_string( char * string, 57 uint32_t length, 58 const char * format, 59 va_list * args ) 60 { 61 62 #define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0); 63 64 uint32_t ps = 0; // index in string buffer 65 66 format_to_string_text: 67 68 // handle one character per iteration 57 69 while ( *format != 0 ) 58 70 { … … 60 72 { 61 73 format++; 62 goto xprintf_arguments;74 goto format_to_string_arguments; 63 75 } 64 76 else // copy one char to string 65 77 { 66 TO_STR EAM( *format );78 TO_STRING( *format ); 67 79 format++; 68 80 } 69 81 } 70 82 71 va_end( args ); 72 73 // add terminating NUL chracter 74 TO_STREAM( 0 ); 83 TO_STRING( 0 ); 75 84 return ps; 76 85 77 xprintf_arguments:86 format_to_string_arguments: 78 87 79 88 { … … 84 93 uint32_t i; 85 94 86 // Ignore fields width and precision87 for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ );88 89 95 switch (*format) 90 96 { 91 97 case ('c'): // char conversion 92 98 { 93 int val = va_arg( args, int );94 buf[0] = val;99 int val = va_arg( *args , int ); 100 buf[0] = (char)val; 95 101 pbuf = buf; 96 102 len = 1; 97 103 break; 98 104 } 99 case ('b'): // excactly 2 digits hexadecimal integer100 {101 int val = va_arg( args, int );102 int val_lsb = val & 0xF;103 int val_msb = (val >> 4) & 0xF;104 buf[0] = HexaTab[val_msb];105 buf[1] = HexaTab[val_lsb];106 len = 2;107 pbuf = buf;108 break;109 }110 105 case ('d'): // up to 10 digits decimal signed integer 111 106 { 112 int val = va_arg( args, int );107 int32_t val = va_arg( *args , int32_t ); 113 108 if (val < 0) 114 109 { 115 TO_STR EAM( '-' );110 TO_STRING( '-' ); 116 111 val = -val; 117 112 } … … 127 122 case ('u'): // up to 10 digits decimal unsigned integer 128 123 { 129 uint32_t val = va_arg( args, uint32_t );130 for(i = 0; i < 10; i++)131 {132 buf[9 - i] = HexaTab[val % 10];133 if (!(val /= 10)) break;134 }135 len = i + 1;136 pbuf = &buf[9 - i];137 break;138 }139 case ('x'): // up to 8 digits hexadecimal140 case ('l'): // up to 16 digits hexadecimal141 {142 uint32_t imax;143 uint64_t val;144 145 if ( *format == 'l' ) // 64 bits146 {147 val = va_arg( args, uint64_t);148 imax = 16;149 }150 else // 32 bits151 {152 val = va_arg( args, uint32_t);153 imax = 8;154 }155 156 TO_STREAM( '0' );157 TO_STREAM( 'x' );158 159 for(i = 0; i < imax; i++)160 {161 buf[(imax-1) - i] = HexaTab[val % 16];162 if (!(val /= 16)) break;163 }164 len = i + 1;165 pbuf = &buf[(imax-1) - i];166 break;167 }168 case ('X'): // exactly 8 digits hexadecimal169 {170 uint32_t val = va_arg( args , uint32_t );171 for(i = 0; i < 8; i++)172 {173 buf[7 - i] = HexaTab[val % 16];174 val = (val>>4);175 }176 len = 8;177 pbuf = buf;178 break;179 }180 case ('s'): /* string */181 {182 char* str = va_arg( args, char* );183 while (str[len]) { len++; }184 pbuf = str;185 break;186 }187 default: // unsupported argument type188 {189 return -1;190 }191 } // end switch on argument type192 193 format++;194 195 // copy argument to string196 for( i = 0 ; i < len ; i++ )197 {198 TO_STREAM( pbuf[i] );199 }200 201 goto xprintf_text;202 }203 } // end snprintf()204 205 //////////////////////////////////////////////////////////////////////////////////////206 // This static function is called by printk(), assert() and nolock_printk()207 // to display a formated string on TXT0, using a busy waiting policy.208 //////////////////////////////////////////////////////////////////////////////////////209 // @ format : printf like format.210 // @ args : va_list of arguments.211 //////////////////////////////////////////////////////////////////////////////////////212 static void kernel_printf( const char * format,213 va_list * args )214 {215 216 printf_text:217 218 while (*format)219 {220 uint32_t i;221 for (i = 0 ; format[i] && (format[i] != '%') ; i++);222 if (i)223 {224 dev_txt_sync_write( format, i );225 format += i;226 }227 if (*format == '%')228 {229 format++;230 goto printf_arguments;231 }232 }233 234 return;235 236 printf_arguments:237 238 {239 char buf[20];240 char * pbuf = NULL;241 uint32_t len = 0;242 static const char HexaTab[] = "0123456789ABCDEF";243 uint32_t i;244 245 switch (*format++)246 {247 case ('c'): /* char conversion */248 {249 int val = va_arg( *args , int );250 len = 1;251 buf[0] = (char)val;252 pbuf = &buf[0];253 break;254 }255 case ('b'): /* exactly 2 digits hexadecimal */256 {257 int val = va_arg( *args, int );258 int val_lsb = val & 0xF;259 int val_msb = (val >> 4) & 0xF;260 buf[0] = HexaTab[val_msb];261 buf[1] = HexaTab[val_lsb];262 len = 2;263 pbuf = buf;264 break;265 }266 case ('d'): /* up to 10 digits signed decimal */267 {268 int val = va_arg( *args , int );269 if (val < 0)270 {271 val = -val;272 dev_txt_sync_write( "-" , 1 );273 }274 for(i = 0; i < 10; i++)275 {276 buf[9 - i] = HexaTab[val % 10];277 if (!(val /= 10)) break;278 }279 len = i + 1;280 pbuf = &buf[9 - i];281 break;282 }283 case ('u'): /* up to 10 digits unsigned decimal */284 {285 124 uint32_t val = va_arg( *args , uint32_t ); 286 125 for(i = 0; i < 10; i++) … … 293 132 break; 294 133 } 295 case ('x'): /* up to 8 digits hexadecimal */ 134 case ('x'): // up to 8 digits hexad after "0x" 135 case ('X'): // exactly 8 digits hexa after "0x" 296 136 { 297 137 uint32_t val = va_arg( *args , uint32_t ); 298 dev_txt_sync_write( "0x" , 2 ); 299 for(i = 0; i < 8; i++) 138 TO_STRING( '0' ); 139 TO_STRING( 'x' ); 140 for(i = 0 ; i < 8 ; i++) 300 141 { 301 142 buf[7 - i] = HexaTab[val & 0xF]; 302 if (!(val = (val>>4))) break; 143 if( (*format == 'x') && ((val >> 4) == 0) ) break; 144 val = val >> 4; 303 145 } 304 146 len = i + 1; … … 306 148 break; 307 149 } 308 case ('X'): /* exactly 8 digits hexadecimal */ 150 case ('l'): // up to 16 digits hexa after "0x" 151 case ('L'): // exactly 16 digits hexa after "0x" 309 152 { 310 uint32_t val = va_arg( *args , uint32_t ); 311 dev_txt_sync_write( "0x" , 2 ); 312 for(i = 0; i < 8; i++) 313 { 314 buf[7 - i] = HexaTab[val & 0xF]; 315 val = (val>>4); 316 } 317 len = 8; 318 pbuf = buf; 319 break; 320 } 321 case ('l'): /* up to 16 digits hexadecimal */ 322 { 323 uint64_t val = va_arg( *args , uint64_t ); 324 dev_txt_sync_write( "0x" , 2 ); 325 for(i = 0; i < 16; i++) 153 uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) | 154 ((uint64_t)va_arg( *args, uint32_t)); 155 TO_STRING( '0' ); 156 TO_STRING( 'x' ); 157 for(i = 0 ; i < 16 ; i++) 326 158 { 327 159 buf[15 - i] = HexaTab[val & 0xF]; 328 if (!(val = (val>>4))) break; 160 if( (*format == 'l') && ((val >> 4) == 0) ) break; 161 val = val >> 4; 329 162 } 330 163 len = i + 1; … … 332 165 break; 333 166 } 334 case ('L'): /* exactly 16 digits hexadecimal */335 {336 uint64_t val = va_arg( *args , uint64_t );337 dev_txt_sync_write( "0x" , 2 );338 for(i = 0; i < 16; i++)339 {340 buf[15 - i] = HexaTab[val & 0xF];341 val = (val>>4);342 }343 len = 16;344 pbuf = buf;345 break;346 }347 167 case ('s'): /* string */ 348 168 { 349 169 char* str = va_arg( *args , char* ); 350 while (str[len]) 351 { 352 len++; 353 } 170 while (str[len]) { len++; } 354 171 pbuf = str; 355 172 break; 356 173 } 357 default: 174 default: // unsupported argument type 358 175 { 359 dev_txt_sync_write( "\n[PANIC] in kernel_printf() : illegal format\n", 45 );176 return -2; 360 177 } 361 } 362 363 if( pbuf != NULL ) dev_txt_sync_write( pbuf, len ); 178 } // end switch on argument type 179 180 format++; 181 182 // copy argument sub-string to the string buffer 183 for( i = 0 ; i < len ; i++ ) 184 { 185 TO_STRING( pbuf[i] ); 186 } 364 187 365 goto printf_text; 366 } 367 368 } // end kernel_printf() 188 goto format_to_string_text; 189 } 190 } // end format_to_string() 369 191 370 192 ////////////////////////////////// 371 193 void printk( char * format , ... ) 372 194 { 195 char buffer[CONFIG_PRINTK_BUF_SIZE]; 373 196 va_list args; 197 int32_t length; 198 199 // build args va_list 200 va_start( args , format ); 374 201 375 202 // get pointers on TXT0 chdev … … 384 211 remote_busylock_acquire( lock_xp ); 385 212 386 // display format on TXT0 in busy waiting mode 387 va_start( args , format ); 388 kernel_printf( format , &args ); 213 // build a string from format 214 length = format_to_string( buffer, 215 CONFIG_PRINTK_BUF_SIZE, 216 format, 217 &args ); 389 218 va_end( args ); 219 220 if( length > 0 ) // call TXT driver to display formated string on TXT0 221 { 222 dev_txt_sync_write( buffer , length ); 223 } 224 else if( length == -2 ) // illegal format => display a warning on TXT0 225 { 226 thread_t * this = CURRENT_THREAD; 227 228 nolock_printk("\n[PANIC] from printk : illegal format\n" 229 "thread[%x,%x] on core[%x,%d] at cycle %l\n", 230 this->process->pid, this->trdid, 231 local_cxy, this->core->lid, hal_get_cycles() ); 232 } 233 else // format too long => display a warning on TXT0 234 { 235 thread_t * this = CURRENT_THREAD; 236 237 nolock_printk("\n[PANIC] from printk : formated string too long\n" 238 "thread[%x,%x] on core[%x,%d] at cycle %l\n", 239 this->process->pid, this->trdid, 240 local_cxy, this->core->lid, hal_get_cycles() ); 241 } 390 242 391 243 // release TXT0 lock 392 244 remote_busylock_release( lock_xp ); 393 } 245 246 } // end printk() 394 247 395 248 ///////////////////////////////////////// 396 249 void nolock_printk( char * format , ... ) 397 250 { 251 char buffer[CONFIG_PRINTK_BUF_SIZE]; 398 252 va_list args; 399 400 // call kernel_printf on TXT0, in busy waiting mode 253 int32_t length; 254 255 // build args va_list 401 256 va_start( args , format ); 402 kernel_printf( format , &args ); 257 258 // build a string from format 259 length = format_to_string( buffer, 260 CONFIG_PRINTK_BUF_SIZE, 261 format, 262 &args ); 403 263 va_end( args ); 404 } 405 406 //////////////////////////////////// 407 void panic( const char * function_name, 408 uint32_t line, 409 cycle_t cycle, 410 const char * format, 411 ... ) 412 { 413 // get pointers on TXT0 chdev 414 xptr_t txt0_xp = chdev_dir.txt_tx[0]; 415 cxy_t txt0_cxy = GET_CXY(txt0_xp); 416 chdev_t * txt0_ptr = GET_PTR(txt0_xp); 417 418 // get extended pointer on remote TXT0 lock 419 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 420 421 // get TXT0 lock 422 remote_busylock_acquire( lock_xp ); 423 424 // get calling thread 425 thread_t * current = CURRENT_THREAD; 426 427 // print generic infos 428 nolock_printk("\n\n[PANIC] in %s: line %d | cycle %d\n" 429 "core[%x,%d] | thread %x (%x) | process %x (%x)\n", 430 function_name, line, (uint32_t)cycle, 431 local_cxy, current->core->lid, 432 current->trdid, current, 433 current->process->pid, current->process ); 434 435 // call kernel_printf to print format 436 va_list args; 437 va_start(args, format); 438 kernel_printf(format, &args); 439 va_end(args); 440 441 // release TXT0 lock 442 remote_busylock_release( lock_xp ); 443 444 // suicide 445 hal_core_sleep(); 446 } 447 448 ////////////////////////// 449 void puts( char * string ) 264 265 if( length > 0 ) // call TXT driver to display formated string on TXT0 266 { 267 dev_txt_sync_write( buffer , length ); 268 } 269 else if( length == -2 ) // illegal format => display a warning on TXT0 270 { 271 thread_t * this = CURRENT_THREAD; 272 273 nolock_printk("\n[PANIC] from print : illegal format\n" 274 "thread[%x,%x] on core[%x,%d] at cycle %l\n", 275 this->process->pid, this->trdid, 276 local_cxy, this->core->lid, hal_get_cycles() ); 277 } 278 else // buffer too small => display a warning on TXT0 279 { 280 thread_t * this = CURRENT_THREAD; 281 282 nolock_printk("\n[PANIC] from printk : formated string too long\n" 283 "thread[%x,%x] on core[%x,%d] at cycle %l\n", 284 this->process->pid, this->trdid, 285 local_cxy, this->core->lid, hal_get_cycles() ); 286 } 287 288 } // end nolock_printk() 289 290 ////////////////////////////////////// 291 void assert( const char * func_name, 292 bool_t expr, 293 char * format , ... ) 294 { 295 if( expr == false ) 296 { 297 thread_t * this = CURRENT_THREAD; 298 trdid_t trdid = this->trdid; 299 pid_t pid = this->process->pid; 300 uint32_t lid = this->core->lid; 301 uint32_t cycle = (uint32_t)hal_get_cycles(); 302 303 char buffer[CONFIG_PRINTK_BUF_SIZE]; 304 va_list args; 305 306 va_start( args , format ); 307 308 // build a string from format 309 int32_t length = format_to_string( buffer, 310 CONFIG_PRINTK_BUF_SIZE, 311 format, 312 &args ); 313 va_end( args ); 314 315 if( length > 0 ) // display panic message on TXT0, including formated string 316 { 317 printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n %s\n", 318 func_name, local_cxy, lid, pid, trdid, cycle, buffer ); 319 } 320 else // display minimal panic message on TXT0 321 { 322 printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n", 323 func_name, local_cxy, lid, pid, trdid, cycle ); 324 } 325 } 326 } // end assert( __FUNCTION__,) 327 328 ////////////////////////////////////// 329 int32_t snprintk( char * buffer, 330 uint32_t size, 331 char * format, ... ) 332 { 333 va_list args; 334 int32_t string_length; 335 336 // build args va_list 337 va_start( args , format ); 338 339 // build a string from format 340 string_length = format_to_string( buffer , size , format , &args ); 341 va_end( args ); 342 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 } 354 } // end snprintk() 355 356 //////////////////////////////// 357 void puts( const char * string ) 450 358 { 451 359 uint32_t n = 0; … … 459 367 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 460 368 461 // get extended pointer on remote TXT0 lock 462 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 463 464 // get TXT0 lock 465 remote_busylock_acquire( lock_xp ); 369 if( txt0_xp != XPTR_NULL ) 370 { 371 // get extended pointer on remote TXT0 lock 372 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 373 374 // display string on TTY0 375 remote_busylock_acquire( lock_xp ); 376 dev_txt_sync_write( string , n ); 377 remote_busylock_release( lock_xp ); 378 } 379 } // end puts() 380 381 /////////////////////////////////////// 382 void nolock_puts( const char * string ) 383 { 384 uint32_t n = 0; 385 386 // compute string length 387 while ( string[n] > 0 ) n++; 466 388 467 389 // display string on TTY0 468 390 dev_txt_sync_write( string , n ); 469 470 // release TXT0 lock 471 remote_busylock_release( lock_xp ); 472 } 391 392 } // end nolock_puts() 393 473 394 474 395 … … 496 417 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 497 418 498 // get extended pointer on remote TXT0 chdev lock 499 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 500 501 // get TXT0 lock 502 remote_busylock_acquire( lock_xp ); 419 if( txt0_xp != XPTR_NULL ) 420 { 421 // get extended pointer on remote TXT0 chdev lock 422 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 423 424 // display buf on TTY0 425 remote_busylock_acquire( lock_xp ); 426 dev_txt_sync_write( buf , 10 ); 427 remote_busylock_release( lock_xp ); 428 } 429 } // end putx() 430 431 //////////////////////////////// 432 void nolock_putx( uint32_t val ) 433 { 434 static const char HexaTab[] = "0123456789ABCDEF"; 435 436 char buf[10]; 437 uint32_t c; 438 439 buf[0] = '0'; 440 buf[1] = 'x'; 441 442 // build buffer 443 for (c = 0; c < 8; c++) 444 { 445 buf[9 - c] = HexaTab[val & 0xF]; 446 val = val >> 4; 447 } 503 448 504 449 // display buf on TTY0 505 450 dev_txt_sync_write( buf , 10 ); 506 451 507 // release TXT0 lock 508 remote_busylock_release( lock_xp ); 509 } 452 } // end nilock_putx() 510 453 511 454 //////////////////////// … … 525 468 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 526 469 527 // get TXT0 lock 528 remote_busylock_acquire( lock_xp ); 470 if( txt0_xp != XPTR_NULL ) 471 { 472 // get TXT0 lock 473 remote_busylock_acquire( lock_xp ); 474 475 if (val < 0) 476 { 477 val = -val; 478 dev_txt_sync_write( "-" , 1 ); 479 } 480 481 for(i = 0; i < 10 ; i++) 482 { 483 buf[9 - i] = HexaTab[val % 10]; 484 if (!(val /= 10)) break; 485 } 486 487 // display buf on TTY0 488 dev_txt_sync_write( &buf[9-i] , i+1 ); 489 490 // release TXT0 lock 491 remote_busylock_release( lock_xp ); 492 } 493 } // end putd() 494 495 /////////////////////////////// 496 void nolock_putd( int32_t val ) 497 { 498 static const char HexaTab[] = "0123456789ABCDEF"; 499 500 char buf[10]; 501 uint32_t i; 529 502 530 503 if (val < 0) … … 543 516 dev_txt_sync_write( &buf[9-i] , i+1 ); 544 517 545 // release TXT0 lock 546 remote_busylock_release( lock_xp ); 547 } 518 } // end nolock_putd() 548 519 549 520 ///////////////////////// … … 570 541 chdev_t * txt0_ptr = GET_PTR( txt0_xp ); 571 542 572 // get extended pointer on remote TXT0 chdev lock 573 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 574 575 // get TXT0 lock 576 remote_busylock_acquire( lock_xp ); 543 if( txt0_xp != XPTR_NULL ) 544 { 545 // get extended pointer on remote TXT0 chdev lock 546 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 547 548 // display string on TTY0 549 remote_busylock_acquire( lock_xp ); 550 dev_txt_sync_write( buf , 18 ); 551 remote_busylock_release( lock_xp ); 552 } 553 } // end putl() 554 555 //////////////////////////////// 556 void nolock_putl( uint64_t val ) 557 { 558 static const char HexaTab[] = "0123456789ABCDEF"; 559 560 char buf[18]; 561 uint32_t c; 562 563 buf[0] = '0'; 564 buf[1] = 'x'; 565 566 // build buffer 567 for (c = 0; c < 16; c++) 568 { 569 buf[17 - c] = HexaTab[(unsigned int)val & 0xF]; 570 val = val >> 4; 571 } 577 572 578 573 // display string on TTY0 579 574 dev_txt_sync_write( buf , 18 ); 580 575 581 // release TXT0 lock 582 remote_busylock_release( lock_xp ); 583 } 576 } // end nolock_putl() 584 577 585 578 ///////////////////////////// … … 603 596 xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); 604 597 605 // get TXT0 lock 606 remote_busylock_acquire( lock_xp ); 607 608 // display string on TTY0 609 nolock_printk("\n***** %s *****\n", string ); 610 611 for ( line = 0 , byte = 0 ; line < nlines ; line++ ) 612 { 613 nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b |\n", 614 buffer + byte, 615 buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3], 616 buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7], 617 buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11], 618 buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] ); 619 620 byte += 16; 621 } 622 623 // release TXT0 lock 624 remote_busylock_release( lock_xp ); 625 } 598 if( txt0_xp != XPTR_NULL ) 599 { 600 // get TXT0 lock 601 remote_busylock_acquire( lock_xp ); 602 603 // display string on TTY0 604 nolock_printk("\n***** %s *****\n", string ); 605 606 for ( line = 0 , byte = 0 ; line < nlines ; line++ ) 607 { 608 nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b |\n", 609 buffer + byte, 610 buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3], 611 buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7], 612 buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11], 613 buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] ); 614 615 byte += 16; 616 } 617 618 // release TXT0 lock 619 remote_busylock_release( lock_xp ); 620 } 621 } // end putb() 626 622 627 623 -
trunk/kernel/kern/printk.h
r657 r669 26 26 // to display messages on the kernel terminal TXT0, using a busy waiting policy. 27 27 // It calls synchronously the TXT0 driver, without descheduling. 28 // 29 // For the formated string, the supported formats are defined below : 30 // %c : single ascii character (8 bits) 31 // %d : up to 10 digits decimal integer (32 bits) 32 // %u : up to 10 digits unsigned decimal (32 bits) 33 // %x : up to 8 digits hexadecimal integer (32 bits) 34 // %X : exactly 8 digits hexadecimal integer (32 bits) 35 // %l : up to 16 digits hexadecimal integer (64 bits) 36 // %L : exactly 16 digits hexadecimal integer (64 bits) 37 // %s : NUL terminated character string 28 38 /////////////////////////////////////////////////////////////////////////////////// 29 39 … … 37 47 38 48 /********************************************************************************** 39 * This function build a formatted string. 40 * The supported formats are defined below : 41 * %b : exactly 2 digits hexadecimal integer (8 bits) 42 * %c : single ascii character (8 bits) 43 * %d : up to 10 digits decimal integer (32 bits) 44 * %u : up to 10 digits unsigned decimal (32 bits) 45 * %x : up to 8 digits hexadecimal integer (32 bits) 46 * %X : exactly 8 digits hexadecimal integer (32 bits) 47 * %l : up to 16 digits hexadecimal integer (64 bits) 48 * %L : exactly 16 digits hexadecimal integer (64 bits) 49 * %s : NUL terminated character string 49 * These debug functions display a formated string defined by the <format,...> 50 * argument on the kernel terminal TXT0, with or without taking the TXT0 lock. 50 51 ********************************************************************************** 51 * @ string : pointer on target buffer (allocated by caller). 52 * @ length : target buffer length (number of bytes). 53 * @ format : format respecting the printf syntax. 54 * @ returns the string length (including NUL) if success / return -1 if error. 55 *********************************************************************************/ 56 uint32_t snprintf( char * string, 57 uint32_t length, 58 char * format, ... ); 59 60 /********************************************************************************** 61 * This function displays a formatted string on the kernel terminal TXT0, 62 * after taking the TXT0 lock. 63 * It uses a busy waiting policy, calling directly the relevant TXT driver, 52 * Implementation note: 53 * It uses a buffer allocated in the stack, defined by CONFIG_PRINTK_BUFFER_SIZE. 54 * It calls the snprintk() function to build a printable string in this buffer, 55 * and calls directly the dev_txt_sync_write() driver function without using the 56 * TXT server thread. 57 * It displays a [PANIC] message on kernel TXT0 terminal if the formated string 58 * exceeds the buffer size, or if the format is undefined. 64 59 ********************************************************************************** 65 60 * @ format : formatted string. 66 61 *********************************************************************************/ 67 void printk( char* format, ... ); 62 void printk ( char * format, ... ); 63 void nolock_printk( char * format, ... ); 68 64 69 65 /********************************************************************************** 70 * This function displays a formatted string on the kernel terminal TXT0, 71 * without taking the TXT0 lock. 72 * It uses a busy waiting policy, calling directly the relevant TXT driver, 66 * This debug function displays a [ASSERT] message on kernel TXT0 terminal 67 * if Boolean expression <expr> is false. It prints a detailed message including: 68 * - the calling core [cxy,lpid] 69 * - the calling thread[pid,trdid] 70 * - the current cycle 71 * - the <func_name> argument 72 * - the <string> argument 73 73 ********************************************************************************** 74 * @ format : formatted string. 74 * @ func_name : calling function name. 75 * @ expr : Boolean expression to be checked. 76 * @ format : formated message argument. 75 77 *********************************************************************************/ 76 void nolock_printk( char* format, ... ); 77 78 void assert( const char * func_name, 79 bool_t expr, 80 char * format , ... ); 78 81 79 82 /********************************************************************************** 80 * This function is called in case of kernel panic. It printt a detailed message81 * on the TXT0 terminal after taking the TXT0 lock, and call the hal_core_sleep()82 * function to block the calling core. It is used by the assert macro (below).83 * This function build a formated string in a buffer defined by the <buffer> 84 * and <buf_size> arguments, from the format defined by the <format,...> argument. 85 * This function set the NUL terminating character in target <buffer>. 83 86 ********************************************************************************** 84 * @ file_name : File where the assert macro was invoked 85 * @ function_name : Name of the calling function. 86 * @ line : Line number where the assert macro was invoked 87 * @ cycle : Cycle where the macro was invoked 88 * @ format : Formatted string 89 * ... : arguments of the format string 90 * 91 * See assert macro documentation for information about printed information. 87 * @ buffer : pointer on target buffer (allocated by caller). 88 * @ buf_size : target buffer length (number of bytes). 89 * @ format : format respecting the printf syntax. 90 * @ returns string length (not including NUL) if success / -1 if error. 92 91 *********************************************************************************/ 93 void panic( const char * function_name, 94 uint32_t line, 95 cycle_t cycle, 96 const char * format, 97 ... ) __attribute__((__noreturn__)); 92 int32_t snprintk( char * buffer, 93 uint32_t buf_size, 94 char * format, ... ); 98 95 99 96 /********************************************************************************** 100 * This macro displays a formated message on kernel TXT0 terminal, 101 * and forces the calling core in sleeping mode if a Boolean condition is false. 102 * Actually used to debug the kernel. 103 * 104 * Extra information printed by assert: 105 * - Current thread, process, and core 106 * - Function name / line number in file / cycle 97 * These functions displays a non-formated string on TXT0 terminal. 98 * They are actually used for low level debug, and call directly the TXT driver, 99 * without using the TXT server thread. 107 100 ********************************************************************************** 108 * @ condition : condition that must be true. 109 * @ format : formatted string 101 * @ string : non-formatted, NUL terminated string. 110 102 *********************************************************************************/ 111 #define assert( expr, format, ... ) \ 112 { \ 113 uint32_t __line_at_expansion = __LINE__; \ 114 const volatile cycle_t __assert_cycle = hal_get_cycles(); \ 115 if ( ( expr ) == false ) \ 116 { \ 117 panic( __FUNCTION__, \ 118 __line_at_expansion, \ 119 __assert_cycle, \ 120 ( format ), ##__VA_ARGS__ ); \ 121 } \ 122 } 103 void puts( const char * string ); 104 void nolock_puts( const char * string ); 123 105 124 106 /********************************************************************************** 125 * This debug function displays a non-formated message on TXT0 terminal. 126 * This function is actually used to debug the assembly level kernel functions. 127 ********************************************************************************** 128 * @ string : non-formatted string. 129 *********************************************************************************/ 130 void puts( char * string ); 131 132 /********************************************************************************** 133 * This debug function displays a 32 bits value in hexadecimal on TXT0 terminal. 134 * This function is actually used to debug the assembly level kernel functions. 107 * These functions display a 32 bits value in hexadecimal on TXT0 terminal. 108 * They are actually used for low level debug, and call directly the TXT driver, 109 * without using the TXT server thread. 135 110 ********************************************************************************** 136 111 * @ val : 32 bits unsigned value. 137 112 *********************************************************************************/ 138 113 void putx( uint32_t val ); 114 void nolock_putx( uint32_t val ); 139 115 140 116 /********************************************************************************** 141 * This debug function displays a 32 bits signed value in decimal on TXT0 terminal. 142 * This function is actually used to debug the assembly level kernel functions. 117 * These functions display a 32 bits signed value in decimal on TXT0 terminal. 118 * They are actually used for low level debug, and call directly the TXT driver, 119 * without using the TXT server thread. 143 120 ********************************************************************************** 144 121 * @ val : 32 bits signed value. 145 122 *********************************************************************************/ 146 123 void putd( int32_t val ); 124 void nolock_putd( int32_t val ); 147 125 148 126 /********************************************************************************** 149 * This debug function displays a 64 bits value in hexadecimal on TXT0 terminal. 150 * This function is actually used to debug the assembly level kernel functions. 127 * These functions display a 64 bits value in hexadecimal on TXT0 terminal. 128 * They are actually used low level debug, and call directly the TXT driver, 129 * without using the TXT server thread. 151 130 ********************************************************************************** 152 131 * @ val : 64 bits unsigned value. 153 132 *********************************************************************************/ 154 133 void putl( uint64_t val ); 134 void nolock_putl( uint64_t val ); 155 135 156 136 /********************************************************************************** -
trunk/kernel/kern/process.c
r662 r669 41 41 #include <thread.h> 42 42 #include <chdev.h> 43 #include <ksocket.h> 43 44 #include <list.h> 44 45 #include <string.h> … … 72 73 process_t * process_alloc( void ) 73 74 { 75 76 assert( __FUNCTION__, (sizeof(process_t) < CONFIG_PPM_PAGE_SIZE), 77 "process descriptor exceeds 1 page" ); 78 74 79 kmem_req_t req; 75 80 76 req.type = KMEM_KCM; 77 req.order = bits_log2( sizeof(process_t) ); 78 req.flags = AF_KERNEL; 79 81 req.type = KMEM_PPM; 82 req.order = 0; 83 req.flags = AF_KERNEL | AF_ZERO; 80 84 return kmem_alloc( &req ); 81 85 } … … 86 90 kmem_req_t req; 87 91 88 req.type = KMEM_ KCM;92 req.type = KMEM_PPM; 89 93 req.ptr = process; 90 94 kmem_free( &req ); … … 109 113 char rx_path[40]; 110 114 char tx_path[40]; 111 xptr_t file_xp;112 xptr_t chdev_xp;113 chdev_t * chdev_ptr;114 cxy_t chdev_cxy;115 115 pid_t parent_pid; 116 116 vmm_t * vmm; … … 211 211 212 212 // attach process to TXT 213 process_txt_attach( process , txt_id );213 process_txt_attach( process_xp , txt_id ); 214 214 215 215 #if (DEBUG_PROCESS_REFERENCE_INIT & 1) … … 220 220 #endif 221 221 // build path to TXT_RX[i] and TXT_TX[i] chdevs 222 snprint f( rx_path , 40 , "/dev/external/txt%d_rx", txt_id );223 snprint f( tx_path , 40 , "/dev/external/txt%d_tx", txt_id );222 snprintk( rx_path , 40 , "/dev/external/txt%d_rx", txt_id ); 223 snprintk( tx_path , 40 , "/dev/external/txt%d_tx", txt_id ); 224 224 225 225 // create stdin pseudo file … … 237 237 } 238 238 239 assert( (stdin_id == 0) , "stdin index must be 0" );239 assert( __FUNCTION__, (stdin_id == 0) , "stdin index must be 0" ); 240 240 241 241 #if (DEBUG_PROCESS_REFERENCE_INIT & 1) … … 260 260 } 261 261 262 assert( (stdout_id == 1) , "stdout index must be 1" );262 assert( __FUNCTION__, (stdout_id == 1) , "stdout index must be 1" ); 263 263 264 264 #if (DEBUG_PROCESS_REFERENCE_INIT & 1) … … 283 283 } 284 284 285 assert( (stderr_id == 2) , "stderr index must be 2" );285 assert( __FUNCTION__, (stderr_id == 2) , "stderr index must be 2" ); 286 286 287 287 #if (DEBUG_PROCESS_REFERENCE_INIT & 1) … … 295 295 else // normal user process 296 296 { 297 // get extended pointer on stdin pseudo file in parent process 298 file_xp = (xptr_t)hal_remote_l64( XPTR( parent_cxy, 299 &parent_ptr->fd_array.array[0] ) ); 300 301 // get extended pointer on parent process TXT chdev 302 chdev_xp = chdev_from_file( file_xp ); 303 304 // get cluster and local pointer on chdev 305 chdev_cxy = GET_CXY( chdev_xp ); 306 chdev_ptr = GET_PTR( chdev_xp ); 307 308 // get parent process TXT terminal index 309 txt_id = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) ); 310 311 // attach child process to parent process TXT terminal 312 process_txt_attach( process , txt_id ); 313 314 // copy all open files from parent process fd_array to this process 315 process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ), 316 XPTR( parent_cxy , &parent_ptr->fd_array ) ); 297 // get parent process TXT index 298 txt_id = process_txt_get_index( parent_xp ); 299 300 // attach child process to same TXT terminal as parent 301 process_txt_attach( process_xp , txt_id ); 302 303 // recreate all open files from parent process fd_array to child process fd_array 304 process_fd_replicate( process_xp , parent_xp ); 317 305 } 318 306 319 307 // initialize lock protecting CWD changes 320 remote_busylock_init( XPTR( local_cxy , 321 &process->cwd_lock ), LOCK_PROCESS_CWD ); 308 remote_busylock_init( XPTR( local_cxy , &process->cwd_lock ), LOCK_PROCESS_CWD ); 322 309 323 310 #if (DEBUG_PROCESS_REFERENCE_INIT & 1) … … 415 402 416 403 // check user process 417 assert( (local_process->pid != 0), "LPID cannot be 0" );404 assert( __FUNCTION__, (local_process->pid != 0), "LPID cannot be 0" ); 418 405 419 406 // initialize VSL as empty … … 520 507 521 508 // check no more threads 522 assert( (process->th_nr == 0),509 assert( __FUNCTION__, (process->th_nr == 0), 523 510 "process %x in cluster %x contains threads", pid , local_cxy ); 524 511 … … 616 603 cycle = (uint32_t)hal_get_cycles(); 617 604 if( DEBUG_PROCESS_DESTROY < cycle ) 618 printk("\n[%s] thread[%x,%x] exit /process %x in cluster %x / cycle %d\n",605 printk("\n[%s] thread[%x,%x] exit for process %x in cluster %x / cycle %d\n", 619 606 __FUNCTION__, this->process->pid, this->trdid, pid, local_cxy, cycle ); 620 607 #endif … … 683 670 684 671 // check action type 685 assert( ((type == DELETE_ALL_THREADS ) ||672 assert( __FUNCTION__, ((type == DELETE_ALL_THREADS ) || 686 673 (type == BLOCK_ALL_THREADS ) || 687 674 (type == UNBLOCK_ALL_THREADS )), "illegal action type" ); … … 809 796 810 797 // check target process is an user process 811 assert( (LPID_FROM_PID( process->pid ) != 0 ),798 assert( __FUNCTION__, (LPID_FROM_PID( process->pid ) != 0 ), 812 799 "process %x is not an user process\n", process->pid ); 813 800 … … 894 881 895 882 // check target process is an user process 896 assert( (LPID_FROM_PID( process->pid ) != 0),883 assert( __FUNCTION__, (LPID_FROM_PID( process->pid ) != 0), 897 884 "process %x is not an user process\n", process->pid ); 898 885 … … 916 903 { 917 904 // mark target thread for delete and block it 918 thread_delete ( target_xp , true ); // forced905 thread_delete_request( target_xp , true ); // forced 919 906 } 920 907 } … … 950 937 951 938 // check target process is an user process 952 assert( ( LPID_FROM_PID( process->pid ) != 0 ),939 assert( __FUNCTION__, ( LPID_FROM_PID( process->pid ) != 0 ), 953 940 "process %x is not an user process\n", process->pid ); 954 941 … … 1027 1014 xptr_t ref_xp = cluster_get_reference_process_from_pid( pid ); 1028 1015 1029 assert( (ref_xp != XPTR_NULL) , "illegal pid\n" );1016 assert( __FUNCTION__, (ref_xp != XPTR_NULL) , "illegal pid\n" ); 1030 1017 1031 1018 // allocate memory for local process descriptor … … 1081 1068 switch( type ) 1082 1069 { 1083 case INODE_TYPE_FILE: return "FILE";1084 case INODE_TYPE_DIR : return "DIR";1085 case INODE_TYPE_FIFO : return "FIFO";1086 case INODE_TYPE_PIPE : return "PIPE";1087 case INODE_TYPE_SOCK : return "SOCK";1088 case INODE_TYPE_DEV : return "DEV";1089 case INODE_TYPE_BLK : return "BLK";1090 case INODE_TYPE_SYML : return "SYML";1070 case FILE_TYPE_REG : return "FILE"; 1071 case FILE_TYPE_DIR : return "DIR"; 1072 case FILE_TYPE_FIFO : return "FIFO"; 1073 case FILE_TYPE_PIPE : return "PIPE"; 1074 case FILE_TYPE_SOCK : return "SOCK"; 1075 case FILE_TYPE_DEV : return "DEV"; 1076 case FILE_TYPE_BLK : return "BLK"; 1077 case FILE_TYPE_SYML : return "SYML"; 1091 1078 1092 1079 default : return "undefined"; … … 1129 1116 1130 1117 // check target process is owner process 1131 assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ),1118 assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ), 1132 1119 "process must be owner process\n" ); 1133 1120 … … 1145 1132 max_xp = XPTR( process_cxy , &process_ptr->fd_array.max ); 1146 1133 1147 // take lock protecting referencefd_array1134 // take lock protecting fd_array 1148 1135 remote_queuelock_acquire( lock_xp ); 1149 1136 … … 1158 1145 entry_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[id] ) ); 1159 1146 1147 // take the first empty slot 1160 1148 if ( entry_xp == XPTR_NULL ) 1161 1149 { … … 1165 1153 // update max when required 1166 1154 if( id > max ) hal_remote_s32( max_xp , id ); 1167 1168 // increase file refcount1169 vfs_file_count_up( file_xp );1170 1155 1171 1156 // exit loop … … 1208 1193 1209 1194 // check target process is owner process 1210 assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ),1195 assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ) ) ), 1211 1196 "process must be owner process\n" ); 1212 1197 … … 1253 1238 // release the fd_array entry in process copy 1254 1239 hal_remote_s64( XPTR( copy_cxy , ©_ptr->fd_array.array[fdid] ), XPTR_NULL ); 1255 1256 // decrease file refcount1257 vfs_file_count_down( file_xp );1258 1240 } 1259 1241 … … 1261 1243 if( fdid == max ) hal_remote_s32( fd_max_xp , max-1 ); 1262 1244 1263 // release the lock protecting referencefd_array1245 // release the lock protecting fd_array 1264 1246 remote_queuelock_release( fd_lock_xp ); 1265 1247 … … 1279 1261 void process_fd_clean_all( xptr_t process_xp ) 1280 1262 { 1281 uint32_t id;1263 uint32_t fdid; 1282 1264 xptr_t file_xp; // one fd_array entry 1283 1265 xptr_t lock_xp; // extendad pointer on lock protecting fd_array 1284 1266 uint32_t max; // number of registered files 1285 error_t error;1286 1267 1287 1268 // get process cluster, local pointer and PID 1288 1269 process_t * process_ptr = GET_PTR( process_xp ); 1289 1270 cxy_t process_cxy = GET_CXY( process_xp ); 1290 pid_t pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid) );1291 1271 1292 1272 // check target process is owner process 1293 assert( (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) ),1273 assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) ), 1294 1274 "process must be owner process\n" ); 1295 1275 … … 1298 1278 uint32_t cycle = (uint32_t)hal_get_cycles(); 1299 1279 if( DEBUG_PROCESS_FD_CLEAN_ALL < cycle ) 1300 printk("\n[%s] thread[%x,%x] enter for process %x/ cycle %d\n",1301 __FUNCTION__, this->process->pid, this->trdid, pid,cycle );1280 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 1281 __FUNCTION__, this->process->pid, this->trdid, cycle ); 1302 1282 1303 1283 process_fd_display( process_xp ); … … 1313 1293 remote_queuelock_acquire( lock_xp ); 1314 1294 1315 for ( id = 0; id <= max ;id++ )1295 for( fdid = 0 ; fdid <= max ; fdid++ ) 1316 1296 { 1317 1297 // get fd_array entry 1318 file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[ id] ) );1298 file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[fdid] ) ); 1319 1299 1320 1300 if ( file_xp != XPTR_NULL ) 1321 1301 { 1322 // close the file or socket 1323 error = sys_close( id ); 1324 1325 if( error ) 1326 printk("/n[ERROR] in %s : cannot close the file %d for process %x\n", 1327 __FUNCTION__, id, pid ); 1302 vfs_file_t * file_ptr = GET_PTR( file_xp ); 1303 cxy_t file_cxy = GET_CXY( file_xp ); 1304 1305 // get file type 1306 uint32_t file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type )); 1307 1308 if( file_type == FILE_TYPE_REG ) 1309 { 1310 vfs_close( file_xp , fdid ); 1311 } 1312 if( file_type == FILE_TYPE_SOCK ) 1313 { 1314 socket_close( file_xp , fdid ); 1315 } 1328 1316 } 1329 1317 } … … 1348 1336 process_t * process_ptr = GET_PTR( process_xp ); 1349 1337 1350 assert( (hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) == process_xp),1338 assert( __FUNCTION__, (hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp )) == process_xp), 1351 1339 "process_xp argument must be the owner process" ); 1352 1340 … … 1379 1367 remote_queuelock_acquire( lock_xp ); 1380 1368 1381 // access referenceprocess descriptor1369 // access owner process descriptor 1382 1370 file_xp = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->fd_array.array[fdid] ) ); 1383 1371 … … 1386 1374 // update local fd_array 1387 1375 process->fd_array.array[fdid] = file_xp; 1388 1389 // increase file refcount1390 vfs_file_count_up( file_xp );1391 1376 } 1392 1377 … … 1399 1384 } // end process_fd_get_xptr_from_local() 1400 1385 1401 /////////////////////////////////////////// 1402 void process_fd_remote_copy( xptr_t dst_xp, 1403 xptr_t src_xp ) 1404 { 1405 uint32_t fd; 1406 xptr_t entry; 1407 1408 // get cluster and local pointer for src fd_array 1409 cxy_t src_cxy = GET_CXY( src_xp ); 1410 fd_array_t * src_ptr = GET_PTR( src_xp ); 1411 1412 // get cluster and local pointer for dst fd_array 1413 cxy_t dst_cxy = GET_CXY( dst_xp ); 1414 fd_array_t * dst_ptr = GET_PTR( dst_xp ); 1386 ///////////////////////////////////////// 1387 void process_fd_replicate( xptr_t dst_xp, 1388 xptr_t src_xp ) 1389 { 1390 uint32_t fdid; // current file descriptor index 1391 xptr_t old_xp; // extended pointer on a file descriptor (stored in SRC fd_array) 1392 xptr_t new_xp; // extended pointer on a file descriptor (stored in DST fd_array) 1393 error_t error; 1394 1395 // get cluster and local pointer for SRC process 1396 cxy_t src_cxy = GET_CXY( src_xp ); 1397 process_t * src_ptr = GET_PTR( src_xp ); 1398 1399 assert( __FUNCTION__, (src_xp == hal_remote_l64( XPTR( src_cxy , &src_ptr->owner_xp ))), 1400 "src_xp process not in owner cluster" ); 1401 1402 // get cluster and local pointer for DST fd_array 1403 cxy_t dst_cxy = GET_CXY( dst_xp ); 1404 process_t * dst_ptr = GET_PTR( dst_xp ); 1405 1406 assert( __FUNCTION__, (dst_xp == hal_remote_l64( XPTR( dst_cxy , &dst_ptr->owner_xp ))), 1407 "dst_xp process not in owner cluster" ); 1408 1409 // build extende pointers on SRC fd_array lock and max fields 1410 xptr_t src_lock_xp = XPTR( src_cxy , &src_ptr->fd_array.lock ); 1411 xptr_t src_max_xp = XPTR( src_cxy , &src_ptr->fd_array.max ); 1415 1412 1416 1413 // get the remote lock protecting the src fd_array 1417 remote_queuelock_acquire( XPTR( src_cxy , &src_ptr->lock ));1418 1419 // loop on allfd_array entries1420 for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )1414 remote_queuelock_acquire( src_lock_xp ); 1415 1416 // loop on fd_array entries 1417 for( fdid = 0 ; fdid <= hal_remote_l32( src_max_xp ) ; fdid++ ) 1421 1418 { 1422 entry = (xptr_t)hal_remote_l64( XPTR( src_cxy , &src_ptr->array[fd] ) );1423 1424 if( entry!= XPTR_NULL )1419 old_xp = (xptr_t)hal_remote_l64( XPTR( src_cxy , &src_ptr->fd_array.array[fdid] ) ); 1420 1421 if( old_xp != XPTR_NULL ) 1425 1422 { 1426 // increment file descriptor refcount 1427 vfs_file_count_up( entry ); 1428 1429 // copy entry in destination process fd_array 1430 hal_remote_s64( XPTR( dst_cxy , &dst_ptr->array[fd] ) , entry ); 1423 // get the existing file descriptor cluster and local pointer 1424 vfs_file_t * old_ptr = GET_PTR( old_xp ); 1425 cxy_t old_cxy = GET_CXY( old_xp ); 1426 1427 // get existing file attributes and local pointer on inode 1428 uint32_t attr = hal_remote_l32( XPTR( old_cxy , &old_ptr->attr ) ); 1429 vfs_inode_t * inode_ptr = hal_remote_lpt( XPTR( old_cxy , &old_ptr->inode ) ); 1430 1431 // create a new file descriptor in same cluster as the existing one 1432 error = vfs_file_create( XPTR( old_cxy , inode_ptr ), 1433 attr, 1434 &new_xp ); 1435 if( error ) 1436 { 1437 printk("\n[ERROR] in %s : cannot create new file\n", __FUNCTION__ ); 1438 return; 1439 } 1440 1441 // register new_xp in DST fd_array 1442 hal_remote_s64( XPTR( dst_cxy , &dst_ptr->fd_array.array[fdid] ) , new_xp ); 1431 1443 } 1432 1444 } 1433 1445 1434 1446 // release lock on source process fd_array 1435 remote_queuelock_release( XPTR( src_cxy , &src_ptr->lock ));1436 1437 } // end process_fd_re mote_copy()1447 remote_queuelock_release( src_lock_xp ); 1448 1449 } // end process_fd_replicate() 1438 1450 1439 1451 … … 1497 1509 file_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type )); 1498 1510 1499 // get file name for a true file1500 if( file_type == INODE_TYPE_FILE)1511 // get file name if inode exist 1512 if( (file_type != FILE_TYPE_PIPE) && (file_type != FILE_TYPE_SOCK) ) 1501 1513 { 1502 1514 // get inode pointers … … 1507 1519 vfs_inode_get_name( inode_xp , name ); 1508 1520 1509 // display relevant file de criptor info1510 printk(" - %d : type %s (%s)\n",1511 fdid , process_fd_type_str(file_type), name );1521 // display relevant file descriptor info 1522 printk(" - %d : type %s / ptr %x (%s)\n", 1523 fdid, process_fd_type_str(file_type), file_ptr, name ); 1512 1524 } 1513 else 1525 else // PIPE or SOCK types 1514 1526 { 1515 1527 // display relevant file decriptor info 1516 printk(" - %d : type %s \n",1517 fdid , process_fd_type_str(file_type) );1528 printk(" - %d : type %s / ptr %x\n", 1529 fdid , process_fd_type_str(file_type), file_ptr ); 1518 1530 } 1519 1531 } 1520 1532 else 1521 1533 { 1522 // display relevant file decriptor info1523 1534 printk(" - %d : empty slot\n", 1524 1535 fdid ); … … 1540 1551 1541 1552 // check arguments 1542 assert( (process != NULL) , "process argument is NULL" );1543 assert( (thread != NULL) , "thread argument is NULL" );1553 assert( __FUNCTION__, (process != NULL) , "process argument is NULL" ); 1554 assert( __FUNCTION__, (thread != NULL) , "thread argument is NULL" ); 1544 1555 1545 1556 // get the lock protecting th_tbl for all threads … … 1580 1591 1581 1592 // check thread 1582 assert( (thread != NULL) , "thread argument is NULL" );1593 assert( __FUNCTION__, (thread != NULL) , "thread argument is NULL" ); 1583 1594 1584 1595 process_t * process = thread->process; … … 1594 1605 1595 1606 // check th_nr value 1596 assert( (count > 0) , "process th_nr cannot be 0" );1607 assert( __FUNCTION__, (count > 0) , "process th_nr cannot be 0" ); 1597 1608 1598 1609 // remove thread from th_tbl[] … … 1633 1644 1634 1645 // check parent process is the reference process 1635 assert( (parent_process_xp == ref_xp ) ,1646 assert( __FUNCTION__, (parent_process_xp == ref_xp ) , 1636 1647 "parent process must be the reference process" ); 1637 1648 … … 1711 1722 cycle = (uint32_t)hal_get_cycles(); 1712 1723 if( DEBUG_PROCESS_MAKE_FORK < cycle ) 1713 printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n", 1714 __FUNCTION__, pid, trdid, cycle ); 1715 hal_vmm_display( XPTR( local_cxy , process ) , true ); 1724 { 1725 printk("\n[%s] thread[%x,%x] copied VMM from parent to child / cycle %d\n", 1726 __FUNCTION__, pid, trdid, cycle ); 1727 hal_vmm_display( XPTR( local_cxy , process ) , true ); 1728 } 1716 1729 #endif 1717 1730 … … 1748 1761 1749 1762 // check main thread LTID 1750 assert( (LTID_FROM_TRDID(thread->trdid) == 0) ,1763 assert( __FUNCTION__, (LTID_FROM_TRDID(thread->trdid) == 0) , 1751 1764 "main thread must have LTID == 0" ); 1752 1765 … … 1806 1819 } // end process_make_fork() 1807 1820 1808 ///////////////////////////////////////////////////// 1809 error_t process_make_exec( exec_info_t * exec_info ) 1810 { 1811 thread_t * thread; // local pointer on this thread 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() 1981 1982 ///////////////////////////////// 1983 error_t process_make_exec( void ) 1984 { 1985 thread_t * this; // local pointer on this thread 1812 1986 process_t * process; // local pointer on this process 1813 1987 pid_t pid; // this process identifier 1988 trdid_t trdid; // this thread identifier 1814 1989 xptr_t ref_xp; // reference process for this process 1815 1990 error_t error; // value returned by called functions 1816 char * path;// path to .elf file1991 char * elf_path; // path to .elf file 1817 1992 xptr_t file_xp; // extended pointer on .elf file descriptor 1818 1993 uint32_t file_id; // file index in fd_array 1819 uint32_t args_nr; // number of main thread arguments 1820 char ** args_pointers; // array of pointers on main thread arguments 1821 1822 // get calling thread, process, pid and ref_xp 1823 thread = CURRENT_THREAD; 1824 process = thread->process; 1994 vseg_t * vseg; // local pointer on created vseg(s) 1995 uint32_t n; // index for loops 1996 1997 uint32_t args_nr; // actual number of args (from exec_info) 1998 intptr_t args_base; // args vseg base address in user space 1999 uint32_t args_size; // args vseg size (bytes) 2000 2001 uint32_t envs_nr; // actual number of envs (from exec_info) 2002 intptr_t envs_base; // envs vseg base address in user space 2003 uint32_t envs_size; // envs vseg size (bytes) 2004 2005 // get calling thread, process, pid, trdid, and ref_xp 2006 this = CURRENT_THREAD; 2007 process = this->process; 1825 2008 pid = process->pid; 2009 trdid = this->trdid; 1826 2010 ref_xp = process->ref_xp; 1827 2011 1828 // get relevant infos from exec_info 1829 path = exec_info->path; 1830 args_nr = exec_info->args_nr; 1831 args_pointers = exec_info->args_pointers; 2012 // get .elf pathname from exec_info structure 2013 elf_path = process->exec_info.path; 1832 2014 1833 2015 #if DEBUG_PROCESS_MAKE_EXEC 1834 2016 uint32_t cycle = (uint32_t)hal_get_cycles(); 1835 2017 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 1836 printk("\n[%s] thread[%x,%x] enters for %s/ cycle %d\n",1837 __FUNCTION__, pid, t hread->trdid,path, cycle );1838 #endif 1839 1840 // open the file identified by <path>2018 printk("\n[%s] thread[%x,%x] enters for <%s> / cycle %d\n", 2019 __FUNCTION__, pid, trdid, elf_path, cycle ); 2020 #endif 2021 2022 // 1. open the file identified by <path> 1841 2023 file_xp = XPTR_NULL; 1842 2024 file_id = 0xFFFFFFFF; 1843 2025 error = vfs_open( process->vfs_root_xp, 1844 path,2026 elf_path, 1845 2027 ref_xp, 1846 2028 O_RDONLY, … … 1850 2032 if( error ) 1851 2033 { 1852 printk("\n[ERROR] in %s : failed to open file <%s>\n", __FUNCTION__ , path ); 2034 printk("\n[ERROR] in %s : thread[%x,%x] failed to open file <%s>\n", 2035 __FUNCTION__, pid, trdid, elf_path ); 1853 2036 return -1; 1854 2037 } 1855 2038 1856 2039 #if (DEBUG_PROCESS_MAKE_EXEC & 1) 1857 cycle = (uint32_t)hal_get_cycles();1858 2040 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 1859 printk("\n[%s] thread[%x,%x] opened file <%s> / cycle %d\n",1860 __FUNCTION__, pid, t hread->trdid, path, cycle);1861 #endif 1862 1863 // delete all threads other than this main thread in all clusters2041 printk("\n[%s] thread[%x,%x] opened file <%s>\n", 2042 __FUNCTION__, pid, trdid, elf_path ); 2043 #endif 2044 2045 // 2. delete all threads other than this main thread in all clusters 1864 2046 process_sigaction( pid , DELETE_ALL_THREADS ); 1865 2047 1866 2048 #if (DEBUG_PROCESS_MAKE_EXEC & 1) 1867 cycle = (uint32_t)hal_get_cycles();1868 2049 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 1869 printk("\n[%s] thread[%x,%x] deleted existing threads / cycle %d\n",1870 __FUNCTION__, pid, t hread->trdid, cycle);1871 #endif 1872 1873 // reset calling process VMM2050 printk("\n[%s] thread[%x,%x] deleted existing threads\n", 2051 __FUNCTION__, pid, trdid ); 2052 #endif 2053 2054 // 3. reset calling process VMM 1874 2055 vmm_user_reset( process ); 1875 2056 1876 2057 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 1877 cycle = (uint32_t)hal_get_cycles();1878 2058 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 1879 printk("\n[%s] thread[%x,%x] completed VMM reset / cycle %d\n", 1880 __FUNCTION__, pid, thread->trdid, cycle ); 1881 #endif 1882 1883 // re-initialize the VMM (args/envs vsegs registration) 1884 error = vmm_user_init( process ); 1885 if( error ) 1886 { 1887 printk("\n[ERROR] in %s : cannot initialise VMM for %s\n", __FUNCTION__ , path ); 1888 vfs_close( file_xp , file_id ); 1889 // FIXME restore old process VMM [AG] 1890 return -1; 1891 } 1892 2059 { 2060 printk("\n[%s] thread[%x,%x] completed VMM reset\n", 2061 __FUNCTION__, pid, trdid ); 2062 hal_vmm_display( ref_xp , true ); 2063 } 2064 #endif 2065 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 2068 args_nr = process->exec_info.args_nr; 2069 2070 if( args_nr > 0 ) 2071 { 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; 2075 2076 // create and register args vseg in VMM 2077 vseg = vmm_create_vseg( process, 2078 VSEG_TYPE_DATA, 2079 args_base, 2080 args_size, 2081 0, // file_offset unused for DATA type 2082 0, // file_size unused for DATA type 2083 XPTR_NULL, // mapper_xp unused for DATA type 2084 0 ); // cxy unused for DATA type 2085 if( vseg == NULL ) 2086 { 2087 printk("\n[ERROR] in %s : thread[%x,%x] cannot get args vseg for <%s>\n", 2088 __FUNCTION__, pid, trdid, elf_path ); 2089 return -1; 2090 } 2091 1893 2092 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 1894 cycle = (uint32_t)hal_get_cycles();1895 2093 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 1896 printk("\n[%s] thread[%x,%x] registered args/envs vsegs / cycle %d\n", 1897 __FUNCTION__, pid, thread->trdid, cycle ); 1898 #endif 1899 1900 // register code & data vsegs as well as entry-point in process VMM, 1901 // and register extended pointer on .elf file in process descriptor 2094 { 2095 printk("\n[%s] thread[%x,%x] args vseg registered in new process VSL\n", 2096 __FUNCTION__, pid, trdid ); 2097 hal_vmm_display( ref_xp , true ); 2098 } 2099 #endif 2100 // map all pages for this "args" vseg 2101 uint32_t fake_attr; // required for hal_gpt_lock_pte() 2102 ppn_t fake_ppn; // required for hal_gpt_lock_pte() 2103 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); 2108 2109 for( n = 0 ; n < CONFIG_VMM_ARGS_SIZE ; n++ ) 2110 { 2111 // lock the PTE 2112 if (hal_gpt_lock_pte( gpt , vpn , &fake_attr , &fake_ppn ) ) 2113 { 2114 printk("\n[ERROR] in %s : thread[%x,%x] cannot map args vpn %x for <%s>\n", 2115 __FUNCTION__, pid, trdid, vpn, elf_path ); 2116 return -1; 2117 } 2118 2119 // map and unlock the PTE 2120 hal_gpt_set_pte( gpt , vpn + n , attr , ppn + n ); 2121 } 2122 2123 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 2124 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 2125 { 2126 printk("\n[%s] thread[%x,%x] args vseg mapped in new process GPT\n", 2127 __FUNCTION__, pid, trdid ); 2128 hal_vmm_display( ref_xp , true ); 2129 } 2130 #endif 2131 2132 // set user space pointers in array of pointers 2133 char ** ptr = process->exec_info.args_pointers; 2134 2135 for( n = 0 ; n < args_nr ; n++ ) 2136 { 2137 ptr[n] = ptr[n] + args_base - (intptr_t)ptr; 2138 } 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 2143 envs_nr = process->exec_info.envs_nr; 2144 2145 if( envs_nr > 0 ) 2146 { 2147 // 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) 2152 } 2153 2154 2155 // 6. register code & data vsegs, and entry-point in process VMM, 2156 // register extended pointer on .elf file in process descriptor 1902 2157 error = elf_load_process( file_xp , process ); 1903 2158 if( error ) 1904 2159 { 1905 printk("\n[ERROR] in %s : failed to access <%s>\n", __FUNCTION__ , path ); 1906 vfs_close( file_xp , file_id ); 1907 // FIXME restore old process VMM [AG] 2160 printk("\n[ERROR] in %s : thread[%x,%x] failed to access <%s>\n", 2161 __FUNCTION__, pid, trdid, elf_path ); 1908 2162 return -1; 1909 2163 } 1910 2164 1911 2165 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 1912 cycle = (uint32_t)hal_get_cycles();1913 2166 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 1914 printk("\n[%s] thread[%x,%x] registered code/data vsegs / cycle %d\n", 1915 __FUNCTION__, pid, thread->trdid, cycle ); 1916 #endif 1917 1918 // update the existing main thread descriptor... and jump to user code 1919 error = thread_user_exec( (void *)process->vmm.entry_point, 1920 args_nr, 1921 args_pointers ); 2167 { 2168 printk("\n[%s] thread[%x,%x] registered code/data vsegs / entry %x\n", 2169 __FUNCTION__, pid, trdid, process->vmm.entry_point ); 2170 hal_vmm_display( ref_xp , true ); 2171 } 2172 #endif 2173 2174 // 7. allocate an user stack vseg for main thread 2175 vseg = vmm_create_vseg( process, 2176 VSEG_TYPE_STACK, 2177 LTID_FROM_TRDID( trdid ), 2178 0, // length unused 2179 0, // file_offset unused 2180 0, // file_size unused 2181 XPTR_NULL, // mapper_xp unused 2182 local_cxy ); 2183 if( vseg == NULL ) 2184 { 2185 printk("\n[ERROR] in %s : thread[%x,%x] cannot set u_stack vseg for <%s>\n", 2186 __FUNCTION__, pid, trdid, elf_path ); 2187 return -1; 2188 } 2189 2190 #if( DEBUG_PROCESS_MAKE_EXEC & 1 ) 2191 if( DEBUG_PROCESS_MAKE_EXEC < cycle ) 2192 { 2193 printk("\n[%s] thread[%x,%x] registered stack vseg\n", 2194 __FUNCTION__, pid, trdid ); 2195 hal_vmm_display( ref_xp , true ); 2196 } 2197 #endif 2198 2199 // update user stack in thread descriptor 2200 this->user_stack_vseg = vseg; 2201 2202 // 8. update the main thread descriptor ... and jumps (one way) to user code 2203 thread_user_exec( args_nr , args_base ); 2204 1922 2205 if( error ) 1923 2206 { 1924 printk("\n[ERROR] in %s : cannot update main thread for %s\n", __FUNCTION__ , path ); 1925 vfs_close( file_xp , file_id ); 1926 // FIXME restore old process VMM 2207 printk("\n[ERROR] in %s : thread[%x,%x] cannot update thread for <%s>\n", 2208 __FUNCTION__ , pid, trdid, elf_path ); 1927 2209 return -1; 1928 2210 } 1929 2211 1930 assert( false, "we should not execute this code");1931 1932 2212 return 0; 1933 2213 … … 2153 2433 #if(DEBUG_PROCESS_INIT_CREATE & 1) 2154 2434 if( DEBUG_PROCESS_INIT_CREATE < cycle ) 2155 printk("\n[%s] thread[%x,%x] registered code/data vsegs in VMM\n", 2156 __FUNCTION__, this->process->pid, this->trdid ); 2157 #endif 2158 2159 #if (DEBUG_PROCESS_INIT_CREATE & 1) 2160 hal_vmm_display( XPTR( local_cxy , process ) , true ); 2435 { 2436 printk("\n[%s] thread[%x,%x] registered code/data vsegs in VMM\n", 2437 __FUNCTION__, this->process->pid, this->trdid ); 2438 hal_vmm_display( XPTR( local_cxy , process ) , true ); 2439 } 2161 2440 #endif 2162 2441 … … 2291 2570 txt_file_xp = hal_remote_l64( XPTR( owner_cxy , &owner_ptr->fd_array.array[0] ) ); 2292 2571 2293 assert( (txt_file_xp != XPTR_NULL) ,2572 assert( __FUNCTION__, (txt_file_xp != XPTR_NULL) , 2294 2573 "process must be attached to one TXT terminal" ); 2295 2574 … … 2363 2642 } 2364 2643 2365 assert( false , "no free TXT terminal found" );2644 assert( __FUNCTION__, false , "no free TXT terminal found" ); 2366 2645 2367 2646 return -1; … … 2370 2649 2371 2650 ///////////////////////////////////////////// 2372 void process_txt_attach( process_t * process,2373 uint32_t 2651 void process_txt_attach( xptr_t process_xp, 2652 uint32_t txt_id ) 2374 2653 { 2375 2654 xptr_t chdev_xp; // extended pointer on TXT_RX chdev … … 2379 2658 xptr_t lock_xp; // extended pointer on list lock in chdev 2380 2659 2660 process_t * process_ptr = GET_PTR(process_xp ); 2661 cxy_t process_cxy = GET_CXY(process_xp ); 2662 2381 2663 // check process is in owner cluster 2382 assert( (CXY_FROM_PID( process->pid ) == local_cxy),2664 assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ))), 2383 2665 "process descriptor not in owner cluster" ); 2384 2666 2385 2667 // check terminal index 2386 assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,2668 assert( __FUNCTION__, (txt_id < LOCAL_CLUSTER->nb_txt_channels) , 2387 2669 "illegal TXT terminal index" ); 2388 2670 … … 2399 2681 remote_busylock_acquire( lock_xp ); 2400 2682 2401 // insert process in attached process list2402 xlist_add_last( root_xp , XPTR( local_cxy , &process->txt_list ) );2683 // insert owner process in list of attached processes to same TXT 2684 xlist_add_last( root_xp , XPTR( process_cxy , &process_ptr->txt_list ) ); 2403 2685 2404 2686 // release lock protecting list of processes attached to TXT … … 2410 2692 if( DEBUG_PROCESS_TXT < cycle ) 2411 2693 printk("\n[%s] thread[%x,%x] attached process %x to TXT %d / cycle %d\n", 2412 __FUNCTION__, this->process->pid, this->trdid, process->pid, txt_id , cycle ); 2694 __FUNCTION__, this->process->pid, this->trdid, 2695 hal_remote_l32( XPTR( process_cxy , &process_ptr->pid, txt_id , cycle ); 2413 2696 #endif 2414 2697 … … 2433 2716 2434 2717 // check process descriptor in owner cluster 2435 assert( (CXY_FROM_PID( process_pid ) == process_cxy ) ,2718 assert( __FUNCTION__, (CXY_FROM_PID( process_pid ) == process_cxy ) , 2436 2719 "process descriptor not in owner cluster" ); 2437 2720 … … 2471 2754 2472 2755 /////////////////////////////////////////////////// 2756 uint32_t process_txt_get_index( xptr_t process_xp ) 2757 { 2758 2759 // get target process cluster and local pointer 2760 process_t * process_ptr = GET_PTR( process_xp ); 2761 cxy_t process_cxy = GET_CXY( process_xp ); 2762 2763 assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp))), 2764 "process descriptor not in owner cluster" ); 2765 2766 // get extended pointer on STDIN pseudo file in owner process descriptor 2767 xptr_t file_xp = hal_remote_l64( XPTR( process_cxy , &process_ptr->fd_array.array[0])); 2768 2769 assert( __FUNCTION__, (file_xp != XPTR_NULL), 2770 "STDIN pseudo-file undefined in fd_array for process %x\n", 2771 hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) ) ); 2772 2773 // get extended pointer on TXT chdev 2774 xptr_t chdev_xp = chdev_from_file( file_xp ); 2775 2776 assert( __FUNCTION__, (chdev_xp != XPTR_NULL), 2777 "chdev undefined for STDIN pseudo-file of process %x\n", 2778 hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) ) ); 2779 2780 // get cluster and local pointer on chdev 2781 cxy_t chdev_cxy = GET_CXY( chdev_xp ); 2782 chdev_t * chdev_ptr = GET_PTR( chdev_xp ); 2783 2784 // get parent TXT terminal index 2785 return hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) ); 2786 2787 } // end process_txt_get_index() 2788 2789 /////////////////////////////////////////////////// 2473 2790 void process_txt_set_ownership( xptr_t process_xp ) 2474 2791 { 2475 2792 process_t * process_ptr; 2476 2793 cxy_t process_cxy; 2477 pid_t process_pid;2478 2794 xptr_t file_xp; 2479 2795 xptr_t txt_xp; … … 2484 2800 process_cxy = GET_CXY( process_xp ); 2485 2801 process_ptr = GET_PTR( process_xp ); 2486 process_pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) );2487 2802 2488 2803 // check owner cluster 2489 assert( (process_cxy == CXY_FROM_PID( process_pid )),2804 assert( __FUNCTION__, (process_xp == hal_remote_l64( XPTR( process_cxy , &process_ptr->owner_xp ))), 2490 2805 "process descriptor not in owner cluster" ); 2491 2806 … … 2506 2821 uint32_t txt_id = hal_remote_l32( XPTR( txt_cxy , &txt_ptr->channel ) ); 2507 2822 if( DEBUG_PROCESS_TXT < cycle ) 2508 printk("\n[%s] thread[%x,%x] give TXT%d ownership to process %x/ cycle %d\n",2509 __FUNCTION__, this->process->pid, this->trdid, txt_id, process_pid,cycle );2823 printk("\n[%s] thread[%x,%x] give TXT%d ownership to process / cycle %d\n", 2824 __FUNCTION__, this->process->pid, this->trdid, txt_id, cycle ); 2510 2825 #endif 2511 2826 … … 2541 2856 2542 2857 // check owner cluster 2543 assert( (process_cxy == CXY_FROM_PID( process_pid )) ,2858 assert( __FUNCTION__, (process_cxy == CXY_FROM_PID( process_pid )) , 2544 2859 "process descriptor not in owner cluster" ); 2545 2860 … … 2595 2910 2596 2911 // It must exist a KSH process for each user TXT channel 2597 assert( (found == true), "KSH process not found for TXT%d", txt_id );2912 assert( __FUNCTION__, (found == true), "KSH process not found for TXT%d", txt_id ); 2598 2913 2599 2914 } … … 2671 2986 // check calling thread execute in target process owner cluster 2672 2987 pid_t process_pid = hal_remote_l32( XPTR( process_cxy , &process_ptr->pid ) ); 2673 assert( (process_cxy == CXY_FROM_PID( process_pid )) ,2988 assert( __FUNCTION__, (process_cxy == CXY_FROM_PID( process_pid )) , 2674 2989 "process descriptor not in owner cluster" ); 2675 2990 … … 2715 3030 xptr_t txt0_lock_xp; 2716 3031 2717 assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,3032 assert( __FUNCTION__, (txt_id < LOCAL_CLUSTER->nb_txt_channels) , 2718 3033 "illegal TXT terminal index" ); 2719 3034 -
trunk/kernel/kern/process.h
r662 r669 71 71 * This structure defines an array of extended pointers on the open file descriptors 72 72 * for a given process. The file descriptors are always stored in the same cluster 73 * as the inode associated to the file. A free entry in this array contains XPTR_NULL. 73 * as the object associated to the file descriptor (inode, socket, pipe, etc). 74 * A free entry in this array contains XPTR_NULL. 74 75 * The array size is defined by the CONFIG_PROCESS_FILE_MAX_NR parameter. 75 76 * 76 * NOTE: - Only the fd_array[] in the reference process contains the complete list of open 77 * files, and is protected by the lock against concurrent access. 78 * - the fd_array[] in a process copy is not used. 79 * open files to speed the fdid to xptr translation, but the "lock" and "max" 80 * fields are not significant for these copies. 77 * NOTE: - Only the fd_array[] in the owner cluster process contains the complete list 78 * of open files, and is protected by the lock against concurrent access. 79 * - the fd_array[] in a process copy is only used to speed the fdid -> xptr 80 * translation, but the "lock" and "max" fields are not significant in these copies. 81 81 * - The modifications made by the process_fd_register() function are only done 82 82 * in the owner cluster. 83 83 * - The modifications made by the process_fd_remove() function are done in the 84 84 * owner cluster, and in all process_copies. 85 * - In case of miss on thelocal fd_array, the process_fd_get_xptr() access the85 * - In case of miss on a local fd_array, the process_fd_get_xptr() access the 86 86 * owner cluster fd_array, and update the fd_array local copy. 87 87 ********************************************************************************************/ … … 94 94 } 95 95 fd_array_t; 96 97 /********************************************************************************************* 98 * This structure defines the information required by the process_make_exec() function 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. 102 * 103 * It contains three parts: 104 * - the "path" field is a string defining the pathname of the .elf file. 105 * - the "args_pointers" & "args_nr" fields define the arguments (one arg == one string). 106 * - the "envs_pointers" & "envs_nr" fields define the env variables (one env == one string). 107 * 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 : 112 * - in the first bytes, a fixed size kernel array of pointers on the strings. 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. 122 ********************************************************************************************/ 123 124 typedef struct exec_info_s 125 { 126 char path[CONFIG_VFS_MAX_PATH_LENGTH]; /*! .elf file path in kernel space */ 127 128 char ** args_pointers; /*! pointer on array of pointers on strings */ 129 uint32_t args_nr; /*! actual number of arguments */ 130 131 char ** envs_pointers; /*! pointer on array of pointers on strings */ 132 uint32_t envs_nr; /*! actual number of environment variables */ 133 char * envs_buf_free; /*! local pointer on first free slot in strings buffer */ 134 } 135 exec_info_t; 96 136 97 137 /********************************************************************************************* … … 112 152 * are actually use as read-only caches. 113 153 * 3) the <fd_array>, containing extended pointers on the open file descriptors, is only 114 * complete in the referenceprocess cluster, other copies are read-only caches.154 * complete in the owner process cluster, other copies are read-only caches. 115 155 * 4) The <sem_root>, <mutex_root>, <barrier_root>, <condvar_root>, and the associated 116 156 * <sync_lock>, dynamically allocated, are only defined in the reference cluster. … … 129 169 fd_array_t fd_array; /*! embedded open file descriptors array */ 130 170 171 exec_info_t exec_info; /*! embedded structure for args & envs */ 172 131 173 xptr_t vfs_root_xp; /*! extended pointer on VFS root inode */ 132 174 xptr_t vfs_bin_xp; /*! extended pointer on .elf file descriptor */ … … 165 207 } 166 208 process_t; 167 168 /*********************************************************************************************169 * This structure defines the information required by the process_make_exec() function170 * to create a new reference process descriptor, and the associated main thread.171 ********************************************************************************************/172 173 typedef struct exec_info_s174 {175 char path[CONFIG_VFS_MAX_PATH_LENGTH]; /*! .elf file path */176 177 char ** args_pointers; /*! physical base address of array of pointers */178 char * args_buf_base; /*! physical base address of kernel args buffer */179 uint32_t args_nr; /*! actual number of arguments */180 181 char ** envs_pointers; /*! physical base address of array of pointers */182 char * envs_buf_base; /*! physical base address of kernel args buffer */183 char * envs_buf_free; /*! physical address of first free slot in envs_buf */184 uint32_t envs_nr; /*! actual number of environment variables */185 }186 exec_info_t;187 209 188 210 /*************** Process Descriptor Operations *****************************************/ … … 393 415 394 416 /********************************************************************************************* 395 * This function implements the "exec" system call, and is called by the sys_exec() function. 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 in 422 * the calling user process space. The max number of envs, and the max number of args are 423 * 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 one 427 * 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_info 433 * 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 * This function implements the "execve" system call, and is called by sys_exec() function. 446 * It must be called by the main thread of the calling "old" process. 447 * The <exec_info> structure in process descriptor contains all informations required 448 * to update both the calling process descriptor and the calling thread descriptor. 396 449 * The "new" process keep the "old" process PID and PPID, all open files, and env variables, 397 * the vfs_root and vfs_cwd, but build a brand new memory image (new VMM from the new .elf).450 * the vfs_root and vfs_cwd, but build a brand new memory image (new VMM from the .elf file). 398 451 * It is executed in the local cluster, that becomes both the "owner" and the "reference" 399 452 * cluster for the "new" process. 400 453 ********************************************************************************************* 401 * @ exec_info : [in] pointer on the exec_info structure. 454 * Implementation note: 455 * It executes the following sequence: 456 * 1) it creates a file descriptor for the .elf file (pathname in exec_info). 457 * 2) it deletes all other threads than the main thread, in all clusters. 458 * 3) it reset the existing VMM (remove all user vsegs). 459 * 4) it build the "args" user vseg from process exec_info, and registers in the VMM. 460 * 5) TODO it build the "envs" user vseg from process exec_info, and registers in the VMM. 461 * 6) it get the "code" and "data" user vsegs from the .elf file, and registers in the VMM. 462 * 7) it allocates an user "stack" vseg, and registers in the VMM 463 * 8) it calls thread_user_exec() to complete thread initialisation and jumps to user code. 464 ********************************************************************************************* 402 465 * @ return 0 if success / return non-zero if error. 403 466 ********************************************************************************************/ 404 error_t process_make_exec( exec_info_t * exec_info);467 error_t process_make_exec( void ); 405 468 406 469 /********************************************************************************************* … … 452 515 * and return the slot index in the <fdid> buffer. 453 516 * It can be called by any thread in any cluster. 454 * It takes the lock protecting the fd_array against concurrent accesses.455 * Note: we must use the owner process descriptor, because this fd_array must456 * containall files open by a given process.457 ********************************************************************************************* 458 * @ process_xp : [in] extended pointer on client referenceprocess.517 * It takes the lock protecting the fd_array against concurrent slot allocations. 518 * Note: we must use the owner process descriptor, because only this fd_array contains 519 * all files open by a given process. 520 ********************************************************************************************* 521 * @ process_xp : [in] extended pointer on owner process. 459 522 * @ file_xp : [in] extended pointer on the file descriptor to be registered. 460 523 * @ fdid : [out] buffer for allocated fd_array slot index. … … 470 533 * process descriptor, identified by the <process_xp> argument. 471 534 * It can be called by any thread in any cluster. 472 * It takes the lock protecting the fd_array against concurrent accesses.535 * It takes the lock protecting the list of copies. 473 536 * Note: we must use the owner process descriptor, because only this owner cluster contains 474 537 * the complete list of process copies. … … 523 586 524 587 /********************************************************************************************* 525 * This function copies all non-zero entries (other than the three first stdin/stdout/stderr)526 * from a remote <src_xp> fd_array, embedded in a process descriptor, to another remote527 * <dst_xp> fd_array, embedded in another process descriptor.528 * The calling thread can be running in any cluster.529 * It takes the lock protecting the reference fd_array against concurrent accesses.530 * For each involved file descriptor, the refcount is incremented.531 ********************************************************************************************* 532 * @ dst_xp : extended pointer on the destination fd_array_t.533 * @ src_xp : extended pointer on the source fd_array_t.534 ********************************************************************************************/ 535 void process_fd_re mote_copy( xptr_t dst_xp,536 588 * This function scans all entries in a fd_array, identified by the <src_xp> argument, that 589 * must be the process descriptor in owner cluster. For each non-zero entry, it allocates a 590 * new file descriptor in the cluster containing the involved inode, and registers it in the 591 * fd_array identified by the <dst_xp> argument, that must also be the process descriptor in 592 * owner cluster. The calling thread itself can be running in any cluster. 593 * It takes the lock protecting the <src_xp> fd_array against concurrent accesses. 594 ********************************************************************************************* 595 * @ dst_xp : extended pointer on the source process descriptor (in owner cluster). 596 * @ 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 ); 537 600 538 601 /********************************************************************************************* … … 598 661 599 662 /********************************************************************************************* 600 * This function attach a process, identified by the <process > argument to a TXT terminal,663 * This function attach a process, identified by the <process_xp> argument to a TXT terminal, 601 664 * identified by the <txt_id> channel index argument. 602 * The process descriptor identified by the <process > argument must be in the owner cluster.603 * It insert the process descriptor in the xlist rooted in the TXT_RX device.665 * The process descriptor identified by the <process_xp> argument must be in the owner 666 * cluster. It insert the process descriptor in the xlist rooted in the TXT_RX device. 604 667 * It is called by the process_reference_init() function. 605 668 ********************************************************************************************* 606 * @ process : local pointer on process descriptor.607 * @ txt_id : TXT channel index.608 ********************************************************************************************/ 609 void process_txt_attach( process_t * process,610 uint32_t 669 * @ process_xp : extended pointer on process descriptor in owner cluster. 670 * @ txt_id : TXT channel index. 671 ********************************************************************************************/ 672 void process_txt_attach( xptr_t process_xp, 673 uint32_t txt_id ); 611 674 612 675 /********************************************************************************************* … … 617 680 * cluster, but the calling thread can be running in any cluster. 618 681 ********************************************************************************************* 619 * @ process_xp : extended pointer on process descriptor .682 * @ process_xp : extended pointer on process descriptor in owner cluster. 620 683 ********************************************************************************************/ 621 684 void process_txt_detach( xptr_t process_xp ); 685 686 /********************************************************************************************* 687 * This function returns the TXT terminal index allocated to a process identified by the 688 * <process_xp> argument. The process descriptor identified by the <process_xp> argument 689 * must be in the owner cluster, but the calling thread can be running in any cluster. 690 ********************************************************************************************* 691 * @ process_xp : extended pointer on process descriptor in owner cluster. 692 ********************************************************************************************/ 693 uint32_t process_txt_get_index( xptr_t process_xp ); 622 694 623 695 /********************************************************************************************* … … 625 697 * ownership of its attached TXT_RX terminal (i.e. put the process in foreground). 626 698 * It can be called by a thread running in any cluster, but the target process descriptor 627 * must be the process owner.699 * must be in the owner cluster. 628 700 ********************************************************************************************* 629 701 * @ owner_xp : extended pointer on process descriptor in owner cluster. … … 654 726 655 727 /********************************************************************************************* 656 * This function returns an extended po nter on the current TXT owner process,728 * This function returns an extended pointer on the current TXT owner process, 657 729 * for the TXT terminal identified by the <channel> index. 658 730 ********************************************************************************************* -
trunk/kernel/kern/rpc.c
r657 r669 102 102 void __attribute__((noinline)) rpc_undefined( xptr_t xp __attribute__ ((unused)) ) 103 103 { 104 assert( false , "called in cluster %x", local_cxy );104 assert( __FUNCTION__, false , "called in cluster %x", local_cxy ); 105 105 } 106 106 … … 231 231 232 232 // response must be available for a blocking RPC 233 assert( (*rpc->rsp == 0) , "illegal response for RPC %s\n", rpc_str[rpc->index] );233 assert( __FUNCTION__, (*rpc->rsp == 0) , "illegal response for RPC %s\n", rpc_str[rpc->index] ); 234 234 235 235 } -
trunk/kernel/kern/scheduler.c
r651 r669 85 85 86 86 // check kernel threads list 87 assert( (count < sched->k_threads_nr), "bad kernel threads list" );87 assert( __FUNCTION__, (count < sched->k_threads_nr), "bad kernel threads list" ); 88 88 89 89 // get next entry in kernel list … … 119 119 120 120 // check user threads list 121 assert( (count < sched->u_threads_nr), "bad user threads list" );121 assert( __FUNCTION__, (count < sched->u_threads_nr), "bad user threads list" ); 122 122 123 123 // get next entry in user list … … 196 196 197 197 // check target thread blocked 198 assert( (thread->blocked & THREAD_BLOCKED_GLOBAL) , "thread not blocked" );198 assert( __FUNCTION__, (thread->blocked & THREAD_BLOCKED_GLOBAL) , "thread not blocked" ); 199 199 200 200 // decrement response counter … … 210 210 211 211 // check calling thread != target thread 212 assert( (thread != CURRENT_THREAD) , "calling thread cannot delete itself" );212 assert( __FUNCTION__, (thread != CURRENT_THREAD) , "calling thread cannot delete itself" ); 213 213 214 214 // get thread process descriptor … … 287 287 288 288 // check process descriptor is local kernel process 289 assert( ( thread->process == &process_zero ) , "illegal process descriptor");289 assert( __FUNCTION__, ( thread->process == &process_zero ) , "illegal process descriptor"); 290 290 291 291 // get thread ltid … … 322 322 323 323 // check th_nr value 324 assert( (process_zero.th_nr > 0) , "kernel process th_nr cannot be 0" );324 assert( __FUNCTION__, (process_zero.th_nr > 0) , "kernel process th_nr cannot be 0" ); 325 325 326 326 // remove thread from process th_tbl[] … … 495 495 // This assert should always be true, as this check has been 496 496 // done before, by any function that can possibly deschedule... 497 assert( (current->busylocks == 0),497 assert( __FUNCTION__, (current->busylocks == 0), 498 498 "current thread hold %d busylocks\n", current->busylocks ); 499 499 … … 511 511 512 512 // check next thread kernel_stack overflow 513 assert( (next->signature == THREAD_SIGNATURE),513 assert( __FUNCTION__, (next->signature == THREAD_SIGNATURE), 514 514 "kernel stack overflow for thread %x on core[%x,%d]", next, local_cxy, lid ); 515 515 516 516 // check next thread attached to same core as the current thread 517 assert( (next->core == current->core),517 assert( __FUNCTION__, (next->core == current->core), 518 518 "next_core_lid %d / current_core_lid %d", current->core->lid, next->core->lid ); 519 519 520 520 // check next thread not blocked when type != IDLE 521 assert( ((next->blocked == 0) || (next->type == THREAD_IDLE)) ,521 assert( __FUNCTION__, ((next->blocked == 0) || (next->type == THREAD_IDLE)) , 522 522 "next thread %x (%s) is blocked on core[%x,%d]", 523 523 next->trdid , thread_type_str(next->type) , local_cxy , lid ); -
trunk/kernel/kern/thread.c
r662 r669 30 30 #include <hal_remote.h> 31 31 #include <hal_vmm.h> 32 #include <hal_switch.h> 32 33 #include <memcpy.h> 33 34 #include <printk.h> … … 120 121 121 122 // check type and trdid fields are initialized 122 assert( (thread->type == type) , "bad type argument" );123 assert( (thread->trdid == trdid) , "bad trdid argument" );123 assert( __FUNCTION__, (thread->type == type) , "bad type argument" ); 124 assert( __FUNCTION__, (thread->trdid == trdid) , "bad trdid argument" ); 124 125 125 126 #if DEBUG_THREAD_INIT … … 160 161 list_entry_init( &thread->sched_list ); 161 162 163 // initialize the embedded alarm to unlink 164 list_entry_init( &thread->alarm.list ); 165 162 166 // initialize waiting queue entries 163 167 list_entry_init( &thread->wait_list ); … … 220 224 vseg_t * us_vseg; // user stack vseg 221 225 222 assert( (attr != NULL) , "pthread attributes must be defined" );226 assert( __FUNCTION__, (attr != NULL) , "pthread attributes must be defined" ); 223 227 224 228 #if DEBUG_THREAD_USER_CREATE … … 370 374 return -1; 371 375 } 372 hal_cpu_context_init( thread ); 376 hal_cpu_context_init( thread, 377 false , 0 , 0 ); // not a main thread 373 378 374 379 // allocate & initialize FPU context … … 662 667 } // end thread_user_fork() 663 668 664 //////////////////////////////////////////////// 665 error_t thread_user_exec( void * entry_func, 666 uint32_t argc, 667 char ** argv ) 669 ///////////////////////////////////// 670 void thread_user_exec( uint32_t argc, 671 intptr_t argv ) 668 672 { 669 673 thread_t * thread = CURRENT_THREAD; … … 673 677 uint32_t cycle = (uint32_t)hal_get_cycles(); 674 678 if( DEBUG_THREAD_USER_EXEC < cycle ) 675 printk("\n[%s] thread[%x,%x] enter / entry %x /cycle %d\n",676 __FUNCTION__, process->pid, thread->trdid, entry_func ,cycle );679 printk("\n[%s] thread[%x,%x] enter / cycle %d\n", 680 __FUNCTION__, process->pid, thread->trdid, cycle ); 677 681 #endif 678 682 679 683 // check parent thread attributes 680 assert( (thread->type == THREAD_USER ), "bad type" );681 assert( (thread->signature == THREAD_SIGNATURE) , "bad signature" );682 assert( (thread->busylocks == 0) , "bad busylocks" );684 assert( __FUNCTION__, (thread->type == THREAD_USER ) , "bad type" ); 685 assert( __FUNCTION__, (thread->signature == THREAD_SIGNATURE) , "bad signature" ); 686 assert( __FUNCTION__, (thread->busylocks == 0) , "bad busylocks" ); 683 687 684 688 // re-initialize various thread descriptor fields 685 thread->quantum = 0; // TODO 686 thread->ticks_nr = 0; // TODO 687 thread->time_last_check = 0; // TODO 688 689 thread->entry_func = entry_func; 690 thread->main_argc = argc; 691 thread->main_argv = argv; 692 693 // the main thread is always detached 694 thread->flags = THREAD_FLAG_DETACHED; 689 thread->quantum = 0; // TODO 690 thread->ticks_nr = 0; // TODO 691 thread->time_last_check = 0; // TODO 692 thread->entry_func = (void*)process->vmm.entry_point; 693 thread->flags = THREAD_FLAG_DETACHED; // main always detached 695 694 thread->blocked = 0; 696 695 thread->errno = 0; 697 thread->fork_user = 0; // not inherited 698 thread->fork_cxy = 0; // not inherited 699 700 // re-initialize busylocks counters 701 thread->busylocks = 0; 696 thread->fork_user = 0; 697 thread->fork_cxy = 0; 702 698 703 699 // reset thread info … … 707 703 remote_busylock_init( XPTR( local_cxy , &thread->join_lock ), LOCK_THREAD_JOIN ); 708 704 709 // allocate an user stack vseg for main thread710 vseg_t * us_vseg = vmm_create_vseg( process,711 VSEG_TYPE_STACK,712 LTID_FROM_TRDID( thread->trdid ),713 0, // length unused714 0, // file_offset unused715 0, // file_size unused716 XPTR_NULL, // mapper_xp unused717 local_cxy );718 if( us_vseg == NULL )719 {720 printk("\n[ERROR] in %s : cannot create stack vseg for main thread\n", __FUNCTION__ );721 return -1;722 }723 724 // update user stack in thread descriptor725 thread->user_stack_vseg = us_vseg;726 727 705 // release FPU ownership if required 728 706 if( thread->core->fpu_owner == thread ) thread->core->fpu_owner = NULL; 729 707 730 // re-initializeFPU context708 // initialize thread FPU context 731 709 hal_fpu_context_init( thread ); 710 711 // initialize thread CPU context 712 hal_cpu_context_init( thread, 713 true, // main thread 714 argc, 715 argv ); 732 716 733 717 #if DEBUG_THREAD_USER_EXEC 734 718 cycle = (uint32_t)hal_get_cycles(); 735 719 if( DEBUG_THREAD_USER_EXEC < cycle ) 736 printk("\n[%s] thread[%x,%x] set CPU context & jump to user code / cycle %d\n", 737 __FUNCTION__, process->pid, thread->trdid, cycle ); 738 hal_vmm_display( XPTR( local_cxy , process ) , true );739 #endif 740 741 // re-initialize CPU context... and jump to user code742 hal_cpu_context_exec( thread ); 743 744 assert( false, "we should not execute this code"); 745 746 return 0;720 { 721 printk("\n[%s] thread[%x,%x] set CPU context & jump to user code / cycle %d\n", 722 __FUNCTION__, process->pid, thread->trdid, cycle ); 723 724 hal_cpu_context_display( XPTR( local_cxy , thread ) ); 725 hal_vmm_display( XPTR( local_cxy , process ) , true ); 726 } 727 #endif 728 729 // restore CPU registers ... and jump to user code 730 hal_do_cpu_restore( thread->cpu_context ); 747 731 748 732 } // end thread_user_exec() … … 761 745 thread_t * this = CURRENT_THREAD; 762 746 763 assert( ( (type == THREAD_IDLE) || (type == THREAD_RPC) || (type == THREAD_DEV) ) ,747 assert( __FUNCTION__, ( (type == THREAD_IDLE) || (type == THREAD_RPC) || (type == THREAD_DEV) ) , 764 748 "illegal thread type" ); 765 749 766 assert( (core_lid < LOCAL_CLUSTER->cores_nr) ,750 assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr) , 767 751 "illegal core_lid" ); 768 752 … … 829 813 } 830 814 831 hal_cpu_context_init( thread ); 815 hal_cpu_context_init( thread, 816 false , 0 , 0 ); // not a main thread 832 817 833 818 #if DEBUG_THREAD_KERNEL_CREATE … … 854 839 855 840 // check arguments 856 assert( (type == THREAD_IDLE) , "illegal thread type" );857 assert( (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" );841 assert( __FUNCTION__, (type == THREAD_IDLE) , "illegal thread type" ); 842 assert( __FUNCTION__, (core_lid < LOCAL_CLUSTER->cores_nr) , "illegal core index" ); 858 843 859 844 // set type in thread descriptor … … 863 848 error = process_register_thread( &process_zero , thread , &trdid ); 864 849 865 assert( (error == 0), "cannot register idle_thread in kernel process" );850 assert( __FUNCTION__, (error == 0), "cannot register idle_thread in kernel process" ); 866 851 867 852 // set trdid in thread descriptor … … 878 863 NULL ); // no user stack for a kernel thread 879 864 880 assert( (error == 0), "cannot initialize idle_thread" );881 882 // allocate & initialize CPU context if success865 assert( __FUNCTION__, (error == 0), "cannot initialize idle_thread" ); 866 867 // allocate CPU context 883 868 error = hal_cpu_context_alloc( thread ); 884 869 885 assert( (error == 0), "cannot allocate CPU context" ); 886 887 hal_cpu_context_init( thread ); 870 assert( __FUNCTION__, (error == 0), "cannot allocate CPU context" ); 871 872 // initialize CPU context 873 hal_cpu_context_init( thread, 874 false , 0 , 0 ); // not a main thread 888 875 889 876 } // end thread_idle_init() … … 949 936 #endif 950 937 938 // unlink embedded alarm from the list rooted in core when required 939 list_entry_t * entry = &thread->alarm.list; 940 if( (entry->next != NULL) || (entry->pred != NULL) ) list_unlink( entry ); 941 951 942 // remove thread from process th_tbl[] 952 943 count = process_remove_thread( thread ); … … 1028 1019 1029 1020 // check signal pending in scheduler 1030 assert( sched->req_ack_pending , "no pending signal" );1021 assert( __FUNCTION__, sched->req_ack_pending , "no pending signal" ); 1031 1022 1032 1023 // enter critical section … … 1101 1092 1102 1093 ////////////////////////////////////// 1103 void thread_delete ( xptr_t target_xp,1094 void thread_delete_request( xptr_t target_xp, 1104 1095 bool_t is_forced ) 1105 1096 { … … 1150 1141 // check target thread is not the main thread, because the main thread 1151 1142 // must be deleted by the parent process sys_wait() function 1152 assert( ((CXY_FROM_PID( target_pid ) != target_cxy) || (target_ltid != 0)),1143 assert( __FUNCTION__, ((CXY_FROM_PID( target_pid ) != target_cxy) || (target_ltid != 0)), 1153 1144 "target thread cannot be the main thread" ); 1154 1145 … … 1275 1266 1276 1267 } 1277 } // end thread_delete ()1268 } // end thread_delete_request() 1278 1269 1279 1270 -
trunk/kernel/kern/thread.h
r662 r669 37 37 #include <core.h> 38 38 #include <chdev.h> 39 #include <alarm.h> 39 40 #include <cluster.h> 40 41 #include <process.h> … … 95 96 #define THREAD_BLOCKED_LOCK 0x1000 /*! ANY : wait queuelock or rwlock */ 96 97 #define THREAD_BLOCKED_CLIENT 0x2000 /*! DEV : wait clients queue non empty */ 98 #define THREAD_BLOCKED_ALARM 0x4000 /*! ANY : wait a timer based alarm */ 97 99 98 100 /*************************************************************************************** … … 160 162 vseg_t * user_stack_vseg; /*! local pointer on user stack vseg */ 161 163 162 void * entry_func; /*! pointer on entry function */ 163 void * entry_args; /*! pointer on entry function arguments */ 164 uint32_t main_argc; /*! main thread number of arguments */ 165 char ** main_argv; /*! main thread array of strings arguments */ 164 void * entry_func; /*! pointer on thread entry function */ 165 void * entry_args; /*! pthread : pointer on arguments */ 166 166 167 167 uint32_t flags; /*! bit vector of flags */ … … 177 177 178 178 chdev_t * chdev; /*! chdev pointer (for a DEV thread only) */ 179 180 alarm_t alarm; /*! embedded timer based alarm */ 179 181 180 182 reg_t save_sr; /*! used by sched_yield() function */ … … 269 271 /*************************************************************************************** 270 272 * This function is called by the process_make_exec() function to re-initialise the 271 * calling thread descriptor, that will become the new process main thread .272 * It must be called by the main thread of the calling process.273 * calling thread descriptor, that will become the new process main thread, from 274 * the process descriptor, and from the <args_nr> & <args_base> arguments. 273 275 * - The calling thread TRDID is not modified. 274 276 * - The kernel stack (currently in use) is not modified. 275 * - A new user stack vseg is created and initialised. 276 * - The function calls the hal_cpu_context_exec() to re-initialize the CPU context 277 * and the uzone registered in kernel stack, an jump to user code. 278 *************************************************************************************** 279 * @ entry_func : main thread entry point. 280 * @ argc : number of main thread arguments. 281 * @ argv : array of pointers on stringarguments. 282 * @ returns 0 if success / returns ENOMEM if error. 283 **************************************************************************************/ 284 error_t thread_user_exec( void * entry_func, 285 uint32_t argc, 286 char ** argv); 277 * - It calls the hal_cpu_context_init() to re-initialize the thread CPU context. 278 * - It calls the hal_do_cpu_restore() to force execution of the new user code. 279 *************************************************************************************** 280 * @ argc : actual number of main thread arguments. 281 * @ argv : user space pointer on array of pointers on arguments. 282 **************************************************************************************/ 283 void thread_user_exec( uint32_t argc, 284 intptr_t argv ); 287 285 288 286 /*************************************************************************************** … … 397 395 * @ is_forced : the deletion does not depends on the attached mode. 398 396 **************************************************************************************/ 399 void thread_delete ( xptr_t thread_xp,400 bool_t is_forced );397 void thread_delete_request( xptr_t thread_xp, 398 bool_t is_forced ); 401 399 402 400 /***************************************************************************************
Note: See TracChangeset
for help on using the changeset viewer.