📄 file.c
字号:
//--------------------------------------------------------------------------
// Streaming/Socket IO Layer
//--------------------------------------------------------------------------
// file.c
//
// File Management Functions
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "fdt.h"
//--------------------------------------------------------------------
// FDWaitEvent()
//
// Wait for a file event on the supplied FD handle with a timeout
//
// If timeout is NULL, function waits forever
//
// Returns 1 if the event was detected, or 0 on timeout
//--------------------------------------------------------------------
int FDWaitEvent( HANDLE hFd, uint EventFlags, UINT32 timeout )
{
FILEDESC *pfd = (FILEDESC *)hFd;
#ifdef _STRONG_CHECKING
if( pfd->Type != HTYPE_FD )
{
DbgPrintf(DBG_ERROR,"FDWaitEvent: HTYPE %04x",pfd->Type);
return(0);
}
#endif
// Sync the task to track FD activity
fdint_clearevent( pfd->pfdt );
// Add the current request to the state
pfd->EventFlags |= EventFlags;
// If there's no timeout, this will wait forever
// Else wait for the time limit
fdint_waitevent( pfd->pfdt, timeout );
// If EventFlags still set, then we timed out
if( (pfd->EventFlags & EventFlags) == EventFlags )
{
pfd->EventFlags &= ~EventFlags;
return(0);
}
return(1);
}
//--------------------------------------------------------------------
// FDSignalEvent()
//
// Signal a file event on the supplied FD handle
//
// Note: hFd can be NULL
//--------------------------------------------------------------------
void FDSignalEvent( HANDLE hFd, uint EventFlags )
{
FILEDESC *pfd = (FILEDESC *)hFd;
// The calling parameter can be NULL. Also, if the FD is in
// an orphaned state, there's no owner task to notify.
if( !pfd || !pfd->pfdt )
return;
#ifdef _STRONG_CHECKING
if( pfd->Type != HTYPE_FD )
{
DbgPrintf(DBG_ERROR,"FDSignalEvent: HTYPE %04x",pfd->Type);
return;
}
#endif
// Wake if conditions are right
if( pfd->EventFlags & EventFlags )
{
// Since we're waking, clear all the wake bits
pfd->EventFlags &= ~(FD_EVENT_READ | FD_EVENT_WRITE | FD_EVENT_EXCEPT);
// Wake the owining task
fdint_signalevent( pfd->pfdt );
}
}
//--------------------------------------------------------------------
// fdint_new()
//
// Create a new file descriptor
//--------------------------------------------------------------------
int fdint_new( FDTABLE *pfdt, FILEDESC **ppfd, uint fdType )
{
int i;
FILEDESC *pfd;
// Look for an open slot
for( i=0; i<FD_MAX; i++ )
if( !pfdt->pfd[i] )
break;
if( i==FD_MAX )
return( EMFILE );
// Allocate the file descriptor
if( !(pfd = (FILEDESC*)mmAlloc(sizeof(FILEDESC))) )
return( ENOMEM );
// Save the FD
pfdt->pfd[i] = pfd;
// Initialize the FD
pfd->Type = HTYPE_FD;
pfd->fdType = fdType;
pfd->EventFlags = 0;
pfd->hSock = 0;
pfd->pfdt = pfdt;
pfd->fd = i+1;
*ppfd = pfd;
return( 0 );
}
//--------------------------------------------------------------------
// fdint_free()
//
// Free an unused file descriptor
//--------------------------------------------------------------------
void fdint_free( FILEDESC *pfd )
{
// Simple abort
pfd->pfdt->pfd[pfd->fd-1] = 0;
mmFree( pfd );
}
//--------------------------------------------------------------------
// fdint_close()
//
// Close an FD
//--------------------------------------------------------------------
int fdint_close( FILEDESC *pfd )
{
int error = 0;
int tmp;
// We need to free the file descriptor.
// *** In this OS, all file descriptors are sockets or pipes ***
if( pfd->hSock )
{
if( pfd->fdType == FDTYPE_SOCKET )
{
// If fd is an orphan or we're closing someone else's fd,
// then we can't block during close
if( !pfd->pfdt || pfd->pfdt->hOwner != TaskSelf() )
{
tmp = 0;
SockSet(pfd->hSock, SOL_SOCKET, SO_BLOCKING, &tmp, sizeof(int));
}
// Close it
error = SockClose( pfd->hSock );
}
else
error = PipeClose( pfd->hSock );
}
// If not orphan, free the file descriptor from the table
if( pfd->pfdt )
pfd->pfdt->pfd[pfd->fd-1] = 0;
// Free fd
mmFree( pfd );
return( error );
}
//--------------------------------------------------------------------
// fdint_verify()
//
// Verifies an FD and returns a pointer to it.
// If return is NULL, this function has already set a reasonable error
//--------------------------------------------------------------------
FILEDESC *fdint_verify( int fd, uint fdType )
{
FDTABLE *pfdt;
// Get a pointer to the FD Table
pfdt = fdint_getfdt( 0 );
// If pointer is bad, we can't do a thing
if( !pfdt )
return( 0 );
// Verify File Descriptor
fd--;
if( fd < 0 || fd >= FD_MAX || !pfdt->pfd[fd] )
{
pfdt->error = EBADF;
return( 0 );
}
// If the caller specified a file type, it must match
if( fdType != FDTYPE_ANY && pfdt->pfd[fd]->fdType != fdType )
return( 0 );
// Return a pointer to the FD
return( pfdt->pfd[fd] );
}
//--------------------------------------------------------------------
// fdint_getfdt()
//
// Returns a handle to File Descriptor Table.
//
// When called with NULL handle, the FDT for the current task is
// returned.
//--------------------------------------------------------------------
FDTABLE *fdint_getfdt( HANDLE hTask )
{
if( !hTask )
return( TaskGetEnv( TaskSelf(), 0 ) );
else
return( TaskGetEnv( hTask, 0 ) );
}
//--------------------------------------------------------------------
// fdint_clearevent()
//
// Clears any pending file events for the current task
//--------------------------------------------------------------------
void fdint_clearevent( FDTABLE *pfdt )
{
pfdt->Evented = 0;
SemReset( pfdt->hSem, 0 );
}
//--------------------------------------------------------------------
// fdint_signalevent()
//
// Signals a file event for the indicated table
//--------------------------------------------------------------------
void fdint_signalevent( FDTABLE *pfdt )
{
pfdt->Evented = 1;
SemPost( pfdt->hSem );
}
//--------------------------------------------------------------------
// fdint_signaltimeout()
//
// Signals a file timeout for the indicated table
//--------------------------------------------------------------------
void fdint_signaltimeout( FDTABLE *pfdt )
{
pfdt->Evented = 0;
SemPost( pfdt->hSem );
}
//--------------------------------------------------------------------
// fdint_waitevent()
//
// Wait for a file event with a timeout. If no timeout is specified,
// the function waits forever.
//--------------------------------------------------------------------
void fdint_waitevent( FDTABLE *pfdt, UINT32 timeout )
{
// If already evented, return
if( pfdt->Evented )
return;
// Convert a timeout of 0 to forever
if( !timeout )
timeout = SEM_FOREVER;
// Since this SemPend may block, we must exit and then
// reenter the kernel mode
llExit();
SemPend( pfdt->hSem, timeout );
llEnter();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -