me->io_pending = PR_TRUE;
(void)PBReadAsync(&pbAsync.pb);
PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op){	PRInt32 refNum = fd->secret->md.osfd;	OSErr				err; 	ExtendedParamBlock 	pbAsync;	PRThread			*me = _PR_MD_CURRENT_THREAD();    _PRCPU *cpu = _PR_MD_CURRENT_CPU();	/* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */	/* note, if a user chooses "seek" or the like as an operation in another function */	/* this will not work */	if (refNum >= 0 && refNum < 3)	{		switch (refNum)		{				case 0:					/* stdin - not on a Mac for now */					err = paramErr;					goto ErrorExit;					break;				case 1: /* stdout */				case 2: /* stderr */					puts(buf);					break;		}				return (bytes);	}	else	{		static IOCompletionUPP	sCompletionUPP = NULL;				/* allocate the callback Universal Procedure Pointer (UPP). This actually allocates		   a 32 byte Ptr in the heap, so only do this once		*/		if (!sCompletionUPP)			sCompletionUPP = NewIOCompletionProc((IOCompletionProcPtr)&AsyncIOCompletion);					/* grab the thread so we know which one to post to at completion */		pbAsync.thread	= me;		pbAsync.pb.ioParam.ioCompletion	= sCompletionUPP;		pbAsync.pb.ioParam.ioResult		= noErr;		pbAsync.pb.ioParam.ioRefNum		= refNum;		pbAsync.pb.ioParam.ioBuffer		= buf;		pbAsync.pb.ioParam.ioReqCount	= bytes;		pbAsync.pb.ioParam.ioPosMode	= fsAtMark;		pbAsync.pb.ioParam.ioPosOffset	= 0;		/* 		** Issue the async read call and wait for the io semaphore associated		** with this thread.		** Don't compute error code from async call. Bug in OS returns a garbage value.		*/	    me->io_fd = refNum;		me->md.osErrCode = noErr;		if (op == READ_ASYNC)		{			/*			**  Skanky optimization so that reads < 20K are actually done synchronously			**  to optimize performance on small reads (e.g. registry reads on startup)			*/			if ( bytes > 20480L )			{				err = PBReadAsync(&pbAsync.pb);				if (err != noErr && err != eofErr)					goto ErrorExit;					   			me->io_pending = PR_TRUE; /* Only mark thread io pending if async call worked */			}			else			{				(void) PBReadSync(&pbAsync.pb);				/*				** This is probbaly redundant but want to make sure we indicate the read				** is complete so we don't wander off into the Sargasso Sea of Mac				** threading				*/				pbAsync.pb.ioParam.ioResult = 0;			}		}		else		{			/* writes are currently always async */			err = PBWriteAsync(&pbAsync.pb);				if (err != noErr)					goto ErrorExit;						/* Didn't get an error on the asyn call so mark thread io pending */	   		me->io_pending = PR_TRUE;		}				/* See if the i/o call is still pending before we actually yield */		if (pbAsync.pb.ioParam.ioResult == 1)			WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);		else			me->io_pending = PR_FALSE; /* io completed so don't mark thread io pending */	}		err = me->md.osErrCode;	if (err != noErr)		goto ErrorExit;	err = pbAsync.pb.ioParam.ioResult;	if (err != noErr && err != eofErr)		goto ErrorExit;	else		return pbAsync.pb.ioParam.ioActCount;ErrorExit:	me->md.osErrCode = err;	_MD_SetError(err);    return -1;}