/*
 * pipe.h - single writer, single reader pipe specification.  
 *
 * Author     Alain Greiner (2016,2017,2018,2019,2020)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */


#ifndef _PIPE_H_
#define _PIPE_H_

#include <hal_kernel_types.h>

/*******************************************************************************************
 * This structure defines a generic, single writer, single reader, inter-processes
 * communication channel, used to implement both the POSIX named fifos, and the POSIX
 * anonymous pipes.
 *
 * It uses the (lower level) remote_buf_t object and access functions, and can be
 * allocated in any cluster, and accessed by threads running in any cluster.
 * The default buffer size is defined by the CONFIG_PIPE_BUF_SIZE parameter.
 * It it accessed by the user processes through the POSIX read/write syscalls, that call
 * the pipe_move_user() to move data between the kernel remote buf and the user buffer.
 * These access functions are blocking when the kernel buffer is full (for a write),
 * or empty (for a read), and use a desheduling policy, blocking on THREAD_ BLOCKED_IO. 
 ******************************************************************************************/
 
typedef struct pipe_s
{
    remote_buf_t * buffer;       /*! local pointer on the remote_buf_t                    */
    xptr_t         writer_xp;    /*! extended pointer on the writer thread                */
    xptr_t         reader_xp;    /*! extended pointer on the reader thread                */
}
pipe_t;

/*******************************************************************************************
 * This function allocates memory for the pipe descriptor, for the remote_buf descriptor,
 * and for the associated data buffer, in the cluster defined by the <cxy> argument.
 * The buffer size is defined by the <size> argument. 
 * The "buffer" field is set in the pipe descriptor, but the "writer_xp" and "reader_xp"
 * fields are not set by this function.
 *******************************************************************************************
 * @ cxy        : target cluster identifier.
 * @ size       : data buffer size (in bytes).
 * @ return a local pointer on pipe_t if success /:w NULL if error.
 ******************************************************************************************/
pipe_t * pipe_create( cxy_t     cxy,
                      uint32_t  size );

/*******************************************************************************************
 * This function releases all memory allocated fo a pipe: pipe descriptor,
 * remote_buffer_t descriptor, and associated data buffer.
 *******************************************************************************************
 * @ pipe_xp    : extended pointer on target pipe.
 ******************************************************************************************/
void pipe_destroy( xptr_t pipe_xp );

/*******************************************************************************************
 * These two functions update the "writer_xp" or "reader_xp" field in the pipe descriptor.
 * They are called when the user process open a file descriptor to access the pipe.
 *******************************************************************************************
 * @ pipe_xp    : extended pointer on the target thread
 * @ thread_xp  : extended pointer on the client (writer/reader) thread.
 ******************************************************************************************/
void pipe_register_writer( xptr_t pipe_xp,
                           xptr_t thread_xp );

void pipe_register_reader( xptr_t pipe_xp,
                           xptr_t thread_xp );

/*******************************************************************************************
 * This blocking function is called by the sys_read() and sys_write() functions.
 * It moves up to <size> bytes between an user buffer, defined by the <u_buf> argument,
 * and the kernel pipe, identified by the <file_xp> argument.
 * The file descriptor is always located in the same cluster as the pipe descriptor. 
 * The read/write direction is defined by the <to_buffer> argument. 
 * It returns the number of bytes actually moved.
 * It uses a desheduling policy, blocking on THREAD_ BLOCKED_IO. 
 *******************************************************************************************
 * @ to_buffer : pipe -> buffer if true / buffer -> pipe if false. 
 * @ file_xp   : extended pointer on the remote file descriptor.
 * @ u_buf     : user space buffer (virtual address).
 * @ size      : requested number of bytes to move.
 * @ return number of bytes actually moved if success / -1 if error.
 ******************************************************************************************/
int pipe_user_move( bool_t   to_buffer,
                    xptr_t   file_xp,
                    void   * u_buf,
                    uint32_t size );


#endif	/* _PIPE_H_ */
