Changeset 469 for trunk/user/ksh


Ignore:
Timestamp:
Aug 20, 2018, 1:04:16 PM (6 years ago)
Author:
alain
Message:

1) Introduce the libsemaphore library.
2) Introduce a small libmath library, required by the "fft" application..
3) Introduce the multithreaded "fft" application.
4) Fix a bad synchronisation bug in the Copy-On-Write mechanism.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/user/ksh/ksh.c

    r459 r469  
    1 ///////////////////////////////////////////////////////////////////////////////
     1/////////////////////////////////////////////////////////////////////////////////////////
    22// File   :  ksh.c
    33// Date   :  October 2017
    44// Author :  Alain Greiner
    5 ///////////////////////////////////////////////////////////////////////////////
     5/////////////////////////////////////////////////////////////////////////////////////////
    66// This application implements a minimal shell for ALMOS-MKH.
    77//
    88// This user KSH process contains two POSIX threads:
    99// - the "main" thread contains the infinite loop implementing
    10 //   the children processes termination monitoring using the wait syscall.
    11 // - the "interactive" thread contains the infinite loop implementing
    12 //   the command interpreter attached to the TXT terminal.
    13 //   This "interactive" thread block and deschedules when the KSH process
    14 //   loses the TXT terminal ownership. It is reactivated when the KSH
    15 //   process returns in background.
     10//   the children processes termination monitoring, using the wait syscall.
     11// - the "interactive" thread contains the infinite loop implementing the command
     12//   interpreter attached to the TXT terminal, and handling one KSH command
     13//   per iteration.
    1614//
    17 // Note: the children processes are created by the <load> command, and are
     15// The children processes are created by the <load> command, and are
    1816// attached to the same TXT terminal as the KSH process itself.
    19 // . A child process can be lauched in foreground: the KSH process loses
    20 //   the TXT terminal ownership, that is transfered to the new process.
    21 // . A child process can be lauched in background: the KSH process keeps
    22 //   the TXT terminal ownership. that is transfered to the new process.
    23 ///////////////////////////////////////////////////////////////////////////////
     17// A child process can be lauched in foreground or in background:
     18// . when the child process is running in foreground, the KSH process loses
     19//   the TXT terminal ownership, that is transfered to the child process.
     20// . when the child process is running in background: the KSH process keeps
     21//   the TXT terminal ownership.
     22//
     23// A semaphore is used to synchronize the two KSH threads. At each iteration,
     24// the interactive thread check the semaphore (with a sem_wait). It blocks
     25// and deschedules, if the KSH process loosed the TXT ownership (after a load,
     26// or for any other cause. It unblocks with the following policy:
     27// . if the command is "not a load", the semaphore is incremented by the
     28//   cmd_***() function when the command is completed, to allow the KSH interactive()
     29//   function to get the next command in the while loop.   
     30// . if the command is a "load without &", the TXT is given to the NEW process by the
     31//   execve() syscall, and is released to the KSH process when NEW process terminates.
     32//   The KSH process is notified and the KSH main() function increments the semahore
     33//   to allow the KSH interactive() function to handle commands.
     34// . if the command is a "load with &", the cmd_load() function returns the TXT
     35//   to the KSH process and increment the semaphore, when the parent KSH process
     36//   returns from the fork() syscall.
     37/////////////////////////////////////////////////////////////////////////////////////////
    2438
    2539#include <stdio.h>
     
    3751#define FIFO_SIZE      (1024)   // FIFO depth for recursive ls
    3852
    39 #define KSH_DEBUG      0
    40 
    41 ////////////////////////////////////////////////////////////////////////////////
     53#define KSH_DEBUG           0
     54#define CMD_LOAD_DEBUG      0
     55
     56//////////////////////////////////////////////////////////////////////////////////////////
    4257//         Structures
    43 ////////////////////////////////////////////////////////////////////////////////
     58//////////////////////////////////////////////////////////////////////////////////////////
    4459
    4560// one entry in the registered commands array
     
    6176
    6277
    63 ////////////////////////////////////////////////////////////////////////////////
     78//////////////////////////////////////////////////////////////////////////////////////////
    6479//         Global Variables
    65 ////////////////////////////////////////////////////////////////////////////////
     80//////////////////////////////////////////////////////////////////////////////////////////
    6681
    6782ksh_cmd_t       cmd[];                    // array of supported commands
     
    7691sem_t           semaphore;                // block interactive thread when zero
    7792
    78 ////////////////////////////////////////////////////////////////////////////////
     93//////////////////////////////////////////////////////////////////////////////////////////
    7994//         Shell  Commands
    80 ////////////////////////////////////////////////////////////////////////////////
     95//////////////////////////////////////////////////////////////////////////////////////////
    8196
    8297/////////////////////////////////////////////
     
    454469        if( (argc < 2) || (argc > 3) ) 
    455470    {
    456                 printf("  usage: %s pathname [&]\n", argv[0] );
     471                printf("  usage: %s pathname [&] / argc = %d\n", argv[0], argc );  // @@@
    457472                return;
    458473        }
     
    466481    ksh_pid = getpid();
    467482
    468 #if KSH_DEBUG
    469 printf("\n[KSH_DEBUG] in %s : ksh PID %x / path %s / background %d\n",
    470 __FUNCTION__, ksh_pid, argv[1], background );
     483#if CMD_LOAD_DEBUG
     484long long unsigned cycle;
     485get_cycle( &cycle );
     486printf("\n@@@ %s : KSH PID %x before fork / path %s / background %d / cycle %d\n",
     487__FUNCTION__, ksh_pid, argv[1], background, (int)cycle );
    471488#endif
    472489
     
    481498    else if (ret_fork == 0) // it is the CHILD process
    482499    {
     500
     501#if CMD_LOAD_DEBUG
     502get_cycle( &cycle );
     503printf("\n@@@ %s : CHILD_PID %x after fork, before exec / cycle %d\n",
     504__FUNCTION__ , getpid(), (int)cycle );
     505#endif
     506
    483507        // CHILD process exec NEW process
    484508        ret_exec = execve( pathname , NULL , NULL );
     509
     510#if CMD_LOAD_DEBUG
     511get_cycle( &cycle );
     512printf("\n@@@ %s : CHILD_PID %x after exec / ret_exec %d / cycle %d\n",
     513__FUNCTION__ , getpid(), ret_exec, (int)cycle );
     514#endif
    485515
    486516        // this is only executed in case of exec failure
     
    494524    {
    495525
    496 #if KSH_DEBUG
    497 int sem_value;
    498 sem_getvalue( &semaphore , &sem_value );
    499 printf("\n[KSH_DEBUG] in %s : child PID %x / background %d / sem_value %d\n",
    500 ret_fork, background, sem_value  );
     526#if CMD_LOAD_DEBUG
     527get_cycle( &cycle );
     528printf("\n@@@ %s : KSH_PID %x after fork / ret_fork %x / cycle %d\n",
     529__FUNCTION__, getpid(), ret_fork, (int)cycle );
    501530#endif
    502531
    503         if( background )        // child in background =>  KSH keeps TXT ownership
     532        if( background )    // child in background =>  KSH must keep TXT ownership
    504533        {
    505534            // execve() tranfered TXT ownership to child => give it back to KSH
     
    734763// This function analyses one command (with arguments), executes it, and returns.
    735764////////////////////////////////////////////////////////////////////////////////////
    736 static void parse( char * buf )
     765static void __attribute__ ((noinline)) parse( char * buf )
    737766{
    738767        int argc = 0;
     
    758787        }
    759788
     789    // analyse command type
    760790        if (argc > 0)
    761791    {
     
    765795
    766796                // try to match typed command
    767                 for (i = 0; cmd[i].name; i++)
     797                for (i = 0 ; cmd[i].name ; i++)
    768798        {
    769799                        if (strcmp(argv[0], cmd[i].name) == 0)
     
    788818static void interactive()
    789819{
    790         char         c;                                           // read character
    791         char         buf[CMD_MAX_SIZE];           // buffer for one command
    792     unsigned int end_command;             // last character found in a command
    793         unsigned int count;                               // pointer in command buffer
    794         unsigned int i;                                           // index for loops
    795         unsigned int state;                   // escape sequence state
    796 
    797 // @@@
    798 // parse( "load /bin/user/fft.elf" );
    799 // @@@
     820        char           c;                                               // read character
     821        char           buf[CMD_MAX_SIZE];               // buffer for one command
     822    unsigned int   end_command;             // last character found in a command
     823        unsigned int   count;                   // pointer in command buffer
     824        unsigned int   i;                                               // index for loops
     825        unsigned int   state;                   // escape sequence state
     826
     827/* This can be used to remove interactive mode
     828
     829for( i=1 ; 1 ; i += 2)
     830{
     831    if( sem_wait( &semaphore ) )
     832    {
     833        printf("\n[ksh error] cannot found semafore\n" );
     834        exit( 1 );
     835    }
     836    else
     837    {
     838        printf("\n[ksh] %d for sort\n", i );
     839    }
     840    strcpy( buf , "load /bin/user/sort.elf" );
     841    parse( buf );
     842
     843    if( sem_wait( &semaphore ) )
     844    {
     845        printf("\n[ksh error] cannot found semafore\n" );
     846        exit( 1 );
     847    }
     848    else
     849    {
     850        printf("\n[ksh] %d for fft\n", i+1 );
     851    }
     852    strcpy( buf , "load /bin/user/fft.elf" );
     853    parse( buf );
     854}
     855
     856*/
    800857
    801858        enum fsm_states
     
    826883            state = NORMAL;
    827884
    828         // block if the KSH process is not the TXT owner
    829         // - if the command is not a "load"
    830         //   the semaphore must be released by the cmd_***()
    831         // - if the command is a load, it depends on
    832         //   the "background" argument
    833         sem_wait( &semaphore );
     885        // decrement semaphore, and block if the KSH process is not the TXT owner
     886        if ( sem_wait( &semaphore ) )
     887        {
     888            printf("\n[ksh error] cannot found semafore\n" );
     889            exit( 1 );
     890        }
    834891
    835892        // display prompt on a new line
     
    9911048    int          status;          // child process termination status
    9921049    int          child_pid;       // child process identifier
    993     int          parent_pid;      // parent process identifier
    994     pthread_t    trdid;           // kernel allocated index for interactive thread
     1050    int          parent_pid;      // parent process identifier (i.e. this process)
     1051    pthread_t    trdid;           // interactive thread identifier (unused)
    9951052    unsigned int is_owner;        // non-zero if KSH process is TXT owner
    9961053
     
    10051062
    10061063    // initializes the semaphore used to unblock the interactive thread
    1007     sem_init( &semaphore , 0 , 1 );
     1064    if ( sem_init( &semaphore , 0 , 1 ) )
     1065    {
     1066        printf("\n[KSH ERROR] cannot initialize semaphore\n" );
     1067        exit( 1 );
     1068    }
     1069
     1070printf("\n@@@ in KSH %s : &semaphore = %x\n", __FUNCTION__, &semaphore );
    10081071
    10091072    // initialize interactive thread attributes
Note: See TracChangeset for help on using the changeset viewer.