April 19, 2024, 01:25:36 PM

News : LinuxSolved.com Linux Help Community Forum..


Author Topic: problem in do_fork()  (Read 5485 times)

Offline Xee

  • New Member
  • Posts: 2
problem in do_fork()
« 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"]

 
Code: [Select]
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, &current->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():

Code: [Select]

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 :)