The fork system call
The pseudo code:
do_fork()
{
Increment number of the tasks, we gOT one more;
The new task is ready to run.
Copy the whole TCB.
Copy the whole tcb (task control block), wich
contains all hw- related things as registers
to the new task;
CHANGE RETURN PARAMETER TO THE CHILD PROCESS (
reg r8)
SET tlb tr info for the new task's backing strore
area.
Backing store must always have translation
virtual-> physical. Can't use fault as the rest of the system (demand
paging).
loop(parent's all page table entries)
{
if (parent alreday accessed the page)
{
Icrement
gobal physicl block pointer.
Copy the
PYSICAL page for children.
Update
child's page table (The new pages needed come from "the disc"- simulated
as needed)
}
}
Return to the middle of the context switch- branch by
flag, BAD PROGRAMMING STYLE, SEE EXERCISES
}
A parent and child differ from each other by athe return value. I use for
the parent 1944 (my birth year) and for the child 1972, my son's bith
year.
register char * f_ptr
__asm__("r4"); //
These are "caller saved" registers, gcc do not use then RSE when it needs
more registers!
register char *
old_ptr
__asm__("r5");
register char * f_ptr_T
__asm__("r6");
register char *
old_ptr_T
__asm__("r7");
//_____________________
void do_fork(void){
fork_flag=0;
old_ptr = (char *)tcb_ptr[found];
f_ptr = (char
*)tcb_ptr[MAXTASK];
old_ptr_T =
(char *)TCB_ptr[found];
f_ptr_T = (char
*)TCB_ptr[MAXTASK];//+1!!!!!!!!!!!!!!
F_ptr = (struct
tcb_type *)f_ptr;
O_ptr = (struct
tcb_type *)old_ptr;
for (count=0;count
< STCB;count++) // Copy TCB to new task (Task Control
Block)
*f_ptr_T++ = *old_ptr_T++;
++MAXTASK;
//Now we have one more task
_ready_
= _ready_ | (1 << MAXTASK-1); //And the new task is ready to
run
message=0x1944;//Return value for the original task
for (count=0;count
< Stcb;count++) //Copy whole tcb (HW state, registers)
*f_ptr++ = *old_ptr++;
F_ptr->GRs_r01_r15[7]=0x1972; //Return value for the new
task. THE COPIED CONTENTS IS NOT GOOD AS TO RETURN VALUE
F_ptr->flag = 0xa;
F_ptr->rse_idrt = (F_ptr->rse_idrt &
0xffffffffff000fff ) | ((long)(next_block+0x200)) ; //NEW TLB transalation
info to for backing store
for(iDsize=0;iDsize< MAXPAGES;iDsize++) //Make new physical copy
for the child task/ every accessed data page of the parent
{
d_ptr = (long
*)(PHYS_data[found][iDsize]) ;
if((long)(d_ptr) !=0)
{
next_block += 0x200;
new_d_ptr =next_block;
or(r=0;r<
0x200;r++ )//Copy the data segment including backing storage
*new_d_ptr++= *d_ptr++;
PHYS_data[MAXTASK-1][iDsize]=(long)next_block ;
//Update child's page table
}
}
__asm__("br.sptk.few b7;");
}