Linux Forums - Linux Help,Advice & support community:LinuxSolved.com
		Linux in General => Linux Kernel => Topic started by: Xee on November 16, 2009, 04:50:39 AM
		
			
			- 
				Hello..
 
 As a part of homework.. i need to add a piece of code to the function do_fork in the file fork.c
 I need to copy a linked list i have added to the task descriptor from the father to the new son just cloned in fork.
 Here is the change i've made on do_fork:
 [ i've attached the whole implementation of do_fork.. but please look only at the code i've added :"My code starts here"]
 
 int do_fork(unsigned long clone_flags, unsigned long stack_start,
 struct pt_regs *regs, unsigned long stack_size)
 {
 int retval,j;
 event_node* current_node;
 unsigned long flags;
 struct task_struct *p;
 struct completion vfork;
 
 if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 return -EINVAL;
 
 retval = -EPERM;
 
 /*
 * CLONE_PID is only allowed for the initial SMP swapper
 * calls
 */
 if (clone_flags & CLONE_PID) {
 if (current->pid)
 goto fork_out;
 }
 
 retval = -ENOMEM;
 p = alloc_task_struct();
 if (!p)
 goto fork_out;
 
 *p = *current;
 p->tux_info = NULL;
 p->cpus_allowed_mask &= p->cpus_allowed;
 
 retval = -EAGAIN;
 /*
 * Check if we are over our maximum process limit, but be sure to
 * exclude root. This is needed to make it possible for login and
 * friends to set the per-user process limit to something lower
 * than the amount of processes root is running. -- Rik
 */
 if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur
 && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
 goto bad_fork_free;
 
 atomic_inc(&p->user->__count);
 atomic_inc(&p->user->processes);
 
 /*
 * Counter increases are protected by
 * the kernel lock so nr_threads can't
 * increase under us (but it may decrease).
 */
 if (nr_threads >= max_threads)
 goto bad_fork_cleanup_count;
 
 get_exec_domain(p->exec_domain);
 
 if (p->binfmt && p->binfmt->module)
 __MOD_INC_USE_COUNT(p->binfmt->module);
 
 p->did_exec = 0;
 p->swappable = 0;
 p->state = TASK_UNINTERRUPTIBLE;
 
 copy_flags(clone_flags, p);
 p->pid = get_pid(clone_flags);
 if (p->pid == 0 && current->pid != 0)
 goto bad_fork_cleanup;
 
 INIT_LIST_HEAD(&p->run_list);
 
 p->p_cptr = NULL;
 init_waitqueue_head(&p->wait_chldexit);
 p->vfork_done = NULL;
 if (clone_flags & CLONE_VFORK) {
 p->vfork_done = &vfork;
 init_completion(&vfork);
 }
 spin_lock_init(&p->alloc_lock);
 
 p->sigpending = 0;
 init_sigpending(&p->pending);
 
 p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
 p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
 init_timer(&p->real_timer);
 p->real_timer.data = (unsigned long) p;
 
 p->leader = 0;		/* session leadership doesn't inherit */
 p->tty_old_pgrp = 0;
 p->times.tms_utime = p->times.tms_stime = 0;
 p->times.tms_cutime = p->times.tms_cstime = 0;
 #ifdef CONFIG_SMP
 {
 int i;
 
 /* ?? should we just memset this ?? */
 for(i = 0; i < smp_num_cpus; i++)
 p->per_cpu_utime[cpu_logical_map(i)] =
 p->per_cpu_stime[cpu_logical_map(i)] = 0;
 spin_lock_init(&p->sigmask_lock);
 }
 #endif
 p->array = NULL;
 p->lock_depth = -1;		/* -1 = no lock */
 p->start_time = jiffies_64;
 
 retval = -ENOMEM;
 /* copy all the process information */
 if (copy_files(clone_flags, p))
 goto bad_fork_cleanup;
 if (copy_fs(clone_flags, p))
 goto bad_fork_cleanup_files;
 if (copy_sighand(clone_flags, p))
 goto bad_fork_cleanup_fs;
 if (copy_mm(clone_flags, p))
 goto bad_fork_cleanup_sighand;
 if (copy_namespace(clone_flags, p))
 goto bad_fork_cleanup_mm;
 retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
 if (retval)
 goto bad_fork_cleanup_namespace;
 p->semundo = NULL;
 
 /* Our parent execution domain becomes current domain
 These must match for thread signalling to apply */
 
 p->parent_exec_id = p->self_exec_id;
 
 /* ok, now we should be set up.. */
 p->swappable = 1;
 p->exit_signal = clone_flags & CSIGNAL;
 p->pdeath_signal = 0;
 
 /*
 * Share the timeslice between parent and child, thus the
 * total amount of pending timeslices in the system doesnt change,
 * resulting in more scheduling fairness.
 */
 __save_flags(flags);
 __cli();
 if (!current->time_slice)
 BUG();
 p->time_slice = (current->time_slice + 1) >> 1;
 p->first_time_slice = 1;
 current->time_slice >>= 1;
 p->sleep_timestamp = jiffies;
 if (!current->time_slice) {
 /*
 * This case is rare, it happens when the parent has only
 * a single jiffy left from its timeslice. Taking the
 * runqueue lock is not a problem.
 */
 current->time_slice = 1;
 scheduler_tick(0,0);
 }
 __restore_flags(flags);
 
 /*
 * Ok, add it to the run-queues and make it
 * visible to the rest of the system.
 *
 * Let it rip!
 */
 
 /***************************************************************************/
 /************* My code starts here********************************************/
 /***************************************************************************/
 
 p->events_queue = (events_list*)kmalloc(sizeof(events_list), GFP_KERNEL);
 p->events_queue->dummy = (event_node*)kmalloc(sizeof(event_node), GFP_KERNEL);
 p->events_queue->dummy->prev=NULL;
 p->events_queue->dummy->next=NULL;
 p->events_queue->dummy->event_data=NULL;
 
 p->events_queue->oldest = p->events_queue->dummy;
 p->events_queue->size = current->events_queue->size;
 p->is_monitored = 0;
 p->events_num = current->events_queue->size;
 current_node = current->events_queue->dummy->next;
 printk(" line 10 is done \n");
 while(current_node != NULL){
 printk(" this line is the 'while' loop \n");
 p_event* to_add = (p_event*)kmalloc(sizeof(p_event), GFP_KERNEL);
 for(j=0;j<256;++j)
 to_add->filename[j] = current_node->event_data->filename[j];
 to_add->type = current_node->event_data->type;
 add_event(p->events_queue,to_add);
 current_node = current_node->next;
 }
 /***************************************************************************/
 /************* My code ends here***********************************************/
 /***************************************************************************/
 
 
 retval = p->pid;
 p->tgid = retval;
 INIT_LIST_HEAD(&p->thread_group);
 
 /* Need tasklist lock for parent etc handling! */
 write_lock_irq(&tasklist_lock);
 
 /* CLONE_PARENT re-uses the old parent */
 p->p_opptr = current->p_opptr;
 p->p_pptr = current->p_pptr;
 if (!(clone_flags & CLONE_PARENT)) {
 p->p_opptr = current;
 if (!(p->ptrace & PT_PTRACED))
 p->p_pptr = current;
 }
 
 if (clone_flags & CLONE_THREAD) {
 p->tgid = current->tgid;
 list_add(&p->thread_group, ¤t->thread_group);
 }
 
 SET_LINKS(p);
 hash_pid(p);
 nr_threads++;
 write_unlock_irq(&tasklist_lock);
 
 if (p->ptrace & PT_PTRACED)
 send_sig(SIGSTOP, p, 1);
 wake_up_forked_process(p);	/* do this last */
 ++total_forks;
 if (clone_flags & CLONE_VFORK)
 wait_for_completion(&vfork);
 else
 /*
 * Let the child process run first, to avoid most of the
 * COW overhead when the child exec()s afterwards.
 */
 current->need_resched = 1;
 
 fork_out:
 return retval;
 
 bad_fork_cleanup_namespace:
 exit_namespace(p);
 bad_fork_cleanup_mm:
 exit_mm(p);
 bad_fork_cleanup_sighand:
 exit_sighand(p);
 bad_fork_cleanup_fs:
 exit_fs(p); /* blocking */
 bad_fork_cleanup_files:
 exit_files(p); /* blocking */
 bad_fork_cleanup:
 put_exec_domain(p->exec_domain);
 if (p->binfmt && p->binfmt->module)
 __MOD_DEC_USE_COUNT(p->binfmt->module);
 bad_fork_cleanup_count:
 atomic_dec(&p->user->processes);
 free_uid(p->user);
 bad_fork_free:
 free_task_struct(p);
 goto fork_out;
 }
 
 
 
 
 The problem is when i try to test this.. the whole system lags.. it's not even segmentation fault.. i have to restart the system each time i call fork explicitly:
 
 Here is a piece of code that i do for testing do_fork():
 
 
 int main(){
 int wrap_res,i,j,res;
 int fa,fb,status;
 
 
 start_monitor(getpid());
 printf("current events number is %d\n",get_event_number());
 fb = open("bbb.txt",O_RDWR);
 if (fb ==-1) exit(-1);
 fb = open("bbb.txt",O_RDWR);
 if (fb ==-1) exit(-1);
 fa = open("aaa.txt",O_RDWR);
 if (fa ==-1) exit(-1);
 close(fb);
 
 event events_array[4];
 
 status = fork();
 if ( status < 0 ) return 0;
 if ( status == 0 ){
 printf("kaka\n");
 exit(-1);
 res = get_events(getpid(), 8, events_array);
 printf("Number of events of process: %d is: \n",getpid(),res);
 if (res<0) exit(-1);
 printf("The events of process: %d are: \n",getpid());
 for (i=0;i<res;i++) printf("Event %d is %s file %s\n",i,events_array[i].type==Open?"open":"close",events_array[i].filename);
 }
 
 stop_monitor(getpid());
 return 0;
 
 the system lags on the call: fork();
 eve i can't make a step in this call on ddd to know on which line exactly the system fails.. :S
 
 I have been working on this for days.. i hope i can find someone to help me..
 any idea? what's wrong in this call? code modification ?
 
 Thanks :)