\newpage
%===========================================================================
%       x.18 > INIT
%===========================================================================
\pagestyle{empty}
\begin{latexonly}
\hfill\line(1,0){400}
\end{latexonly}
\topmargin 1in
\section{\tt {./init/*}}
\begin{latexonly}
\line(1,0){400}
\begin{verbatim}
This directory contains the initialization code for the kernel and it
is a very good place to start looking at how the kernel works. 

patching file init/main.c
\end{verbatim}
\newpage
\end{latexonly}
\topmargin 0in
\pagestyle{fancy}
%===========================================================================
\subsection{{\em main.c}}
Este fichero es el que inicia en cualquier sistema linux el proceso con pid 1,
el proceso {\em init}. Se definen las primeras variables de
arranque y seguidamente se invoca a tres funciones importantes. 
\begin{enumerate}
  \item {\tt extern void prepare\_namespace()} . Prepara el {\em namespace}, es
  decir, decide qu\'e y donde montar, cargar los {\em ramdisks}, {\em etc.}
  Su implementaci\'on puede encontrarse en {\em /init/do\_mounts.c} y no sufre
  modificaciones por el parche de openMosix.

  \item {\tt static int init(void * unused)} . Ejecuta los primeros procesos
  del sistema. Esto incluye tambi\'en a la funci\'on {\tt init\_mosix()} cuya
  implementaci\'on se encuentra en {\em ./hpc/init.c} .

  \item {\tt init\_mosix()} . V\'eanse comentarios en la implementaci\'on.
\end{enumerate}

\vspace{.2in}
\psshadowbox{{\tt extern void prepare\_namespace()}}

\vspace{.1in}
\begin{verbatim}
void prepare_namespace(void)
{
        int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
#ifdef CONFIG_ALL_PPC
        extern void arch_discover_root(void);
        arch_discover_root();
#endif /* CONFIG_ALL_PPC */
#ifdef CONFIG_BLK_DEV_INITRD
        if (!initrd_start)
                mount_initrd = 0;
        real_root_dev = ROOT_DEV;
#endif
        sys_mkdir("/dev", 0700);
        sys_mkdir("/root", 0700);
        sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1));
#ifdef CONFIG_DEVFS_FS
        sys_mount("devfs", "/dev", "devfs", 0, NULL);
        do_devfs = 1;
#endif

        create_dev("/dev/root", ROOT_DEV, NULL);
        if (mount_initrd) {
                if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) {
                        handle_initrd();
                        goto out;
                }
        } else if (is_floppy && rd_doload && rd_load_disk(0))
                ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
        mount_root();
out:
        sys_umount("/dev", 0);
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
        sys_chroot(".");
        mount_devfs_fs ();
}
\end{verbatim}

\vspace{.2in}
\psshadowbox{{\tt static int init(void * unused)}}

\vspace{.1in}
\begin{verbatim}
static int init(void * unused)
{
        lock_kernel();
        do_basic_setup();

        prepare_namespace();

        free_initmem();
#ifdef CONFIG_MOSIX
        init_mosix();
#endif /* CONFIG_MOSIX */
        unlock_kernel();

        if (open("/dev/console", O_RDWR, 0) < 0)
                printk("Warning: unable to open an initial console.\n");

        (void) dup(0);
        (void) dup(0);
        
        if (execute_command)
                execve(execute_command,argv_init,envp_init);
        execve("/sbin/init",argv_init,envp_init);
        execve("/etc/init",argv_init,envp_init);
        execve("/bin/init",argv_init,envp_init);
        execve("/bin/sh",argv_init,envp_init);
        panic("No init found.  Try passing init= option to kernel.");
}
\end{verbatim}

\vspace{.2in}
\psshadowbox{{\tt init\_mosix()}}

\vspace{.1in}
\begin{verbatim}
void
init_mosix(void)
{
        extern int x86_udelay_tsc;
        cpuspeed = ((int64_t)loops_per_jiffy) * STD_SPD / STD_LOOPS; /*
velocidad del nodo */
\end{verbatim}

La constante de openMosix {\em STD\_SPD} debe su nombre a {\em standard speed}
y se define en {\em ./include/hpc/defs.h} como 15000.

\begin{verbatim}
        if(!x86_udelay_tsc)
                cpuspeed *= 2;
\end{verbatim}

La constante {\tt x86\_udelay\_tsc} se define en {\em ./lib/delay.c} como el
entero de valor 0 -cero-. Como puede leerse, si el {\em delay} entre dos
lecturas al registro TSC es cero, se dobla el
valor de velocidad tomado para el nodo donde se inicialice el servicio openMosix.

El TimeStamp Counter (TSC) es un valor que se toma de un registro que poseen
todos los nuevos procesadores. Este registro se incrementa cada ciclo de
reloj. Leyendo 2 veces el registro y dividiendo la diferencia de ciclos
obtenida entre el intervalo de tiempo transcurrido, se obtiene la frecuencia de reloj del procesador.

\begin{verbatim}
        info_init();
\end{verbatim}
Esta funci\'on est\'a implementada en {\em ./hpc/info.c}. Define los valores
para:
\begin{itemize}
  \item n\'umero de procesadores
  \item tama\~{n}o de memoria
  \item invoca a {\tt set\_my\_cpuspeed()} para definir los costes tanto de
  carga como para el sistema de ficheros mfs. Se encuentra implementada
  tambi\'en en {\em ./hpc/info.c} .
\end{itemize}
\begin{verbatim}
        proc_update_costs();
\end{verbatim}

\begin{verbatim}
#ifdef CONFIG_MOSIX_FS
        init_mfs();             /* si el kernel soporta MFS, se inicia */
#endif /* CONFIG_MOSIX_FS */
#ifdef CONFIG_MOSIX_DFSA
        dfsa_init();            /* si el kernel soporta DFSA, se inicia */
#endif /* CONFIG_MOSIX_DFSA */
        kernel_thread(mosix_mig_daemon, NULL, 0);  /* se inicia el daemon de  migracion */
                                                   /* como hebra del kenel              */
        info_startup();
\end{verbatim}

Esta funci\'on tambi\'en est\'a implementada en {\em ./hpc/info.c} . Toma una
ventana de informaci\'on del cluster -i.e. varios nodos, pueden no ser todos-
y eval\'a su ponderaci\'on.

\begin{verbatim}
        mosix_load_init();           /* actualiza la carga instantanea del nodo */
        mosinfo_update_gateways();   /* actualiza costes de envios entre nodos */
        kernel_thread(mosix_info_daemon, NULL, 0);   /* daemon de informacion del sistema */
        kernel_thread(mosix_mem_daemon, NULL, 0);    /* daemon para la memoria */
}
\end{verbatim}