Index: trunk/kernel/syscalls/sys_mkfifo.c
===================================================================
--- trunk/kernel/syscalls/sys_mkfifo.c	(revision 637)
+++ trunk/kernel/syscalls/sys_mkfifo.c	(revision 670)
@@ -2,5 +2,5 @@
  * sys_mkfifo.c - creates a named FIFO file.
  *
- * Author    Alain Greiner (2016,2017,2018,2019)
+ * Author    Alain Greiner (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -31,12 +31,15 @@
 ////////////////////////////////////
 int sys_mkfifo ( char    * pathname,
-                 uint32_t  mode __attribute__((unused)) )
+                 uint32_t  mode )
 {
-    char           kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
+    vseg_t      * vseg;
+    error_t       error;
+    xptr_t        root_inode_xp;           
+    char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
 
-    thread_t  * this    = CURRENT_THREAD;
-    process_t * process = this->process;
+    thread_t    * this    = CURRENT_THREAD;
+    process_t   * process = this->process;
 
-#if (DEBUG_SYS_MKFIFO || CONFIG_INSTRUMENTATION_SYSCALLS)
+#if DEBUG_SYS_MKFIFO || DEBUG_SYSCALLS_ERROR || CONFIG_INSTRUMENTATION_SYSCALLS
 uint64_t     tm_start = hal_get_cycles();
 #endif
@@ -45,18 +48,19 @@
 if( DEBUG_SYS_MKFIFO < tm_end )
 printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, pathname, (uint32_t)tm_end );
+__FUNCTION__, process->pid, this->trdid, pathname, (uint32_t)tm_start );
 #endif
  
-    // check fd_array not full
-    if( process_fd_array_full() )
-    {
+    // check pathname in user space
+    if( vmm_get_vseg( process, (intptr_t)pathname , &vseg ) )
+	{
 
 #if DEBUG_SYSCALLS_ERROR
-printk("\n[ERROR] in %s : file descriptor array full for process %x\n",
-__FUNCTION__ , process->pid );
+if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
+printk("\n[ERROR] in %s : user buffer unmapped %x for thread[%x,%x]\n",
+__FUNCTION__ , (intptr_t)pathname , process->pid, this->trdid );
 #endif
-        this->errno = ENFILE;
+		this->errno = EINVAL;
         return -1;
-    }
+	}
 
     // check pathname length
@@ -65,5 +69,7 @@
 
 #if DEBUG_SYSCALLS_ERROR
-printk("\n[ERROR] in %s : pathname too long\n", __FUNCTION__ );
+if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
+printk("\n[ERROR] in %s : pathname too long for thread[%x,%x]\n",
+__FUNCTION__ , process->pid , this->trdid );
 #endif
         this->errno = ENFILE;
@@ -76,6 +82,42 @@
                             CONFIG_VFS_MAX_PATH_LENGTH );
 
-    printk("\n[ERROR] in %s : not implemented yet\n", __FUNCTION__ );
-    return -1;
+#if DEBUG_SYS_MKFIFO
+if( DEBUG_SYS_MKFIFO < tm_end )
+printk("\n[%s] thread[%x,%x] enter for <%s> / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, kbuf, (uint32_t)tm_start );
+#endif
+ 
+    // get cluster and local pointer on reference process
+    xptr_t      ref_xp  = process->ref_xp;
+    process_t * ref_ptr = GET_PTR( ref_xp );
+    cxy_t       ref_cxy = GET_CXY( ref_xp );
+
+    // get extended pointer on root inode in path
+    if( kbuf[0] == '/' )                            // absolute path
+    {
+        // use extended pointer on VFS root inode
+        root_inode_xp = process->vfs_root_xp;
+    }
+    else                                            // relative path
+    {
+        // use extended pointer on CWD inode
+        root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
+    }
+
+    // call the relevant VFS function
+    error = vfs_mkfifo( root_inode_xp,
+                        kbuf,
+                        mode ); 
+    if( error )
+    {
+
+#if DEBUG_SYSCALLS_ERROR
+if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
+printk("\n[ERROR] in %s : thread[%x,%x] cannot create node in VFS for <%s> path\n",
+__FUNCTION__ , process->pid , this->trdid , kbuf );
+#endif
+        this->errno = ENFILE;
+        return -1;
+    }
 
 #if (DEBUG_SYS_MKFIFO || CONFIG_INSTRUMENTATION_SYSCALLS)
@@ -94,3 +136,5 @@
 #endif
 
+    return 0;
+
 } // end sys_mkfifo()
