Ignore:
Timestamp:
Nov 19, 2020, 11:45:52 PM (4 years ago)
Author:
alain
Message:

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/syscalls/sys_pipe.c

    r506 r670  
    22 * sys_pipe.c - open a pipe communication channel
    33 *
    4  * Author    Alain Greiner  (2016,1017)
     4 * Author    Alain Greiner  (2016,1017,2018,2019,2020)
    55 *
    66 * Copyright (c)  UPMC Sorbonne Universites
     
    2424#include <hal_kernel_types.h>
    2525#include <vfs.h>
     26#include <hal_uspace.h>
    2627#include <process.h>
    2728#include <thread.h>
    2829#include <printk.h>
     30#include <pipe.h>
    2931
    3032#include <syscalls.h>
    3133
    32 //////////////////////////////////////
    33 int sys_pipe ( uint32_t file_fd[2] )
     34////////////////////////////
     35int sys_pipe ( fdid_t * fd )
    3436{
    35     printk("\n[ERROR] in %d : not implemented yet\n", __FUNCTION__, file_fd );
    36     return ENOSYS;
    37 }
     37    vseg_t       * vseg;
     38    kmem_req_t     req;
     39    pipe_t       * pipe;
     40    vfs_file_t   * file_0;
     41    vfs_file_t   * file_1;
     42    fdid_t         fdid_0;
     43    fdid_t         fdid_1;
     44    error_t        error;
     45
     46    thread_t     * this    = CURRENT_THREAD;
     47    process_t    * process = this->process;
     48
     49#if DEBUG_SYS_PIPE || DEBUG_SYSCALLS_ERROR || CONFIG_INSTRUMENTATION_SYSCALLS
     50uint64_t   tm_start = hal_get_cycles();
     51#endif
     52
     53#if DEBUG_SYS_PIPE
     54if( DEBUG_SYS_PIPE < tm_end )
     55printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
     56__FUNCTION__, process->pid, this->trdid, pathname, (uint32_t)tm_end );
     57#endif
     58
     59    // check user buffer is mapped
     60    if( vmm_get_vseg( process , (intptr_t)fd , &vseg ) )
     61    {
     62
     63#if DEBUG_SYSCALLS_ERROR
     64if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
     65printk("\n[ERROR] in %s : thread[%x,%x] / output user buffer unmapped %x\n",
     66__FUNCTION__ , process->pid, this->trdid, (intptr_t)fd );
     67#endif
     68                this->errno = EINVAL;
     69                return -1;
     70    }
     71
     72    // 1. allocate memory in local cluster for pipe descriptor,
     73    //    remote buf_descriptor, and associated data buffer
     74    pipe = pipe_create( local_cxy,
     75                        CONFIG_PIPE_BUF_SIZE );
     76
     77    if( pipe == NULL )
     78    {
     79
     80#if DEBUG_SYSCALLS_ERROR
     81if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
     82printk("\n[ERROR] in %s : thread[%x,%x] / no memory for pipe\n",
     83__FUNCTION__ , process->pid, this->trdid );
     84#endif
     85        goto error_1;
     86    }
     87
     88    // 2. allocate memory for fd[0] file descriptor in local cluster
     89    // we don't use the vfs_file_create function because there is no inode.
     90        req.type  = KMEM_KCM;
     91        req.order = bits_log2( sizeof(vfs_file_t) );
     92    req.flags = AF_ZERO;
     93        file_0    = kmem_alloc( &req );
     94
     95    if( file_0 == NULL )
     96    {
     97
     98#if DEBUG_SYSCALLS_ERROR
     99if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
     100printk("\n[ERROR] in %s : thread[%x,%x] / no memory for file descriptor\n",
     101__FUNCTION__, process->pid, this->trdid );
     102#endif
     103        goto error_2;
     104    }
     105   
     106    // 3. get fd[0] fdid value and register it in owner process fd_array[]
     107    error = process_fd_register( process->owner_xp,
     108                                 XPTR( local_cxy , file_0 ),
     109                                 &fdid_0 );
     110    if ( error )
     111    {
     112
     113#if DEBUG_SYSCALLS_ERROR
     114if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
     115printk("\n[ERROR] in %s : thread[%x,%x] / cannot register file descriptor \n",
     116__FUNCTION__, process->pid, this->trdid );
     117#endif
     118        goto error_3;
     119    }
     120
     121    // 4. allocate memory for fd[1] file descriptor in local cluster
     122        req.type  = KMEM_KCM;
     123        req.order = bits_log2( sizeof(vfs_file_t) );
     124    req.flags = AF_ZERO;
     125        file_1    = kmem_alloc( &req );
     126
     127    if( file_1 == NULL )
     128    {
     129
     130#if DEBUG_SYSCALLS_ERROR
     131if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
     132printk("\n[ERROR] in %s : thread[%x,%x] / no memory for file descriptor\n",
     133__FUNCTION__, process->pid, this->trdid );
     134#endif
     135        goto error_4;
     136    }
     137
     138    // 5. get fd[1] fdid value and register it in owner process fd_array[]
     139    error = process_fd_register( process->owner_xp,
     140                                 XPTR( local_cxy , file_1 ),
     141                                 &fdid_1 );
     142    if ( error )
     143    {
     144
     145#if DEBUG_SYSCALLS_ERROR
     146if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
     147printk("\n[ERROR] in %s : thread[%x,%x] / cannot register file descriptor \n",
     148__FUNCTION__, process->pid, this->trdid );
     149#endif
     150        goto error_5;
     151    }
     152
     153    // link the two file descriptors to the pipe
     154    file_0->pipe = pipe;
     155    file_1->pipe = pipe;
     156
     157    // copy fdid_0 & fdid_1 values to user buffer
     158    hal_copy_to_uspace( &fd[0] , XPTR( local_cxy , &fdid_0 ) , sizeof(fdid_t) );
     159    hal_copy_to_uspace( &fd[1] , XPTR( local_cxy , &fdid_1 ) , sizeof(fdid_t) );
     160
     161#if (DEBUG_SYS_PIPE || CONFIG_INSTRUMENTATION_SYSCALLS)
     162uint64_t     tm_end = hal_get_cycles();
     163#endif
     164
     165#if DEBUG_SYS_PIPE
     166if( DEBUG_SYS_PIPE < tm_end )
     167printk("\n[%s] thread[%x,%x] exit for <%s> / cycle %d\n",
     168__FUNCTION__, this->process->pid, this->trdid, pathname, (uint32_t)tm_end );
     169#endif
     170 
     171#if CONFIG_INSTRUMENTATION_SYSCALLS
     172hal_atomic_add( &syscalls_cumul_cost[SYS_PIPE] , tm_end - tm_start );
     173hal_atomic_add( &syscalls_occurences[SYS_PIPE] , 1 );
     174#endif
     175
     176    return 0;
     177
     178error_5:    // release memory allocated for fd[1] file descriptor
     179
     180    req.ptr = file_1;
     181    kmem_free( &req );
     182
     183error_4:    // release fdid_0 from fd_array[]
     184
     185    process_fd_remove( process->ref_xp , fdid_0 );
     186
     187error_3:    // release memory allocated for fd[0] file descriptor
     188
     189    req.ptr = file_0;
     190    kmem_free( &req );
     191
     192error_2:    // release memory allocated for the pipe
     193
     194    pipe_destroy( XPTR( local_cxy , pipe ) );
     195
     196error_1:   // set errno and return error
     197
     198    this->errno = ENOMEM;
     199    return -1;
     200
     201}  // end sys_pipe()
Note: See TracChangeset for help on using the changeset viewer.