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

Last change on this file since 688 was 682, checked in by alain, 4 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
Line 
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.
7// It uses the fork/exec syscalls to create N KSH child processes
8// (one child process per user TXT terminal).
9// Then it calls the wait() function to block, and recreate any child KSH process
10// that has been deleted, using a new fork/exec.
11///////////////////////////////////////////////////////////////////////////////////////
12
13#include <unistd.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <pthread.h>
17#include <almosmkh.h>
18#include <hal_macros.h>
19#include <sys/wait.h>
20#include <shared_syscalls.h>
21
22#define DEBUG_PROCESS_INIT    0
23
24////////////////
25int main( void )
26{
27    unsigned int  i;
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
33    unsigned int  cxy;           // target cluster identifier
34
35#if DEBUG_PROCESS_INIT
36display_string("[init] process enters");
37#endif
38
39    // get number of TXT channels and number of clusters
40    hard_config_t config;     
41
42    get_config( &config );
43
44    unsigned int  txt_channels = config.txt_channels;
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;
48
49    // check number of TXT channels
50    if( txt_channels < 2 )
51    {
52        snprintf( string , 64 ,
53        "\n[init ERROR] number of TXT channels must be larger than 1");
54        display_string( string );
55        exit( EXIT_FAILURE );
56    }
57
58    cxy = 0;
59
60    // create the KSH processes (one per user terminal)
61    for( i = 1 ; i <  txt_channels ; i++ )
62    {
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
79        // INIT process fork process CHILD[i]
80        ret_fork = fork();
81
82        if( ret_fork < 0 )   // error in fork
83        {
84            // INIT display error message 
85            snprintf( string , 64 , 
86            "\n[init ERROR] cannot fork child[%d] => suicide" , i );
87            display_string( string );
88
89            // INIT suicide
90            exit( EXIT_FAILURE );
91        }
92        else if( ret_fork == 0 )                    // we are in CHILD[i] process
93        {
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
100            // CHILD[i] process exec process KSH[i]
101            ret_exec = execve( "/bin/user/ksh.elf" , NULL , NULL ); 
102
103            if ( ret_exec )   // error in exec             
104            {
105                // CHILD[i] display error message
106                snprintf( string , 64 , 
107                "\n[init ERROR] CHILD[%d] cannot exec KSH" , i );
108                display_string( string );
109
110                // CHILD[i] suicide
111                exit( EXIT_FAILURE );
112            }
113        }
114        else                                      // we are in INIT process
115        {
116            // INIT display CHILD[i] process PID
117            snprintf( string , 64 ,
118            "[init] (pid 0x1) create ksh[%d] (pid %x)", i , ret_fork ); 
119            display_string( string );
120        }
121    } 
122 
123#if DEBUG_PROCESS_INIT
124{
125    // keep blocked for 2 seconds
126    // to allow all KSH[i] process
127    // to be launched before display
128
129    sleep( 2 );
130
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
135
136    unsigned int  x_size       = config.x_size;
137    unsigned int  y_size       = config.y_size;
138    unsigned int  ncores       = config.ncores;
139
140    // INIT displays processes and threads in all clusters
141    for( x = 0 ; x < x_size ; x++ )
142    {
143        for( y = 0 ; y < y_size ; y++ )
144        {
145            cxy = HAL_CXY_FROM_XY( x , y );
146            display_cluster_processes( cxy , 0 );
147            for( lid = 0 ; lid < ncores ; lid++ )
148            { 
149                display_sched( cxy , lid );
150            }
151        }
152    }
153}
154#endif
155
156    // This loop detects the termination of the KSH[i] processes,
157    // and recreate a new KSH[i] process when required.
158    while( 1 )
159    {
160        // block on child processes termination
161        rcv_pid = wait( &status );
162
163        if( WIFSTOPPED( status ) )                         // stopped => unblock it
164        {
165            // display string to report unexpected KSH process block
166            snprintf( string , 64 , "[init] KSH process %x stopped => unblock it" , rcv_pid );
167            display_string( string ); 
168
169            // TODO : unblock KSH [AG]
170
171        }  // end KSH stopped handling
172
173        if( WIFSIGNALED( status ) || WIFEXITED( status ) )  // killed => recreate it
174        {
175            // display string to report KSH process termination
176            snprintf( string , 64 , "[init] KSH process %x terminated => recreate", rcv_pid );
177            display_string( string ); 
178
179            // INIT process fork a new CHILD process
180            ret_fork = fork();
181
182            if( ret_fork < 0 )                          // error in fork
183            {
184                // INIT display error message
185                snprintf( string , 64 , "[init ERROR] cannot fork child => suicide");
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
194                ret_exec = execve( "/bin/user/ksh.elf" , NULL , NULL ); 
195
196                if ( ret_exec )   // error in exec             
197                {
198                    // CHILD display error message on TXT0 terminal
199                    snprintf( string , 64 , "[init ERROR] CHILD cannot exec KSH" );
200                    display_string( string );
201                }
202            }
203            else                                       // we are in INIT process
204            {
205                // INIT display new KSH process PID
206                snprintf( string , 64 , "[init] re-created KSH / pid = %x", ret_fork ); 
207                display_string( string );
208            }
209        } // end KSH kill handling
210
211    }  // end while waiting KSH[i] termination
212
213} // end main()
214
Note: See TracBrowser for help on using the repository browser.