source: trunk/user/init/init.c @ 690

Last change on this file since 690 was 682, checked in by alain, 3 years ago

Introduce three new applications:

  • windows : to test the FBF windows kernel manager
  • udp_chat : chat application based on UDP sockets.
  • tcp_chat : chat application based on TCP sockets (including packet loss recovery).
File size: 6.9 KB
RevLine 
[427]1///////////////////////////////////////////////////////////////////////////////////////
2// File   :  init.c
3// Date   :  January 2018
4// Author :  Alain Greiner
5///////////////////////////////////////////////////////////////////////////////////////
6// This single thread application implement the "init" process for ALMOS-MKH.
[434]7// It uses the fork/exec syscalls to create N KSH child processes
[659]8// (one child process per user TXT terminal).
[682]9// Then it calls the wait() function to block, and recreate any child KSH process
[434]10// that has been deleted, using a new fork/exec.
[427]11///////////////////////////////////////////////////////////////////////////////////////
12
[444]13#include <unistd.h>
[427]14#include <stdlib.h>
15#include <stdio.h>
16#include <pthread.h>
[445]17#include <almosmkh.h>
[574]18#include <hal_macros.h>
[444]19#include <sys/wait.h>
[659]20#include <shared_syscalls.h>
[427]21
[676]22#define DEBUG_PROCESS_INIT    0
[440]23
[574]24////////////////
[475]25int main( void )
[427]26{
[659]27    unsigned int  i;
[438]28    int           ret_fork;      // fork return value 
29    int           ret_exec;      // exec return value 
30    int           rcv_pid;       // pid received from the wait syscall
31    int           status;        // used by the wait syscall
32    char          string[64];    // log messages on kernel TXT0
[682]33    unsigned int  cxy;           // target cluster identifier
[427]34
[574]35#if DEBUG_PROCESS_INIT
[623]36display_string("[init] process enters");
[574]37#endif
38
[682]39    // get number of TXT channels and number of clusters
[659]40    hard_config_t config;     
[676]41
[659]42    get_config( &config );
43
44    unsigned int  txt_channels = config.txt_channels;
[682]45    unsigned int  x_size       = config.x_size;
46    unsigned int  y_size       = config.y_size;
47    unsigned int  n_clusters    = x_size * y_size;
[659]48
[427]49    // check number of TXT channels
[659]50    if( txt_channels < 2 )
[445]51    {
[659]52        snprintf( string , 64 ,
[676]53        "\n[init ERROR] number of TXT channels must be larger than 1");
[659]54        display_string( string );
[445]55        exit( EXIT_FAILURE );
56    }
[427]57
[682]58    cxy = 0;
59
[427]60    // create the KSH processes (one per user terminal)
[659]61    for( i = 1 ; i <  txt_channels ; i++ )
[427]62    {
[682]63        // compute target cluster
64        cxy = (cxy + 1) % n_clusters;
65
66        // select target cluster
67        if( place_fork( cxy ) )
68        {
69            // INIT display error message 
70            snprintf( string , 64 , 
71            "\n[init ERROR] cannot place fork for child[%d] => suicide" , i );
72            display_string( string );
73
74            // INIT suicide
75            exit( EXIT_FAILURE );
76        }
77
78
[434]79        // INIT process fork process CHILD[i]
80        ret_fork = fork();
81
[436]82        if( ret_fork < 0 )   // error in fork
[427]83        {
[437]84            // INIT display error message 
[659]85            snprintf( string , 64 , 
[676]86            "\n[init ERROR] cannot fork child[%d] => suicide" , i );
[427]87            display_string( string );
88
[436]89            // INIT suicide
[659]90            exit( EXIT_FAILURE );
[427]91        }
[434]92        else if( ret_fork == 0 )                    // we are in CHILD[i] process
[427]93        {
[676]94
95#if DEBUG_PROCESS_INIT
96            snprintf( string , 64 ,
97            "\n[init] CHILD[%d] process forked / call execve", i );
98            display_string( string );
99#endif
[434]100            // CHILD[i] process exec process KSH[i]
[444]101            ret_exec = execve( "/bin/user/ksh.elf" , NULL , NULL ); 
[434]102
103            if ( ret_exec )   // error in exec             
[427]104            {
[437]105                // CHILD[i] display error message
[435]106                snprintf( string , 64 , 
[676]107                "\n[init ERROR] CHILD[%d] cannot exec KSH" , i );
[434]108                display_string( string );
[659]109
110                // CHILD[i] suicide
111                exit( EXIT_FAILURE );
[427]112            }
113        }
[434]114        else                                      // we are in INIT process
115        {
[457]116            // INIT display CHILD[i] process PID
[659]117            snprintf( string , 64 ,
[682]118            "[init] (pid 0x1) create ksh[%d] (pid %x)", i , ret_fork ); 
[457]119            display_string( string );
[434]120        }
121    } 
[440]122 
[442]123#if DEBUG_PROCESS_INIT
[528]124{
[682]125    // keep blocked for 2 seconds
126    // to allow all KSH[i] process
127    // to be launched before display
128
129    sleep( 2 );
130
[528]131    unsigned int  x;             // cluster x coordinate
132    unsigned int  y;             // cluster y coordinate
133    unsigned int  cxy;           // cluster identifier
134    unsigned int  lid;           // core local index
[434]135
[676]136    unsigned int  x_size       = config.x_size;
137    unsigned int  y_size       = config.y_size;
138    unsigned int  ncores       = config.ncores;
139
[528]140    // INIT displays processes and threads in all clusters
141    for( x = 0 ; x < x_size ; x++ )
[440]142    {
[588]143        for( y = 0 ; y < y_size ; y++ )
[581]144        {
145            cxy = HAL_CXY_FROM_XY( x , y );
[635]146            display_cluster_processes( cxy , 0 );
[581]147            for( lid = 0 ; lid < ncores ; lid++ )
148            { 
149                display_sched( cxy , lid );
150            }
[440]151        }
152    }
[457]153}
[440]154#endif
155
[435]156    // This loop detects the termination of the KSH[i] processes,
[436]157    // and recreate a new KSH[i] process when required.
[427]158    while( 1 )
159    {
[435]160        // block on child processes termination
[436]161        rcv_pid = wait( &status );
[427]162
[435]163        if( WIFSTOPPED( status ) )                         // stopped => unblock it
164        {
165            // display string to report unexpected KSH process block
[623]166            snprintf( string , 64 , "[init] KSH process %x stopped => unblock it" , rcv_pid );
[435]167            display_string( string ); 
168
[440]169            // TODO : unblock KSH [AG]
[435]170
[436]171        }  // end KSH stopped handling
172
[435]173        if( WIFSIGNALED( status ) || WIFEXITED( status ) )  // killed => recreate it
174        {
[437]175            // display string to report KSH process termination
[623]176            snprintf( string , 64 , "[init] KSH process %x terminated => recreate", rcv_pid );
[435]177            display_string( string ); 
[436]178
179            // INIT process fork a new CHILD process
180            ret_fork = fork();
181
182            if( ret_fork < 0 )                          // error in fork
183            {
[437]184                // INIT display error message
[623]185                snprintf( string , 64 , "[init ERROR] cannot fork child => suicide");
[436]186                display_string( string );
187
188                // INIT suicide
189                exit( 0 );
190            }
191            else if( ret_fork == 0 )                    // we are in CHILD process
192            {
193                // CHILD process exec process KSH
[444]194                ret_exec = execve( "/bin/user/ksh.elf" , NULL , NULL ); 
[436]195
196                if ( ret_exec )   // error in exec             
197                {
198                    // CHILD display error message on TXT0 terminal
[623]199                    snprintf( string , 64 , "[init ERROR] CHILD cannot exec KSH" );
[436]200                    display_string( string );
201                }
202            }
203            else                                       // we are in INIT process
204            {
[442]205                // INIT display new KSH process PID
[623]206                snprintf( string , 64 , "[init] re-created KSH / pid = %x", ret_fork ); 
[436]207                display_string( string );
208            }
[438]209        } // end KSH kill handling
[427]210
[438]211    }  // end while waiting KSH[i] termination
212
[427]213} // end main()
214
Note: See TracBrowser for help on using the repository browser.