Proposed patch to newlib

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Proposed patch to newlib

Post by raf »

As I worked on porting both retawq (web browser) and now links2, I made some changes to newlib (mainly to the libc/sys/psp directory).

Changes include:
-File descriptor management: all file descriptors now come from a common pool. Things like the internal sce descriptor, reference count, filename, flags and descriptor type are kept track of here. This allows for things like: pipe(), socket() and open() to return three consecutive descriptors if called in order. This behavior is required for some applications, furthemore select() is expected to poll file descriptors smaller than FD_SETSIZE which is 256, and this was impossible using the native descriptors.
It also allows some of the code to be simplified, like no more socket file desctiptor masking, or TTY's filename indicator.. etc. And also for adding pipe support, which was my main goal, as both this applications, and I'm sure more, use pipes for thread synchronization/communication.
One thing that needs to be done here is add a locking mechanism to the "get new desciptor" call, to make it thread safe. ATM, is as safe as malloc(), I guess.
-Pipe support: the pipe(..) function, and read/write.
-fcntl support: the function is now implemented, and allows to set and get file descriptor flags. Implementation is not 100% complete. But socket's can be set to non-blocking mode via a fcntl call now. Also, file descriptors can be duplicated (with ref-counting so the real close is only called on the last fd's close). -- Now dup
-socket code simplified a bit thanks to the descriptor management. select() implementation removed, as it only worked with sockets.
-new select() implementation: this implementation is far from perfect, as it manually polls file descriptors internally. Timeout setting is accurate to the millisecond. And it supports pipes and sockets. Support for files is yet to be completed (not sure how to implement it yet).

It works fine for me right now. Compiled against PSPRadio, retawq and links. But I kindly ask for your review before I commit to subversion.

svn diff patch follows for your review:

Code: Select all

Index: libc/sys/psp/pspcwd.c
===================================================================
--- libc/sys/psp/pspcwd.c	(revision 1866)
+++ libc/sys/psp/pspcwd.c	(working copy)
@@ -19,7 +19,6 @@
 #include <pspiofilemgr.h>
 
 char __psp_cwd&#91;MAXPATHLEN + 1&#93; = &#123; 0 &#125;;
-char * __psp_filename_map&#91;1024&#93;;
 
 /* Set the current working directory &#40;CWD&#41; to the path where the module was launched. */
 void __psp_init_cwd&#40;char *argv_0&#41;
Index&#58; libc/sys/psp/Makefile.in
===================================================================
--- libc/sys/psp/Makefile.in	&#40;revision 1866&#41;
+++ libc/sys/psp/Makefile.in	&#40;working copy&#41;
@@ -92,19 +92,26 @@
 
 noinst_LIBRARIES = lib.a
 
-LIBCGLUE_MULT_OBJS = _close.o _exit.o _fork.o _fstat.o _getpid.o	                     _gettimeofday.o _kill.o _lseek.o _open.o _read.o	                     _sbrk.o _wait.o _write.o clock.o isatty.o time.o	                     _link.o _unlink.o sleep.o opendir.o readdir.o	                     closedir.o getcwd.o chdir.o mkdir.o rmdir.o	                     realpath.o _stat.o truncate.o access.o tzset.o	                     __psp_set_errno.o mlock.o
+LIBCGLUE_MULT_OBJS = _close.o _exit.o _fork.o _fstat.o _getpid.o	                     _gettimeofday.o _kill.o _lseek.o _open.o _read.o	                     _sbrk.o _wait.o _write.o clock.o isatty.o time.o	                     _link.o _unlink.o sleep.o opendir.o readdir.o	                     closedir.o getcwd.o chdir.o mkdir.o rmdir.o	                     realpath.o _stat.o truncate.o access.o tzset.o	                     __psp_set_errno.o mlock.o _fcntl.o
 
 
-SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o 				   listen.o recv.o recvfrom.o send.o sendto.o 				   setsockopt.o shutdown.o __psp_socket_map.o 				   getsockname.o getpeername.o select.o inet_ntoa.o
+SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o 				   listen.o recv.o recvfrom.o send.o sendto.o 				   setsockopt.o shutdown.o getsockname.o getpeername.o 				   inet_ntoa.o
 
 
+PIPE_OBJS = pipe.o 
+
+FDMAN_OBJS = fdman.o
+
+SELECT_OBJS = select.o
+
 XPRINTF_MULT_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o _sprintf_r.o
 
 NETDB_MULT_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
 
-lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c
-lib_a_LIBADD = $&#40;LIBCGLUE_MULT_OBJS&#41; $&#40;SOCKET_MULT_OBJS&#41; $&#40;XPRINTF_MULT_OBJS&#41; $&#40;NETDB_MULT_OBJS&#41;
+lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c pipe.c fdman.c select.c
+lib_a_LIBADD = $&#40;LIBCGLUE_MULT_OBJS&#41; $&#40;SOCKET_MULT_OBJS&#41; $&#40;XPRINTF_MULT_OBJS&#41; 				$&#40;NETDB_MULT_OBJS&#41; $&#40;PIPE_OBJS&#41; $&#40;FDMAN_OBJS&#41; $&#40;SELECT_OBJS&#41;
 
+
 ACLOCAL_AMFLAGS = -I ../../..
 CONFIG_STATUS_DEPENDENCIES = $&#40;newlib_basedir&#41;/configure.host
 ACLOCAL_M4 = $&#40;top_srcdir&#41;/aclocal.m4
@@ -120,15 +127,16 @@
 _gettimeofday.o _kill.o _lseek.o _open.o _read.o _sbrk.o _wait.o \
 _write.o clock.o isatty.o time.o _link.o _unlink.o sleep.o opendir.o \
 readdir.o closedir.o getcwd.o chdir.o mkdir.o rmdir.o realpath.o \
-_stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o socket.o \
-accept.o bind.o connect.o getsockopt.o listen.o recv.o recvfrom.o \
-send.o sendto.o setsockopt.o shutdown.o __psp_socket_map.o \
-getsockname.o getpeername.o select.o inet_ntoa.o vxprintf.o _xprintf.o \
-__sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o \
-vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o \
-printf.o vprintf.o _sprintf_r.o h_errno.o gethostbyaddr.o \
-gethostbyname.o
-lib_a_OBJECTS =  libcglue.o socket.o pspcwd.o xprintf.o netdb.o
+_stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o _fcntl.o \
+socket.o accept.o bind.o connect.o getsockopt.o listen.o recv.o \
+recvfrom.o send.o sendto.o setsockopt.o shutdown.o getsockname.o \
+getpeername.o inet_ntoa.o vxprintf.o _xprintf.o __sout.o vsnprintf.o \
+snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o \
+asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o \
+_sprintf_r.o h_errno.o gethostbyaddr.o gethostbyname.o pipe.o fdman.o \
+select.o
+lib_a_OBJECTS =  libcglue.o socket.o pspcwd.o xprintf.o netdb.o pipe.o \
+fdman.o select.o
 CFLAGS = @CFLAGS@
 COMPILE = $&#40;CC&#41; $&#40;DEFS&#41; $&#40;INCLUDES&#41; $&#40;AM_CPPFLAGS&#41; $&#40;CPPFLAGS&#41; $&#40;AM_CFLAGS&#41; $&#40;CFLAGS&#41;
 CCLD = $&#40;CC&#41;
@@ -215,7 +223,7 @@
 	  awk '    &#123; files&#91;$$0&#93; = 1; &#125; \
 	       END &#123; for &#40;i in files&#41; print i; &#125;'`; \
 	test -z "$&#40;ETAGS_ARGS&#41;$$unique$&#40;LISP&#41;$$tags" \
-	  || &#40;cd $&#40;srcdir&#41; && etags -o $$here/TAGS $&#40;ETAGS_ARGS&#41; $$tags  $$unique $&#40;LISP&#41;&#41;
+	  || &#40;cd $&#40;srcdir&#41; && etags $&#40;ETAGS_ARGS&#41; $$tags  $$unique $&#40;LISP&#41; -o $$here/TAGS&#41;
 
 mostlyclean-tags&#58;
 
@@ -362,6 +370,15 @@
 $&#40;NETDB_MULT_OBJS&#41;&#58; netdb.c
 	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
 
+$&#40;PIPE_OBJS&#41;&#58; pipe.c
+	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
+
+$&#40;FDMAN_OBJS&#41;&#58; fdman.c
+	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
+
+$&#40;SELECT_OBJS&#41;&#58; select.c
+	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
+
 # Tell versions &#91;3.59,3.63&#41; of GNU make to not export all variables.
 # Otherwise a system limit &#40;for SysV at least&#41; may be exceeded.
 .NOEXPORT&#58;
Index&#58; libc/sys/psp/select.c
===================================================================
--- libc/sys/psp/select.c	&#40;revision 0&#41;
+++ libc/sys/psp/select.c	&#40;revision 0&#41;
@@ -0,0 +1,172 @@
+/*
+ * PSP Software Development Kit - http&#58;//www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright &#40;c&#41; 2006 Rafael Cabezas <rafpsp@gmail.com>
+ * 
+ */
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <psptypes.h>
+#include <pspthreadman.h>
+
+#include "fdman.h"
+
+#define SELECT_POLLING_DELAY_IN_us	100
+
+static int __psp_poll_select&#40;int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds&#41;;
+
+int	select&#40;int n, fd_set *readfds, fd_set *writefds,
+		   fd_set *exceptfds, struct timeval *timeout&#41;
+&#123;
+	int count;
+	clock_t start_time, time;
+	
+	start_time = clock&#40;&#41;;
+
+	count = 0;
+	
+	if &#40;timeout&#41; &#123;
+		time = &#40;timeout->tv_sec * CLOCKS_PER_SEC&#41; + &#40;timeout->tv_usec * &#40;1*1000*1000/CLOCKS_PER_SEC&#41;&#41;;
+	&#125; 
+	else &#123;
+		time = 0; 
+	&#125;
+	
+	for &#40;;;&#41; &#123;
+		count = __psp_poll_select&#40;n, readfds, writefds, exceptfds&#41;;
+		/* If timeout == NULL, then don't timeout! */
+		if &#40; &#40;count > 0&#41; || &#40;&#40;timeout != NULL&#41; && &#40;&#40;clock&#40;&#41; - start_time&#41; >= time&#41;&#41; &#41; &#123;
+			break;
+		&#125;
+		else &#123;
+			/* Nothing found, and not timed-out yet; let's yield for SELECT_POLLING_DELAY_IN_us, so we're not in a busy loop */
+			sceKernelDelayThread&#40;SELECT_POLLING_DELAY_IN_us&#41;;
+		&#125; 
+	&#125;
+	
+	return count;
+&#125;
+
+#define SCE_FD_SET&#40;n, p&#41; \
+	&#40;&#40;p&#41;->fds_bits&#91;&#40;&#40;n&#41; & 0xFF&#41; /__NFDBITS&#93; |= &#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+
+static int __psp_poll_select&#40;int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds&#41;
+&#123;
+	int fd, count;
+	fd_set ready_readfds, ready_writefds, ready_exceptfds;
+	fd_set scereadfds, scewritefds, sceexceptfds;
+	SceKernelMppInfo info;
+	struct timeval scetv;
+
+	FD_ZERO&#40;&ready_readfds&#41;;
+	FD_ZERO&#40;&ready_writefds&#41;;
+	FD_ZERO&#40;&ready_exceptfds&#41;;
+
+	info.size = sizeof&#40;info&#41;;
+	scetv.tv_sec = 0;
+	scetv.tv_usec = 0;
+	count = 0;
+
+	for &#40;fd = 0; fd < n; fd++&#41;
+	&#123;
+		if &#40;__psp_descriptormap&#91;fd&#93; != NULL&#41; &#123;
+			switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+			&#123;
+				case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+					if &#40;readfds && FD_ISSET&#40;fd, readfds&#41;&#41; &#123;
+						if &#40;sceKernelReferMsgPipeStatus&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, &info&#41; == 0&#41; &#123;
+							if &#40;info.bufSize != info.freeSize&#41; &#123;
+								FD_SET&#40;fd, &ready_readfds&#41;;
+								count++;
+							&#125;
+						&#125;
+						else &#123;
+							FD_SET&#40;fd, &ready_exceptfds&#41;;
+							count++;
+						&#125;
+					&#125;
+					if &#40;writefds && FD_ISSET&#40;fd, writefds&#41;&#41; &#123;
+						if &#40;sceKernelReferMsgPipeStatus&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, &info&#41; == 0&#41; &#123;
+							if &#40;info.freeSize > 0&#41; &#123;
+								FD_SET&#40;fd, &ready_writefds&#41;;
+								count++;
+							&#125;
+						&#125;
+						else &#123;
+							FD_SET&#40;fd, &ready_exceptfds&#41;;
+							count++;
+						&#125;
+					&#125;
+					break;
+				case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+					if &#40;readfds && FD_ISSET&#40;fd, readfds&#41;&#41; &#123;
+						if &#40;readfds && FD_ISSET&#40;fd, readfds&#41;&#41; &#123;
+							/** Just set it for now */
+							FD_SET&#40;fd, &ready_readfds&#41;;
+							count++;
+						&#125;
+					&#125; 
+					break;
+				case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+					if &#40;readfds && FD_ISSET&#40;fd, readfds&#41;&#41; &#123;
+						int sce_ret, sce_fd;
+						sce_fd = __psp_descriptormap&#91;fd&#93;->sce_descriptor;
+						FD_ZERO&#40;&scereadfds&#41;;
+						SCE_FD_SET&#40;sce_fd, &scereadfds&#41;;
+						errno = 0;
+						sce_ret = sceNetInetSelect &#40;sce_fd+1, &scereadfds, NULL, NULL, &scetv&#41;;
+						if &#40;sce_ret>0&#41; &#123;
+							FD_SET&#40;fd, &ready_readfds&#41;;
+							count++;
+						&#125;
+						else if &#40;sce_ret == -1&#41; &#123;
+							errno = sceNetInetGetErrno&#40;&#41;;
+							if &#40;exceptfds && FD_ISSET&#40;fd, exceptfds&#41;&#41; &#123;
+								FD_SET&#40;fd, &ready_exceptfds&#41;;
+								count++;
+							&#125; else &#123;
+								count = -1;
+							&#125;
+						&#125;
+					&#125;
+					if &#40;writefds && FD_ISSET&#40;fd, writefds&#41;&#41; &#123;
+						int sce_ret;
+						FD_ZERO&#40;&scewritefds&#41;;
+						SCE_FD_SET&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, &scewritefds&#41;;
+						sce_ret = sceNetInetSelect &#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor+1, NULL, &scewritefds, NULL, &scetv&#41;;
+						if &#40;sce_ret>0&#41; &#123;
+							FD_SET&#40;fd, &ready_writefds&#41;;
+							count++;
+						&#125;
+						else if &#40;sce_ret == -1&#41; &#123;
+							if &#40;exceptfds && FD_ISSET&#40;fd, exceptfds&#41;&#41; &#123;
+								FD_SET&#40;fd, &ready_exceptfds&#41;;
+								count++;
+							&#125; 
+							else &#123;
+								count = -1;
+							&#125;
+						&#125;
+					&#125;
+					break;
+			&#125;
+		&#125;
+	&#125;
+
+	if &#40;count > 0&#41; &#123;
+		if &#40;readfds&#41;
+			*readfds   = ready_readfds;
+		if &#40;writefds&#41;
+			*writefds  = ready_writefds;
+		if &#40;exceptfds&#41;
+			*exceptfds = ready_exceptfds;
+	&#125;
+
+	return count;
+&#125;
+

Property changes on&#58; libc/sys/psp/select.c
___________________________________________________________________
Name&#58; svn&#58;eol-style
   + native

Index&#58; libc/sys/psp/fdman.c
===================================================================
--- libc/sys/psp/fdman.c	&#40;revision 0&#41;
+++ libc/sys/psp/fdman.c	&#40;revision 0&#41;
@@ -0,0 +1,103 @@
+/*
+ * PSP Software Development Kit - http&#58;//www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * fdman.c - File descriptor management.
+ *
+ * Copyright &#40;c&#41; 2006 Rafael Cabezas <rafpsp@gmail.com>
+ */
+ 
+#include <psptypes.h>
+#include <errno.h>
+#include "fdman.h"
+
+static __psp_descriptormap_type  __psp_descriptor_data_pool&#91;__PSP_FILENO_MAX&#93;;
+__psp_descriptormap_type        *__psp_descriptormap       &#91;__PSP_FILENO_MAX&#93;;
+
+void __psp_fdman_init&#40;&#41;
+&#123;
+	int scefd;
+
+	/* Initialize descriptor data*/
+	memset&#40;__psp_descriptor_data_pool, 0, sizeof&#40;__psp_descriptormap_type&#41; *__PSP_FILENO_MAX&#41;;
+	/* Initialize descriptor map*/
+	memset&#40;__psp_descriptormap,        0, sizeof&#40;__psp_descriptormap_type*&#41;*__PSP_FILENO_MAX&#41;;
+
+	scefd = sceKernelStdin&#40;&#41;;
+	if &#40;&#40;scefd >= 0&#41; && &#40;scefd < __PSP_FILENO_MAX&#41;&#41; &#123;
+		__psp_descriptormap&#91;0&#93; = &__psp_descriptor_data_pool&#91;0&#93;;
+		__psp_descriptormap&#91;0&#93;->sce_descriptor = scefd;
+		__psp_descriptormap&#91;0&#93;->type = __PSP_DESCRIPTOR_TYPE_TTY;
+	&#125;
+	scefd = sceKernelStdout&#40;&#41;;
+	if &#40;&#40;scefd >= 0&#41; && &#40;scefd < __PSP_FILENO_MAX&#41;&#41; &#123;
+		__psp_descriptormap&#91;1&#93; = &__psp_descriptor_data_pool&#91;1&#93;;
+		__psp_descriptormap&#91;1&#93;->sce_descriptor = scefd;
+		__psp_descriptormap&#91;1&#93;->type = __PSP_DESCRIPTOR_TYPE_TTY;
+	&#125;
+	scefd = sceKernelStderr&#40;&#41;;
+	if &#40;&#40;scefd >= 0&#41; && &#40;scefd < __PSP_FILENO_MAX&#41;&#41; &#123;
+		__psp_descriptormap&#91;2&#93; = &__psp_descriptor_data_pool&#91;2&#93;;
+		__psp_descriptormap&#91;2&#93;->sce_descriptor = scefd;
+		__psp_descriptormap&#91;2&#93;->type = __PSP_DESCRIPTOR_TYPE_TTY;
+	&#125;
+&#125;
+
+int __psp_fdman_get_new_descriptor&#40;&#41;
+&#123;
+	int i = 0;
+//lock here
+	for &#40;i = 0; i < __PSP_FILENO_MAX; i++&#41; &#123;
+		if &#40;__psp_descriptormap&#91;i&#93; == NULL&#41; &#123;
+			__psp_descriptormap&#91;i&#93; = &__psp_descriptor_data_pool&#91;i&#93;;
+			__psp_descriptormap&#91;i&#93;->ref_count++;
+			return i;
+		&#125;
+	&#125;
+//unlock here
+	
+	errno = ENOMEM;
+	return -1;
+&#125;
+
+int __psp_fdman_get_dup_descriptor&#40;int fd&#41;
+&#123;
+	int i = 0;
+	
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+
+	//lock here
+	for &#40;i = 0; i < __PSP_FILENO_MAX; i++&#41; &#123;
+		if &#40;__psp_descriptormap&#91;i&#93; == NULL&#41; &#123;
+			__psp_descriptormap&#91;i&#93; = &__psp_descriptor_data_pool&#91;fd&#93;;
+			__psp_descriptormap&#91;i&#93;->ref_count++;
+			return i;
+		&#125;
+	&#125;
+	//unlock here
+	
+	errno = ENOMEM;
+	return -1;
+&#125;
+
+void __psp_fdman_release_descriptor&#40;int fd&#41;
+&#123;
+	__psp_descriptormap&#91;fd&#93;->ref_count--;
+	
+	if &#40;__psp_descriptormap&#91;fd&#93;->ref_count == 0&#41; &#123;
+		
+		if &#40;__psp_descriptormap&#91;fd&#93;->filename != NULL&#41; &#123;
+			free&#40;__psp_descriptormap&#91;fd&#93;->filename&#41;;
+		&#125;
+		__psp_descriptormap&#91;fd&#93;->filename       = NULL;
+		__psp_descriptormap&#91;fd&#93;->sce_descriptor = 0;
+		__psp_descriptormap&#91;fd&#93;->type           = 0;//__PSP_DESCRIPTOR_TYPE_NA;
+		__psp_descriptormap&#91;fd&#93;->flags          = 0;
+		
+	&#125;
+	__psp_descriptormap&#91;fd&#93; = NULL;
+&#125;

Property changes on&#58; libc/sys/psp/fdman.c
___________________________________________________________________
Name&#58; svn&#58;eol-style
   + native

Index&#58; libc/sys/psp/libcglue.c
===================================================================
--- libc/sys/psp/libcglue.c	&#40;revision 1866&#41;
+++ libc/sys/psp/libcglue.c	&#40;working copy&#41;
@@ -35,6 +35,7 @@
 #include <psputility.h>
 #include <pspstdio.h>
 #include <pspintrman.h>
+#include "fdman.h"
 
 extern char __psp_cwd&#91;MAXPATHLEN + 1&#93;;
 extern void __psp_init_cwd&#40;char *argv_0&#41;;
@@ -47,8 +48,12 @@
 extern ssize_t __psp_socket_recv&#40;int s, void *buf, size_t len, int flags&#41; __attribute__&#40;&#40;weak&#41;&#41;;
 extern ssize_t __psp_socket_send&#40;int s, const void *buf, size_t len, int flags&#41; __attribute__&#40;&#40;weak&#41;&#41;;
 
-#define __PSP_FILENO_MAX 1024
-extern char * __psp_filename_map&#91;__PSP_FILENO_MAX&#93;;
+extern int pipe&#40;int fildes&#91;2&#93;&#41;;
+extern int __psp_pipe_close&#40;int filedes&#41;;
+extern int __psp_pipe_nonblocking_read&#40;int fd, void *buf, size_t len&#41;;
+extern int __psp_pipe_read&#40;int fd, void *buf, size_t len&#41;;
+extern int __psp_pipe_write&#40;int fd, const void *buf, size_t size&#41;;
+extern int __psp_pipe_nonblocking_write&#40;int fd, const void *buf, size_t len&#41;;
 
 int __psp_set_errno&#40;int code&#41;;
 
@@ -158,7 +163,7 @@
 #ifdef F__open
 int _open&#40;const char *name, int flags, int mode&#41;
 &#123;
-	int fd;
+	int scefd, fd;
 	int sce_flags;
 	char dest&#91;MAXPATHLEN + 1&#93;;
 
@@ -188,79 +193,166 @@
 		sce_flags |= PSP_O_NBLOCK;
 	&#125;
 	
-	fd = sceIoOpen&#40;dest, sce_flags, mode&#41;;
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		__psp_filename_map&#91;fd&#93; = strdup&#40;dest&#41;;
+	scefd = sceIoOpen&#40;dest, sce_flags, mode&#41;;
+	if &#40;scefd >= 0&#41; &#123;
+		fd = __psp_fdman_get_new_descriptor&#40;&#41;;
+		if &#40;fd != -1&#41; &#123;
+			__psp_descriptormap&#91;fd&#93;->sce_descriptor = scefd;
+			__psp_descriptormap&#91;fd&#93;->type     		= __PSP_DESCRIPTOR_TYPE_FILE;
+			__psp_descriptormap&#91;fd&#93;->flags    		= flags;
+			__psp_descriptormap&#91;fd&#93;->filename 		= strdup&#40;dest&#41;;
+			return fd;
+		&#125;
+		else &#123;
+			sceIoClose&#40;scefd&#41;;
+			errno = ENOMEM;
+			return -1;
+		&#125;
+	&#125; 
+	else &#123;
+		return __psp_set_errno&#40;scefd&#41;;
 	&#125;
-	return __psp_set_errno&#40;fd&#41;;
+	
 &#125;
 #endif
 
 #ifdef F__close
 int _close&#40;int fd&#41;
 &#123;
-	if &#40;fd < 0&#41; &#123;
+	int ret = 0;
+
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	if &#40;SOCKET_IS_VALID&#40;fd&#41; && __psp_socket_close != NULL&#41; &#123;
-		return __psp_socket_close&#40;fd&#41;;
+	switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+	&#123;
+		case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+		case __PSP_DESCRIPTOR_TYPE_TTY&#58;
+			if &#40;__psp_descriptormap&#91;fd&#93;->ref_count == 1&#41; &#123;
+				ret = __psp_set_errno&#40;sceIoClose&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor&#41;&#41;;
+			&#125;
+			__psp_fdman_release_descriptor&#40;fd&#41;;
+			return ret;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+			return __psp_pipe_close&#40;fd&#41;;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+			if &#40;__psp_socket_close != NULL&#41; &#123;
+				ret = __psp_socket_close&#40;fd&#41;;
+				return ret;
+			&#125;
+			break;
+		default&#58;
+			break;
 	&#125;
 
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
-			free&#40;__psp_filename_map&#91;fd&#93;&#41;;
-			__psp_filename_map&#91;fd&#93; = NULL;
-		&#125;
-	&#125;
-
-	return __psp_set_errno&#40;sceIoClose&#40;fd&#41;&#41;;
+	errno = EBADF;
+	return -1;
 &#125;
 #endif
 
 #ifdef F__read
 int _read&#40;int fd, void *buf, size_t size&#41;
 &#123;
-	if &#40;fd < 0&#41; &#123;
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	if &#40;SOCKET_IS_VALID&#40;fd&#41; && __psp_socket_recv != NULL&#41; &#123;
-		return __psp_socket_recv&#40;fd, buf, size, 0&#41;;
+	switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+	&#123;
+		case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+		case __PSP_DESCRIPTOR_TYPE_TTY&#58;
+			return __psp_set_errno&#40;sceIoRead&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, buf, size&#41;&#41;;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+			if &#40;__psp_descriptormap&#91;fd&#93;->flags & O_NONBLOCK&#41; &#123;
+				return __psp_pipe_nonblocking_read&#40;fd, buf, size&#41;;
+			&#125;
+			else &#123;
+				return __psp_pipe_read&#40;fd, buf, size&#41;;
+			&#125;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+			if &#40;__psp_socket_recv != NULL&#41; &#123;
+				return __psp_socket_recv&#40;fd, buf, size, 0&#41;;
+			&#125;
+			break;
+		default&#58;
+			break;
 	&#125;
 
-	return __psp_set_errno&#40;sceIoRead&#40;fd, buf, size&#41;&#41;;
+	errno = EBADF;
+	return -1;
+
 &#125;
 #endif
 
 #ifdef F__write
 int _write&#40;int fd, const void *buf, size_t size&#41;
 &#123;
-	if &#40;fd < 0&#41; &#123;
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	if &#40;SOCKET_IS_VALID&#40;fd&#41; && __psp_socket_send != NULL&#41; &#123;
-		return __psp_socket_send&#40;fd, buf, size, 0&#41;;
+	switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+	&#123;
+		case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+		case __PSP_DESCRIPTOR_TYPE_TTY&#58;
+			return __psp_set_errno&#40;sceIoWrite&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, buf, size&#41;&#41;;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+			if &#40;__psp_descriptormap&#91;fd&#93;->flags & O_NONBLOCK&#41; &#123;
+				return __psp_pipe_nonblocking_write&#40;fd, buf, size&#41;;
+			&#125;
+			else &#123;
+				return __psp_pipe_write&#40;fd, buf, size&#41;;
+			&#125;
+			break;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+			if &#40;__psp_socket_send != NULL&#41; &#123;
+				return __psp_socket_send&#40;fd, buf, size, 0&#41;;
+			&#125;
+			break;
+		default&#58;
+			break;
 	&#125;
 
-	return __psp_set_errno&#40;sceIoWrite&#40;fd, buf, size&#41;&#41;;
+	errno = EBADF;
+	return -1;
 &#125;
 #endif
 
 #ifdef F__lseek
 off_t _lseek&#40;int fd, off_t offset, int whence&#41;
 &#123;
-	if &#40;fd < 0&#41; &#123;
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	/* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
-	return &#40;off_t&#41; __psp_set_errno&#40;sceIoLseek&#40;fd, offset, whence&#41;&#41;;
+	switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+	&#123;
+		case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+			/* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
+			return &#40;off_t&#41; __psp_set_errno&#40;sceIoLseek&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, offset, whence&#41;&#41;;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+			break;
+		default&#58;
+			break;
+	&#125;
+
+	errno = EBADF;
+	return -1;
+
 &#125;
 #endif
 
@@ -466,26 +558,37 @@
 &#123;
 	int ret;
 	SceOff oldpos;
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
-			if &#40;strcmp&#40;__psp_filename_map&#91;fd&#93;, "  __PSP_STDIO"&#41; == 0&#41; &#123;
-				memset&#40;sbuf, '\0', sizeof&#40;struct stat&#41;&#41;;
-				sbuf->st_mode = S_IFCHR;
-				return 0;
-			&#125; else &#123;
-				ret = stat&#40;__psp_filename_map&#91;fd&#93;, sbuf&#41;;
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+
+	switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+	&#123;
+		case __PSP_DESCRIPTOR_TYPE_TTY&#58;
+			memset&#40;sbuf, '\0', sizeof&#40;struct stat&#41;&#41;;
+			sbuf->st_mode = S_IFCHR;
+			return 0;
+			break;		
+		case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+			if &#40;__psp_descriptormap&#91;fd&#93;->filename != NULL&#41; &#123;
+				ret = stat&#40;__psp_descriptormap&#91;fd&#93;->filename, sbuf&#41;;
 				
 				/* Find true size of the open file */
-				oldpos = sceIoLseek&#40;fd, 0, SEEK_CUR&#41;;
+				oldpos = sceIoLseek&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, 0, SEEK_CUR&#41;;
 				if &#40;oldpos != &#40;off_t&#41; -1&#41; &#123;
-					sbuf->st_size = &#40;off_t&#41; sceIoLseek&#40;fd, 0, SEEK_END&#41;;
-					sceIoLseek&#40;fd, oldpos, SEEK_SET&#41;;
+					sbuf->st_size = &#40;off_t&#41; sceIoLseek&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, 0, SEEK_END&#41;;
+					sceIoLseek&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, oldpos, SEEK_SET&#41;;
 				&#125;
-
 				return ret;
 			&#125;
-		&#125;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+		default&#58;
+			break;
 	&#125;
+
 	errno = EBADF;
 	return -1;
 &#125;
@@ -494,16 +597,17 @@
 #ifdef F_isatty
 int isatty&#40;int fd&#41;
 &#123;
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
-			if &#40;strcmp&#40;__psp_filename_map&#91;fd&#93;, "  __PSP_STDIO"&#41; == 0&#41; &#123;
-				return 1;
-			&#125; else &#123;
-				return 0;
-			&#125;
-		&#125;
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
+		errno = EBADF;
+		return 0;
 	&#125;
-	return 0;
+
+	if &#40;__psp_descriptormap&#91;fd&#93;->type == __PSP_DESCRIPTOR_TYPE_TTY&#41; &#123;
+		return 1;
+	&#125;
+	else &#123;
+		return 0;
+	&#125;
 &#125;
 #endif
 
@@ -627,6 +731,68 @@
 &#125;
 #endif
 
+#ifdef F__fcntl
+int _fcntl&#40;int fd, int cmd, ...&#41;
+&#123;
+	if &#40;fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93; == NULL&#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+
+	switch &#40;cmd&#41;
+	&#123;
+		case F_DUPFD&#58;
+		&#123;
+			return __psp_fdman_get_dup_descriptor&#40;fd&#41;;
+			break;
+		&#125;
+		case F_GETFL&#58;
+		&#123;
+			return __psp_descriptormap&#91;fd&#93;->flags;
+			break;
+		&#125;
+		case F_SETFL&#58;
+		&#123;
+			int newfl;
+			va_list args;
+	
+			va_start &#40;args, cmd&#41;;         /* Initialize the argument list. */
+			newfl =  va_arg&#40;args, int&#41;;
+			va_end &#40;args&#41;;                /* Clean up. */
+
+			__psp_descriptormap&#91;fd&#93;->flags = newfl;
+
+			switch&#40;__psp_descriptormap&#91;fd&#93;->type&#41;
+			&#123;
+				case __PSP_DESCRIPTOR_TYPE_FILE&#58;
+					break;
+				case __PSP_DESCRIPTOR_TYPE_PIPE&#58;
+					break;
+				case __PSP_DESCRIPTOR_TYPE_SOCKET&#58;
+					if &#40;newfl & O_NONBLOCK&#41;
+					&#123;
+						int one = 1;
+						return setsockopt&#40;fd, SOL_SOCKET, SO_NONBLOCK, &#40;char *&#41;&one, sizeof&#40;one&#41;&#41;;
+					&#125;
+					else
+					&#123;
+						int zero = 0;
+						return setsockopt&#40;fd, SOL_SOCKET, SO_NONBLOCK, &#40;char *&#41;&zero, sizeof&#40;zero&#41;&#41;;
+					&#125;
+					break;
+				default&#58;
+					break;
+			&#125;
+			return 0;
+			break;
+		&#125;
+	&#125;
+
+	errno = EBADF;
+	return -1;
+&#125;
+#endif /* F__fcntl */
+
 #ifdef F_tzset
 void tzset&#40;void&#41;
 &#123;
@@ -717,27 +883,13 @@
 */
 void __psp_libc_init&#40;int argc, char *argv&#91;&#93;&#41;
 &#123;
-	int fd;
 	&#40;void&#41; argc;
 
 	/* Initialize cwd from this program's path */
 	__psp_init_cwd&#40;argv&#91;0&#93;&#41;;
 
-	/* Initialize filenamap */
-	memset&#40;__psp_filename_map, '\0', sizeof&#40;char *&#41; * __PSP_FILENO_MAX&#41;;
-
-	fd = sceKernelStdin&#40;&#41;;
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		 __psp_filename_map&#91;fd&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
-	&#125;
-	fd = sceKernelStdout&#40;&#41;;
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		 __psp_filename_map&#91;fd&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
-	&#125;
-	fd = sceKernelStderr&#40;&#41;;
-	if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
-		 __psp_filename_map&#91;fd&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
-	&#125;
+	/* Initialize filedescriptor management */
+	__psp_fdman_init&#40;&#41;;
 &#125;
 
 #endif /* F__exit */
Index&#58; libc/sys/psp/socket.c
===================================================================
--- libc/sys/psp/socket.c	&#40;revision 1866&#41;
+++ libc/sys/psp/socket.c	&#40;working copy&#41;
@@ -9,6 +9,7 @@
  * Copyright &#40;c&#41; 2005 James Forshaw <tyranid@gmail.com>
  * 
  */
+#include <fcntl.h>
 #include <errno.h>
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -16,57 +17,48 @@
 #include <arpa/inet.h>
 
 #include <psptypes.h>
+#include "fdman.h"
 
-#define __PSP_SOCKET_MAX 1024
-extern char __psp_socket_map&#91;__PSP_SOCKET_MAX&#93;;
-
-#ifdef F___psp_socket_map
-char __psp_socket_map&#91;__PSP_SOCKET_MAX&#93;;
-#endif
-
 #ifdef F_socket
 int	socket&#40;int domain, int type, int protocol&#41;
 &#123;
-	int sock;
+	int sock, scesock;
 	int i;
 
-	sock = sceNetInetSocket&#40;domain, type, protocol&#41;;
-	if&#40;sock < 0&#41;
-	&#123;
+	scesock = sceNetInetSocket&#40;domain, type, protocol&#41;;
+	if&#40;scesock < 0&#41;	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
 		return -1;
 	&#125;
 
-	if&#40;&#40;sock >= 0&#41; && &#40;sock < __PSP_SOCKET_MAX&#41;&#41;
-	&#123;
-		__psp_socket_map&#91;sock&#93; = 1;
+	sock = __psp_fdman_get_new_descriptor&#40;&#41;;
+	if&#40; sock != -1 &#41;	&#123;
+		__psp_descriptormap&#91;sock&#93;->sce_descriptor = scesock;
+		__psp_descriptormap&#91;sock&#93;->type = __PSP_DESCRIPTOR_TYPE_SOCKET;
 	&#125;
-	else
-	&#123;
-		sceNetInetClose&#40;sock&#41;;
+	else &#123;
+		sceNetInetClose&#40;scesock&#41;;
 		errno = ENOENT;
 		return -1;
 	&#125;
 
-	return sock | SOCKET_FD_PAT;
+	return sock;
 &#125;
 
 /* These are glue routines that are called from _close&#40;&#41;, _read&#40;&#41;, and
    _write&#40;&#41;.  They are here so that any program that uses socket&#40;&#41; will pull
    them in and have expanded socket capability. */
 
-int __psp_socket_close&#40;int s&#41;
+int __psp_socket_close&#40;int sock&#41;
 &#123;
-	int ret;
-	int sock;
+	int ret = 0;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-	if&#40;&#40;sock > 0&#41; && &#40;sock < __PSP_SOCKET_MAX&#41;&#41;
-	&#123;
-		__psp_socket_map&#91;sock&#93; = 0;
+	if &#40;__psp_descriptormap&#91;sock&#93;->ref_count == 1&#41; &#123;
+		ret = sceNetInetClose&#40;__psp_descriptormap&#91;sock&#93;->sce_descriptor&#41;;
 	&#125;
 
-	ret = sceNetInetClose&#40;sock&#41;;
+	__psp_fdman_release_descriptor&#40;sock&#41;;
+
 	if&#40;ret < 0&#41;
 	&#123;
 		/* If close is defined likely errno is */
@@ -91,36 +83,32 @@
 #ifdef F_accept
 int	accept&#40;int s, struct sockaddr *addr, socklen_t *addrlen&#41;
 &#123;
-	int sock;
-	int new;
+	int newscesock, newsock;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
-	&#123;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41; &#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
+	newscesock = sceNetInetAccept&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, addr, addrlen&#41;;
+	if&#40; &#40;newscesock >= 0&#41; &#41; &#123;
+		newsock = __psp_fdman_get_new_descriptor&#40;&#41;;
+		if &#40; newsock != -1 &#41; &#123;
+			__psp_descriptormap&#91;newsock&#93;->sce_descriptor = newscesock;
+			__psp_descriptormap&#91;newsock&#93;->type = __PSP_DESCRIPTOR_TYPE_SOCKET;
+		&#125;
+		else &#123;
+			sceNetInetClose&#40;newscesock&#41;;
+			errno = ENOENT;
+			return -1;
+		&#125;
 	&#125;
-
-	new = sceNetInetAccept&#40;sock, addr, addrlen&#41;;
-	if&#40;&#40;new >= 0&#41; && &#40;new < __PSP_SOCKET_MAX&#41;&#41;
-	&#123;
-		__psp_socket_map&#91;new&#93; = 1;
-	&#125;
-	else
-	&#123;
-		sceNetInetClose&#40;new&#41;;
+	else &#123;
 		errno = ENOENT;
 		return -1;
 	&#125;
 
-	return new | SOCKET_FD_PAT;
+	return newsock;
 &#125;
 #endif
 
@@ -128,23 +116,14 @@
 int	bind&#40;int s, const struct sockaddr *my_addr, socklen_t addrlen&#41;
 &#123;
 	int ret;
-	int sock;
 	
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40; __psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET &#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetBind&#40;sock, my_addr, addrlen&#41;;
+	ret = sceNetInetBind&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, my_addr, addrlen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -158,30 +137,21 @@
 #ifdef F_connect
 int	connect&#40;int s, const struct sockaddr *serv_addr, socklen_t addrlen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetConnect&#40;sock, serv_addr, addrlen&#41;;
+	ret = sceNetInetConnect&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, serv_addr, addrlen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
 		return -1;
 	&#125;
-
+	
 	return 0;
 &#125;
 #endif
@@ -189,30 +159,21 @@
 #ifdef F_setsockopt
 int	getsockopt&#40;int s, int level, int optname, void *optval, socklen_t *optlen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetGetsockopt&#40;sock, level, optname, optval, optlen&#41;;
+	ret = sceNetInetGetsockopt&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, level, optname, optval, optlen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
 		return -1;
 	&#125;
-
+	
 	return 0;
 &#125;
 #endif
@@ -220,24 +181,15 @@
 #ifdef F_listen
 int	listen&#40;int s, int backlog&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetListen&#40;sock, backlog&#41;;
+	ret = sceNetInetListen&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, backlog&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -251,24 +203,15 @@
 #ifdef F_recv
 ssize_t	recv&#40;int s, void *buf, size_t len, int flags&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetRecv&#40;sock, buf, len, flags&#41;;
+	ret = sceNetInetRecv&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, buf, len, flags&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -282,24 +225,15 @@
 #ifdef F_recvfrom
 ssize_t	recvfrom&#40;int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetRecvfrom&#40;sock, buf, len, flags, from, fromlen&#41;;
+	ret = sceNetInetRecvfrom&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, buf, len, flags, from, fromlen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -313,24 +247,15 @@
 #ifdef F_send
 ssize_t	send&#40;int s, const void *buf, size_t len, int flags&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetSend&#40;sock, buf, len, flags&#41;;
+	ret = sceNetInetSend&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, buf, len, flags&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -344,24 +269,15 @@
 #ifdef F_sendto
 ssize_t	sendto&#40;int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetSendto&#40;sock, buf, len, flags, to, tolen&#41;;
+	ret = sceNetInetSendto&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, buf, len, flags, to, tolen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -375,29 +291,31 @@
 #ifdef F_setsockopt
 int	setsockopt&#40;int s, int level, int optname, const void *optval, socklen_t optlen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetSetsockopt&#40;sock, level, optname, optval, optlen&#41;;
+	ret = sceNetInetSetsockopt&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, level, optname, optval, optlen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
 		return -1;
 	&#125;
+	else
+	&#123;
+		if &#40; &#40;level == SOL_SOCKET&#41; && &#40;optname == SO_NONBLOCK&#41; &#41; &#123;
+			if &#40;*&#40;&#40;int*&#41;optval&#41; == 1&#41; &#123;
+				__psp_descriptormap&#91;s&#93;->flags |= O_NONBLOCK;
+			&#125;
+			else &#123;
+				__psp_descriptormap&#91;s&#93;->flags &= ~O_NONBLOCK;
+			&#125;	
+		&#125;
+	&#125;
 
 	return 0;
 &#125;
@@ -406,24 +324,15 @@
 #ifdef F_shutdown
 int	shutdown&#40;int s, int how&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetShutdown&#40;sock, how&#41;;
+	ret = sceNetInetShutdown&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, how&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -437,24 +346,15 @@
 #ifdef F_getpeername
 int	getpeername&#40;int s, struct sockaddr *name, socklen_t *namelen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetGetpeername&#40;sock, name, namelen&#41;;
+	ret = sceNetInetGetpeername&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, name, namelen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -468,24 +368,15 @@
 #ifdef F_getsockname
 int	getsockname&#40;int s, struct sockaddr *name, socklen_t *namelen&#41;
 &#123;
-	int sock;
 	int ret;
 
-	if&#40;!&#40;SOCKET_IS_VALID&#40;s&#41;&#41;&#41;
+	if&#40;__psp_descriptormap&#91;s&#93; == NULL || __psp_descriptormap&#91;s&#93;->type != __PSP_DESCRIPTOR_TYPE_SOCKET&#41;
 	&#123;
 		errno = EBADF;
 		return -1;
 	&#125;
 
-	sock = SOCKET_GET_SOCK&#40;s&#41;;
-
-	if&#40;__psp_socket_map&#91;sock&#93; == 0&#41;
-	&#123;
-		errno = EBADF;
-		return -1;
-	&#125;
-
-	ret = sceNetInetGetsockname&#40;sock, name, namelen&#41;;
+	ret = sceNetInetGetsockname&#40;__psp_descriptormap&#91;s&#93;->sce_descriptor, name, namelen&#41;;
 	if&#40;ret < 0&#41;
 	&#123;
 		errno = sceNetInetGetErrno&#40;&#41;;
@@ -496,23 +387,6 @@
 &#125;
 #endif
 
-#ifdef F_select
-int	select&#40;int n, fd_set *readfds, fd_set *writefds,
-	    fd_set *exceptfds, struct timeval *timeout&#41;
-&#123;
-	int ret;
-
-	ret = sceNetInetSelect&#40;n, readfds, writefds, exceptfds, timeout&#41;;
-	if&#40;ret < 0&#41;
-	&#123;
-		errno = sceNetInetGetErrno&#40;&#41;;
-		return -1;
-	&#125;
-
-	return ret;
-&#125;
-#endif
-
 #ifdef F_inet_ntoa
 char *inet_ntoa&#40;struct in_addr in&#41;
 &#123;
Index&#58; libc/sys/psp/Makefile.am
===================================================================
--- libc/sys/psp/Makefile.am	&#40;revision 1866&#41;
+++ libc/sys/psp/Makefile.am	&#40;working copy&#41;
@@ -12,19 +12,26 @@
                      _link.o _unlink.o sleep.o opendir.o readdir.o	\
                      closedir.o getcwd.o chdir.o mkdir.o rmdir.o	\
                      realpath.o _stat.o truncate.o access.o tzset.o	\
-                     __psp_set_errno.o mlock.o
+                     __psp_set_errno.o mlock.o _fcntl.o
 
 SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o \
 				   listen.o recv.o recvfrom.o send.o sendto.o \
-				   setsockopt.o shutdown.o __psp_socket_map.o \
-				   getsockname.o getpeername.o select.o inet_ntoa.o
+				   setsockopt.o shutdown.o getsockname.o getpeername.o \
+				   inet_ntoa.o
+				   
+PIPE_OBJS = pipe.o 
 
+FDMAN_OBJS = fdman.o
+
+SELECT_OBJS = select.o
+
 XPRINTF_MULT_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o _sprintf_r.o
 
 NETDB_MULT_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
 
-lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c
-lib_a_LIBADD  = $&#40;LIBCGLUE_MULT_OBJS&#41; $&#40;SOCKET_MULT_OBJS&#41; $&#40;XPRINTF_MULT_OBJS&#41; $&#40;NETDB_MULT_OBJS&#41;
+lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c pipe.c fdman.c select.c
+lib_a_LIBADD  = $&#40;LIBCGLUE_MULT_OBJS&#41; $&#40;SOCKET_MULT_OBJS&#41; $&#40;XPRINTF_MULT_OBJS&#41; \
+				$&#40;NETDB_MULT_OBJS&#41; $&#40;PIPE_OBJS&#41; $&#40;FDMAN_OBJS&#41; $&#40;SELECT_OBJS&#41;
 
 all&#58; crt0.o
 
@@ -40,5 +47,14 @@
 $&#40;NETDB_MULT_OBJS&#41;&#58; netdb.c
 	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
 
+$&#40;PIPE_OBJS&#41;&#58; pipe.c
+	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
+
+$&#40;FDMAN_OBJS&#41;&#58; fdman.c
+	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
+
+$&#40;SELECT_OBJS&#41;&#58; select.c
+	$&#40;COMPILE&#41; -DF_$* $< -c -o $@
+
 ACLOCAL_AMFLAGS = -I ../../..
 CONFIG_STATUS_DEPENDENCIES = $&#40;newlib_basedir&#41;/configure.host
Index&#58; libc/sys/psp/fdman.h
===================================================================
--- libc/sys/psp/fdman.h	&#40;revision 0&#41;
+++ libc/sys/psp/fdman.h	&#40;revision 0&#41;
@@ -0,0 +1,38 @@
+/*
+ * PSP Software Development Kit - http&#58;//www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * fdman.h - File descriptor management.
+ *
+ * Copyright &#40;c&#41; 2006 Rafael Cabezas <rafpsp@gmail.com>
+ */
+
+#ifndef _FDMAN_H_
+	#define _FDMAN_H_
+	
+	#define __PSP_FILENO_MAX 1024
+
+	typedef enum &#123;
+		__PSP_DESCRIPTOR_TYPE_FILE  ,
+		__PSP_DESCRIPTOR_TYPE_PIPE ,
+		__PSP_DESCRIPTOR_TYPE_SOCKET,
+		__PSP_DESCRIPTOR_TYPE_TTY
+	&#125; __psp_fdman_fd_types;
+	
+	typedef struct &#123;
+		char * filename;
+		u8     type;
+		u32    sce_descriptor;
+		u32    flags;
+		u32    ref_count;
+	&#125; __psp_descriptormap_type;
+	 
+	extern __psp_descriptormap_type *__psp_descriptormap&#91;__PSP_FILENO_MAX&#93;;
+	
+	void __psp_fdman_init&#40;&#41;;
+	int  __psp_fdman_get_new_descriptor&#40;&#41;;
+	int  __psp_fdman_get_dup_descriptor&#40;int fd&#41;;
+	void __psp_fdman_release_descriptor&#40;int fd&#41;;
+
+#endif

Property changes on&#58; libc/sys/psp/fdman.h
___________________________________________________________________
Name&#58; svn&#58;eol-style
   + native

Index&#58; libc/sys/psp/sys/fd_set.h
===================================================================
--- libc/sys/psp/sys/fd_set.h	&#40;revision 1866&#41;
+++ libc/sys/psp/sys/fd_set.h	&#40;working copy&#41;
@@ -56,11 +56,14 @@
 &#125; fd_set;
 
 #define	FD_SET&#40;n, p&#41;	\
-    &#40;&#40;p&#41;->fds_bits&#91;&#40;&#40;n&#41; & 0xFF&#41; /__NFDBITS&#93; |= &#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+	&#40;&#40;p&#41;->fds_bits&#91;&#40;n&#41; /__NFDBITS&#93; |= &#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+
 #define	FD_CLR&#40;n, p&#41;	\
-    &#40;&#40;p&#41;->fds_bits&#91;&#40;&#40;n&#41; & 0xFF&#41; /__NFDBITS&#93; &= ~&#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+	&#40;&#40;p&#41;->fds_bits&#91;&#40;n&#41; /__NFDBITS&#93; &= ~&#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+
 #define	FD_ISSET&#40;n, p&#41;	\
-    &#40;&#40;p&#41;->fds_bits&#91;&#40;&#40;n&#41; & 0xFF&#41; /__NFDBITS&#93; & &#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+	&#40;&#40;p&#41;->fds_bits&#91;&#40;n&#41; /__NFDBITS&#93; & &#40;1 << &#40;&#40;n&#41; % __NFDBITS&#41;&#41;&#41;
+
 #define	FD_ZERO&#40;p&#41;	&#40;void&#41;__builtin_memset&#40;&#40;p&#41;, 0, sizeof&#40;*&#40;p&#41;&#41;&#41;
 
 #endif /* _SYS_FD_SET_H_ */
Index&#58; libc/sys/psp/sys/socket.h
===================================================================
--- libc/sys/psp/sys/socket.h	&#40;revision 1866&#41;
+++ libc/sys/psp/sys/socket.h	&#40;working copy&#41;
@@ -110,6 +110,7 @@
 #define	SO_ERROR	0x1007		/* get error status and clear */
 #define	SO_TYPE		0x1008		/* get socket type */
 #define	SO_OVERFLOWED	0x1009		/* datagrams&#58; return packets dropped */
+#define	SO_NONBLOCK     0x1009		/* non-blocking I/O */
 
 /*
  * Structure used for manipulating linger option.
@@ -266,10 +267,6 @@
 int	shutdown&#40;int, int&#41;;
 int	socket&#40;int, int, int&#41;;
 
-#define SOCKET_FD_PAT      0x7F000000
-#define SOCKET_IS_VALID&#40;x&#41; &#40;&#40;&#40;x&#41; & SOCKET_FD_PAT&#41; == SOCKET_FD_PAT&#41;
-#define SOCKET_GET_SOCK&#40;x&#41; &#40;&#40;x&#41; & ~SOCKET_FD_PAT&#41;
-
 /* sceNetInet socket API. */
 int	sceNetInetAccept&#40;int s, struct sockaddr *addr, socklen_t *addrlen&#41;;
 int	sceNetInetBind&#40;int s, const struct sockaddr *my_addr, socklen_t addrlen&#41;;
Index&#58; libc/sys/psp/pipe.c
===================================================================
--- libc/sys/psp/pipe.c	&#40;revision 0&#41;
+++ libc/sys/psp/pipe.c	&#40;revision 0&#41;
@@ -0,0 +1,265 @@
+/*
+ * PSP Software Development Kit - http&#58;//www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright &#40;c&#41; 2006 Rafael Cabezas <rafpsp@gmail.com>
+ * 
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/fd_set.h>
+
+#include <psptypes.h>
+#include <pspthreadman.h>
+#include <pspmodulemgr.h>
+#include <pspkerror.h>
+#include "fdman.h"
+
+/* Pipe functions */
+/* Returns how many bytes are in the pipe -- waiting to be read */
+size_t __psp_pipe_peekmsgsize&#40;int fd&#41;
+&#123;
+	SceKernelMppInfo info;
+	info.size = sizeof&#40;info&#41;;
+	if &#40;sceKernelReferMsgPipeStatus&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor, &info&#41; == 0&#41; &#123;
+		return &#40;info.bufSize - info.freeSize&#41;;
+	&#125;
+	else &#123;
+		return -1;
+	&#125;
+&#125;
+
+int pipe&#40;int fildes&#91;2&#93;&#41;
+&#123;
+	static int iIndex = 0;
+	char name&#91;32&#93;;
+	iIndex++;
+
+	sprintf&#40;name, "__psp_pipe_%02d", iIndex&#41;;
+
+	SceUID uid = sceKernelCreateMsgPipe&#40;name, PSP_MEMORY_PARTITION_USER, 0, &#40;void *&#41;PIPE_BUF, NULL&#41;;
+
+	if &#40;uid >= 0&#41; &#123;
+		fildes&#91;0&#93; = __psp_fdman_get_new_descriptor&#40;&#41;;
+		if &#40;fildes&#91;0&#93; != -1&#41; &#123;
+			__psp_descriptormap&#91;fildes&#91;0&#93;&#93;->sce_descriptor = uid;
+			__psp_descriptormap&#91;fildes&#91;0&#93;&#93;->type = __PSP_DESCRIPTOR_TYPE_PIPE;
+		&#125; 
+		else &#123;
+			sceKernelDeleteMsgPipe&#40;uid&#41;;
+			errno = EFAULT;
+			return -1;
+		&#125;
+		
+		fildes&#91;1&#93; = __psp_fdman_get_dup_descriptor&#40;fildes&#91;0&#93;&#41;;
+		if &#40;fildes&#91;1&#93; != -1&#41; &#123;
+			__psp_descriptormap&#91;fildes&#91;1&#93;&#93;->sce_descriptor = uid;
+			return 0;
+		&#125; 
+		else &#123;
+			sceKernelDeleteMsgPipe&#40;uid&#41;;
+			errno = EFAULT;
+			return -1;
+		&#125;
+		
+	&#125;
+	else &#123;
+		errno = EFAULT;
+		return -1;
+	&#125;
+&#125;
+
+int __psp_pipe_close&#40;int fd&#41;
+&#123;
+	int ret = 0;
+
+	if&#40; fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || &#40;__psp_descriptormap&#91;fd&#93;->type != __PSP_DESCRIPTOR_TYPE_PIPE&#41; &#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+	
+		
+	if &#40; __psp_descriptormap&#91;fd&#93;->ref_count == 1 &#41; &#123;
+			/**
+			* Delete a message pipe
+			*
+			* @param uid - The UID of the pipe
+			*
+			* @return 0 on success, < 0 on error
+			*/
+			ret = sceKernelDeleteMsgPipe&#40;__psp_descriptormap&#91;fd&#93;->sce_descriptor&#41;;
+	&#125;
+	
+	__psp_fdman_release_descriptor&#40;fd&#41;;
+			
+	if&#40;ret < 0&#41; &#123;
+		return __psp_set_errno&#40;ret&#41;;
+	&#125;
+	
+	return 0;
+&#125;
+
+int __psp_pipe_nonblocking_read&#40;int fd, void *buf, size_t len&#41;
+&#123;
+	int ret;
+	int sceuid;
+	int size;
+	
+	if&#40; fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93;->type != __PSP_DESCRIPTOR_TYPE_PIPE &#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+	
+	sceuid = __psp_descriptormap&#91;fd&#93;->sce_descriptor;
+
+	size = __psp_pipe_peekmsgsize&#40;fd&#41;;
+	if &#40;size > 0&#41; &#123;
+		if &#40;size < len&#41; &#123;
+			len = size;
+		&#125;
+	&#125;
+	else &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+ 
+	/**
+	* Receive a message from a pipe
+	*
+	* @param uid - The UID of the pipe
+	* @param message - Pointer to the message
+	* @param size - Size of the message
+	* @param unk1 - Unknown
+	* @param unk2 - Unknown
+	* @param timeout - Timeout for receive
+	*
+	* @return 0 on success, < 0 on error
+	*/
+    ret = sceKernelTryReceiveMsgPipe&#40;sceuid, buf, len, 0, 0&#41;;
+	
+	if &#40;ret == 0&#41; &#123;/* Success - Data */
+		return len;
+	&#125;
+	else if &#40;ret == SCE_KERNEL_ERROR_MPP_EMPTY&#41; &#123;/* No data */
+		errno = EAGAIN;
+		return -1;
+	&#125;
+	else &#123;/* Error */
+		return __psp_set_errno&#40;ret&#41;;
+	&#125;
+&#125;
+
+int __psp_pipe_read&#40;int fd, void *buf, size_t len&#41;
+&#123;
+	int ret;
+	int sceuid;
+	int size;
+	
+	if&#40; fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93;->type != __PSP_DESCRIPTOR_TYPE_PIPE &#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+	
+	sceuid = __psp_descriptormap&#91;fd&#93;->sce_descriptor;
+
+	size = __psp_pipe_peekmsgsize&#40;fd&#41;;
+	if &#40;size > 0&#41; &#123;
+		if &#40;size < len&#41; &#123;
+			len = size;
+		&#125;
+	&#125;
+	else &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+
+	/**
+	* Receive a message from a pipe
+	*
+	* @param uid - The UID of the pipe
+	* @param message - Pointer to the message
+	* @param size - Size of the message
+	* @param unk1 - Unknown
+	* @param unk2 - Unknown
+	* @param timeout - Timeout for receive
+	*
+	* @return 0 on success, < 0 on error
+	*/
+	ret = sceKernelReceiveMsgPipe&#40;sceuid, buf, len, 0, NULL, NULL&#41;;
+	
+	if &#40;ret == 0&#41; &#123;/* Success - Data */
+		return len;
+	&#125;
+	else &#123;/* Error */
+		return __psp_set_errno&#40;ret&#41;;
+	&#125;
+&#125;
+
+int __psp_pipe_write&#40;int fd, const void *buf, size_t len&#41;
+&#123;
+	int ret;
+	int sceuid;
+	char *cbuf;
+	
+	if&#40; fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93;->type != __PSP_DESCRIPTOR_TYPE_PIPE &#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+	
+	sceuid = __psp_descriptormap&#91;fd&#93;->sce_descriptor;
+
+	/**
+	* Send a message to a pipe
+	*
+	* @param uid - The UID of the pipe
+	* @param message - Pointer to the message
+	* @param size - Size of the message
+	* @param unk1 - Unknown
+	* @param unk2 - Unknown
+	* @param timeout - Timeout for send
+	*
+	* @return 0 on success, < 0 on error
+	*/
+	cbuf = &#40;char *&#41;buf;
+	ret = sceKernelSendMsgPipe&#40;sceuid, cbuf, len, 0, NULL, NULL&#41;;
+	
+	if &#40;ret == 0&#41; &#123;/* Success - Data */
+		return len;
+	&#125;
+	else &#123;/* Error */
+		return __psp_set_errno&#40;ret&#41;;
+	&#125;
+&#125;
+
+int __psp_pipe_nonblocking_write&#40;int fd, const void *buf, size_t len&#41;
+&#123;
+	int ret;
+	int sceuid;
+	char *cbuf;
+	
+	if&#40; fd < 0 || fd > &#40;__PSP_FILENO_MAX - 1&#41; || __psp_descriptormap&#91;fd&#93;->type != __PSP_DESCRIPTOR_TYPE_PIPE &#41; &#123;
+		errno = EBADF;
+		return -1;
+	&#125;
+	
+	sceuid = __psp_descriptormap&#91;fd&#93;->sce_descriptor;
+
+	cbuf = &#40;char *&#41;buf;
+	ret = sceKernelTrySendMsgPipe&#40;sceuid, cbuf, len, 0, 0&#41;;
+	
+	if &#40;ret == 0&#41; &#123;/* Success - Data */
+		return len;
+	&#125;
+	else if &#40;ret == SCE_KERNEL_ERROR_MPP_FULL&#41; &#123;
+		errno = EAGAIN;
+		return -1;
+	&#125;
+	else &#123;/* Error */
+		return __psp_set_errno&#40;ret&#41;;
+	&#125;
+&#125;
+

Property changes on&#58; libc/sys/psp/pipe.c
___________________________________________________________________
Name&#58; svn&#58;eol-style
   + native

Index&#58; configure.host
===================================================================
--- configure.host	&#40;revision 1866&#41;
+++ configure.host	&#40;working copy&#41;
@@ -574,7 +574,7 @@
 	  mipsallegrex*-psp-*&#41;
 		sys_dir=psp
 		syscall_dir=syscalls
-		newlib_cflags="$&#123;newlib_cflags&#125; -G0 -DCOMPACT_CTYPE -DCLOCK_PROVIDED -DMALLOC_ALIGNMENT=16 -I$&#123;prefix&#125;/psp/sdk/include" ;;
+		newlib_cflags="$&#123;newlib_cflags&#125; -G0 -mno-explicit-relocs -DCOMPACT_CTYPE -DCLOCK_PROVIDED -DHAVE_FCNTL -DMALLOC_ALIGNMENT=16 -I$&#123;prefix&#125;/psp/sdk/include" ;;
 	  *&#41;
 		newlib_cflags="$&#123;newlib_cflags&#125; -DMISSING_SYSCALL_NAMES" ;;
 	esac
Thanks,

Raf.

PS: Edit: a bit of cleanup
Last edited by raf on Fri Apr 28, 2006 1:42 am, edited 1 time in total.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

I skimmed over it; looks good to me. The added features are all very nice!
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Yah looks nice, was wanting to implement something like this myself but was always too lazy so just went with the dirty approach :)

I am assuming you also added into the patch the removal of gp usage ?
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

Thanks, Jim and James! It's very reassuring to hear you say that it looks good.. :)
Yes, the -mno-explicit-relocs takes care of the gp issue we found earlier.

Raf.
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Btw regarding thread safety, really the simplest way would be to disable then enable interrupts over the bit you need to be thread safe, as long as you dont take too long doing it and are not calling any kernel functions then it is low cost and little effort ;)

The reason that this wasn't implemented before for malloc is the kernel functions to do it were in a usermode library which therefore would not link into kernel executables, pspsdk now has replacements for them in pspSdkDisableInterrupts/EnableInterrupts so perhaps now is the time to put that into malloc as well as your file descriptor mapping stuff, just a thought.

e.g.

Code: Select all

int inten;

inten = pspSdkDisableInterrupts&#40;&#41;;

/* Do something or other */

pspSdkEnableInterrupts&#40;inten&#41;;
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

TyRaNiD wrote:Btw regarding thread safety, really the simplest way would be to disable then enable interrupts over the bit you need to be thread safe, as long as you dont take too long doing it and are not calling any kernel functions then it is low cost and little effort ;)

The reason that this wasn't implemented before for malloc is the kernel functions to do it were in a usermode library which therefore would not link into kernel executables, pspsdk now has replacements for them in pspSdkDisableInterrupts/EnableInterrupts so perhaps now is the time to put that into malloc as well as your file descriptor mapping stuff, just a thought.

e.g.

Code: Select all

int inten;

inten = pspSdkDisableInterrupts&#40;&#41;;

/* Do something or other */

pspSdkEnableInterrupts&#40;inten&#41;;
Ah, OK. I saw the code to disable/enable interrupts in libcglue, but it was all commented out so I didn't know how safe it was.. If you think this is appropriate, then I'll do that in the get new descriptor and get dup descriptor functions, they don't make any kernel function calls, just look for a free descriptor through the pool.

Thanks!,

Raf.

PS: Since I see no objections, I'll plan to commit these changes to the repo tomorrow Friday. How do we go about making the newlib patch for the toolchain? Is that re-done every time a change is done to newlib, or only after specific events? Thanks.
Last edited by raf on Fri Apr 28, 2006 11:31 am, edited 1 time in total.
danzel
Posts: 182
Joined: Fri Nov 04, 2005 11:03 pm

Post by danzel »

<warning, sort of off topic>
You aren't the only one who's been porting links2 :) lol.
http://localhost.geek.nz/plinks3.jpg
As you can see I wasn't as far as yourself.

How up to date is the version in pspradio svn?
Any chance of getting added as a developer to pspradio so I can lend a hand?
Perhaps we could get webnab/afkim added into pspradio as apps? They can be GPL'd no problem.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

danzel wrote:<warning, sort of off topic>
You aren't the only one who's been porting links2 :) lol.
http://localhost.geek.nz/plinks3.jpg
As you can see I wasn't as far as yourself.

How up to date is the version in pspradio svn?
Any chance of getting added as a developer to pspradio so I can lend a hand?
Perhaps we could get webnab/afkim added into pspradio as apps? They can be GPL'd no problem.
That's funny, look at some screens of my port here:
http://rafpsp.blogspot.com/

Everybody is welcome to join the PSPRadio team, I'll send you an email.

Raf.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

raf wrote:How do we go about making the newlib patch for the toolchain?
Make your changes in newlib-psp/, have the original newlib tar extracted as newlib-1.13.0/, and run

Code: Select all

psptoolchain/devel/scripts/difftree.sh newlib-psp newlib-1.13.0
then copy the generated patch-newlib* file to psptoolchain/newlib-1.13.0.patch. Or something like that, I might be misremembering a little. :)
danzel
Posts: 182
Joined: Fri Nov 04, 2005 11:03 pm

Post by danzel »

Just applied this by hand :)

Few small things:
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
This is done many times, I think it should get its own define, something like
VALID_FD(index, type);
so it would be if (!VALID_FD(s, __PSP_DESCRIPTOR_TYPE_SOCKET))
or something?
We should also be checking the index passed in to make sure its within valid range shouldn't we?

The comment at the start of select.c calls it pipe.c

all of the sceKernel*Pipe functions in pipe.c have their full headers from the pspsdk headers.

Very good work though :)
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

jimparis wrote:
raf wrote:How do we go about making the newlib patch for the toolchain?
Make your changes in newlib-psp/, have the original newlib tar extracted as newlib-1.13.0/, and run

Code: Select all

psptoolchain/devel/scripts/difftree.sh newlib-psp newlib-1.13.0
then copy the generated patch-newlib* file to psptoolchain/newlib-1.13.0.patch. Or something like that, I might be misremembering a little. :)
Oh, OK. Thanks!, I didn't realize there were scripts there :)

I'll try that after commiting the changes.

Raf.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

danzel wrote:Just applied this by hand :)

Few small things:
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
This is done many times, I think it should get its own define, something like
VALID_FD(index, type);
so it would be if (!VALID_FD(s, __PSP_DESCRIPTOR_TYPE_SOCKET))
or something?
That's not a bad idea, I'll work on that after the initial commit.
We should also be checking the index passed in to make sure its within valid range shouldn't we?
Yes, we should. I actually do it in libcglue.c and pipe.c, but not in socket.c.. good catch.
The comment at the start of select.c calls it pipe.c
Good catch again :) (good ol' copy+paste error)
all of the sceKernel*Pipe functions in pipe.c have their full headers from the pspsdk headers.
Yes, they do! :)

Thanks for reviewing the code, btw.
Last edited by raf on Fri Apr 28, 2006 11:59 pm, edited 1 time in total.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

I just commited the patch, it's at r1883..

I'll work on James and Danzel's comments now.

Raf.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

danzel wrote: if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
This is done many times, I think it should get its own define, something like
VALID_FD(index, type);
so it would be if (!VALID_FD(s, __PSP_DESCRIPTOR_TYPE_SOCKET))
or something?
I'll just do something like:

Code: Select all

	#define __PSP_IS_FD_VALID&#40;FD&#41; \
			&#40; &#40;FD >= 0&#41; && &#40;FD < __PSP_FILENO_MAX&#41; && &#40;__psp_descriptormap&#91;FD&#93; != NULL&#41; &#41;

	#define __PSP_IS_FD_OF_TYPE&#40;FD, TYPE&#41; \
			&#40; &#40;__PSP_IS_FD_VALID&#40;FD&#41;&#41; && &#40;__psp_descriptormap&#91;FD&#93;->type == TYPE&#41; &#41;
Raf.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

TyRaNiD wrote:

Code: Select all

int inten;

inten = pspSdkDisableInterrupts&#40;&#41;;

/* Do something or other */

pspSdkEnableInterrupts&#40;inten&#41;;
James,

I tried adding these calls to fdman.c. But then when I try to compile an application, I get linker errors:

Code: Select all

/usr/local/pspdev/lib/gcc/psp/4.0.2/../../../../psp/lib/libc.a&#40;fdman.o&#41;&#58; In function `__psp_fdman_get_new_descriptor'&#58;
../../../../../../newlib/libc/sys/psp/fdman.c&#58;52&#58; undefined reference to `pspSdkDisableInterrupts'
../../../../../../newlib/libc/sys/psp/fdman.c&#58;57&#58; undefined reference to `pspSdkEnableInterrupts'
../../../../../../newlib/libc/sys/psp/fdman.c&#58;61&#58; undefined reference to `pspSdkEnableInterrupts'
/usr/local/pspdev/lib/gcc/psp/4.0.2/../../../../psp/lib/libc.a&#40;fdman.o&#41;&#58; In function `__psp_fdman_get_dup_descriptor'&#58;
../../../../../../newlib/libc/sys/psp/fdman.c&#58;77&#58; undefined reference to `pspSdkDisableInterrupts'
../../../../../../newlib/libc/sys/psp/fdman.c&#58;82&#58; undefined reference to `pspSdkEnableInterrupts'
../../../../../../newlib/libc/sys/psp/fdman.c&#58;86&#58; undefined reference to `pspSdkEnableInterrupts'
collect2&#58; ld returned 1 exit status
Is there something special I need to do that you can think of?

Thanks,

Raf.
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Hmm well you need to link it with libpspsdk.a to get those functions, it _might_ be best to actually implement them in newlib directly so that you are not dependant on the sdk library in order to build normal apps. You should just be able to grab the ones in the sdk source.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

TyRaNiD wrote:Hmm well you need to link it with libpspsdk.a to get those functions, it _might_ be best to actually implement them in newlib directly so that you are not dependant on the sdk library in order to build normal apps. You should just be able to grab the ones in the sdk source.
I'll try that; but it's funny that if I try to use the functions directly in the same application, then it compiles and links fine... maybe it's something like the order in which the libraries are passed to the linker.. don't know.

EDIT: I did as you suggested and copied interrupt.S to newlib. I renamed the functions to pspDisableInterrupts/pspEnableInterrupts so there's no conflicts. Now it's linking fine, I'll try calling them for the malloc locking as well..

Thanks,

Raf.
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

Post by anhanguera »

hi,

raf, this is really great job. this pipe() support for newlib is very important for me (guess for other developers, too). i was using this (http://svn.sourceforge.net/viewcvs.cgi/ ... pipe_mem.c) ugly && bugy pipe emulation over memory, and i was tired of working on such slow, memory hungary emulation.

keep the great work.

alper akcan "anhanguera"
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Raf, if you get a chance, can you check that this fix is right: http://svn.pspdev.org/listing.php?repna ... =1887&sc=1
(without that patch, they don't build)
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

anhanguera wrote:hi,

raf, this is really great job. this pipe() support for newlib is very important for me (guess for other developers, too). i was using this (http://svn.sourceforge.net/viewcvs.cgi/ ... pipe_mem.c) ugly && bugy pipe emulation over memory, and i was tired of working on such slow, memory hungary emulation.

keep the great work.

alper akcan "anhanguera"
Thanks, akcan! Glad someone else needed this :)

Raf.
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Post by raf »

jimparis wrote:Raf, if you get a chance, can you check that this fix is right: http://svn.pspdev.org/listing.php?repna ... =1887&sc=1
(without that patch, they don't build)
Thanks, Jim.. I knew I had to do that, just haven't had time :)
Your changes look good. Will try them later today, can't atm.
Should be able to pass max fd+1 to select () instead of FD_SETSIZE too now. But it should still work fine..

Raf.

Edit: Jim, I quickly tested the sample, and seems to work fine. Thanks, again.
0li
Posts: 1
Joined: Fri Jun 09, 2006 8:14 pm

Re: Proposed patch to newlib

Post by 0li »

raf wrote: -fcntl support: the function is now implemented, and allows to set and get file descriptor flags. Implementation is not 100% complete. But socket's can be set to non-blocking mode via a fcntl call now. Also, file descriptors can be duplicated (with ref-counting so the real close is only called on the last fd's close). -- Now dup
in my port i have a socket configured with:

Code: Select all

fcntl&#40;sock, F_SETFL, O_NONBLOCK&#41;;
But it blocks if i call accept(). Is this a bug or not implemented yet?

0li
raf
Posts: 57
Joined: Thu Oct 13, 2005 7:38 am

Re: Proposed patch to newlib

Post by raf »

0li wrote:
raf wrote: -fcntl support: the function is now implemented, and allows to set and get file descriptor flags. Implementation is not 100% complete. But socket's can be set to non-blocking mode via a fcntl call now. Also, file descriptors can be duplicated (with ref-counting so the real close is only called on the last fd's close). -- Now dup
in my port i have a socket configured with:

Code: Select all

fcntl&#40;sock, F_SETFL, O_NONBLOCK&#41;;
But it blocks if i call accept(). Is this a bug or not implemented yet?

0li
Should work, it's implemented. Could you post a small sample to recreate your problem?

Raf.
Post Reply