Esempio n. 1
0
static void *rpc_func(int fid, void *buf, int bufsize)
{
	int *res = &rpc_result;
	int thid = -1;

	switch (fid) {
		case RPCF_GetBufAddr:
			*res = (u32)dma_buffer;
			break;
		case RPCF_DmaRead:
			thid = read_thid;
			WakeupThread(thid);
			break;
		case RPCF_DmaWrite:
			thid = write_thid;
			WakeupThread(thid);
			break;

		default:
			*res = -1;
	}

	if (thid >= 0) {
		cur_thid = thid;
		*res = 0;
	}

	return res;
}
Esempio n. 2
0
int NetManRpcNetIFSendPacket(const void *packet, unsigned int length){
	struct PacketTag *PacketTag;

	WaitSema(NetManTxSemaID);

	NetmanTxWaitingThread=GetThreadId();

	WaitSema(TxBankAccessSema);

	//Check is there is space in the current Tx FIFO. If not, wait for the Tx thread to empty out the other FIFO. */
	while(CurrentTxFIFOData->PacketReqs.NumPackets>=NETMAN_RPC_BLOCK_SIZE){
		SignalSema(TxBankAccessSema);
		WakeupThread(TxThreadID);
		SleepThread();
		WaitSema(TxBankAccessSema);
	}

	memcpy(&CurrentTxFIFOData->FrameBuffer[CurrentTxFIFOData->PacketReqs.TotalLength], packet, length);
	PacketTag=&CurrentTxFIFOData->PacketReqs.tags[CurrentTxFIFOData->PacketReqs.NumPackets];
	PacketTag->offset=CurrentTxFIFOData->PacketReqs.TotalLength;
	PacketTag->length=length;

	CurrentTxFIFOData->PacketReqs.TotalLength+=(length+3)&~3;
	CurrentTxFIFOData->PacketReqs.NumPackets++;

	WakeupThread(TxThreadID);

	SignalSema(TxBankAccessSema);

	NetmanTxWaitingThread=-1;

	SignalSema(NetManTxSemaID);

	return 0;
}
Esempio n. 3
0
void ioEnd(void) {
	// termination requested flag
	gIOTerminate = 1;
	
	// wake up and wait for end
	WakeupThread(gIOThreadId);
	WakeupThread(gDispatcherThreadID);
	
	// Cancel the thread dispatcher alarm (TODO: Is this correct?)
	ReleaseAlarm(alarmID);
}
bool Connection::IsActive()
{
	// Good opportunity to check g_ServerShutdown
	if (g_ServerShutdown) WakeupThread();

	return m_ConnectionActive;
}
Esempio n. 5
0
static void topThread(void *arg)
{
	int index;

	while(1)
	{
		WaitSema(topSema);
		index = topArg.requestOut & 0x1FF;
		topArg.requestOut = index + 1;

		switch(topArg.request[index].mode)
		{
			case TOP_REQ_WAKEUP:
				WakeupThread(topArg.request[index].data);
				break;
			case TOP_REQ_ROTATE:
				RotateThreadReadyQueue(topArg.request[index].data);
				break;
			case TOP_REQ_SUSPEND:
				SuspendThread(topArg.request[index].data);
				break;
			/* default:
				Kprintf("## internal error in libkernel!\n"); */
		}
	}
}
Esempio n. 6
0
static void TxThread(void *arg)
{
	int ThreadToWakeUp;

	while(1)
	{
		SleepThread();

		if(PacketReqs.count > 0)
		{
			while(PacketReqs.count > 0)
			{
				WaitSema(NetManIOSemaID);
				while(SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SEND_PACKETS, 0, &PacketReqs, sizeof(PacketReqs), &ReceiveBuffer, sizeof(ReceiveBuffer.result), &TxEndCallback, NULL) < 0){};
				SignalSema(NetManIOSemaID);
			}
		}
		else
		{
			if(NetmanTxWaitingThread >= 0)
			{
				DI();
				ThreadToWakeUp=NetmanTxWaitingThread;
				NetmanTxWaitingThread=-1;
				EI();
				WakeupThread(ThreadToWakeUp);
			}
		}
	}
}
Esempio n. 7
0
void ioEnd(void) {
	// termination requested flag
	gIOTerminate = 1;

	// wake up and wait for end
	WakeupThread(gIOThreadId);
}
Esempio n. 8
0
int ioPutRequest(int type, void* data) {
	if (isIOBlocked)
		return IO_ERR_IO_BLOCKED;

	// check the type before queueing
	if (!ioGetHandler(type))
		return IO_ERR_INVALID_HANDLER;

	WaitSema(gEndSemaId);

	// We don't have to lock the tip of the queue...
	// If it exists, it won't be touched, if it does not exist, it is not being processed
	struct io_request_t* req = gReqEnd;

	if (!req) {
		gReqList = (struct io_request_t*)malloc(sizeof(struct io_request_t));
		req = gReqList;
		gReqEnd = gReqList;
	} else {
		req->next = (struct io_request_t*)malloc(sizeof(struct io_request_t));
		req = req->next;
		gReqEnd = req;
	}

	req->next = NULL;
	req->type = type;
	req->data = data;

	SignalSema(gEndSemaId);

	WakeupThread(gIOThreadId);
	return IO_OK;
}
Esempio n. 9
0
//Only one thread can enter this critical section!
static void EnQFrame(const void *frame, unsigned int length)
{
	SifDmaTransfer_t dmat;
	int dmat_id;

	//Write back D-cache, before performing a DMA transfer.
	SifWriteBackDCache((void*)frame, length);

	//Wait for a spot to be freed up.
	while(PacketReqs.count + 1 >= NETMAN_RPC_BLOCK_SIZE)
	{
		NetmanTxWaitingThread = GetThreadId();
		WakeupThread(TxThreadID);
		SleepThread();
	}

	//Transfer to IOP RAM
	dmat.src = (void*)frame;
	dmat.dest = &IOPFrameBuffer[IOPFrameBufferWrPtr * NETMAN_MAX_FRAME_SIZE];
	dmat.size = length;
	dmat.attr = 0;
	while((dmat_id = SifSetDma(&dmat, 1))==0){};

	//Record the frame length.
	PacketReqs.length[IOPFrameBufferWrPtr] = length;

	DI();
	//Update the frame count.
	PacketReqs.count++;
	EI();

	//Increase write pointer by one position.
	IOPFrameBufferWrPtr = (IOPFrameBufferWrPtr + 1) % NETMAN_RPC_BLOCK_SIZE;

	//Signal the transmission thread that there are more frames to transmit.
	WakeupThread(TxThreadID);

	//Ensure that the frame is copied over before returning (so that the buffer can be freed).
	while(SifDmaStat(dmat_id) >= 0){};
}
Esempio n. 10
0
static void TxThread(void *arg){
	struct TxFIFOData *TxFIFODataToTransmit;
	SifDmaTransfer_t dmat;
	int dmat_id, ThreadToWakeUp;

	while(1){
		SleepThread();

		WaitSema(TxBankAccessSema);

		if(CurrentTxFIFOData->PacketReqs.NumPackets>0){
			// Switch banks
			TxFIFODataToTransmit=CurrentTxFIFOData;
			if(TxActiveBankID==0){
				CurrentTxFIFOData=&TxFIFOData2;
				TxActiveBankID=1;
			}
			else{
				CurrentTxFIFOData=&TxFIFOData1;
				TxActiveBankID=0;
			}

			SignalSema(TxBankAccessSema);

			SifWriteBackDCache(&TxFIFODataToTransmit->PacketReqs, sizeof(TxFIFODataToTransmit->PacketReqs));

			dmat.src=&TxFIFODataToTransmit->PacketReqs;
			dmat.dest=TxFrameTagBuffer;
			dmat.size=8+sizeof(struct PacketTag)*TxFIFODataToTransmit->PacketReqs.NumPackets;
			dmat.attr=0;

			while((dmat_id=SifSetDma(&dmat, 1))==0){};

			WaitSema(NetManIOSemaID);
			SifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SEND_PACKETS, 0, TxFIFODataToTransmit->FrameBuffer, TxFIFODataToTransmit->PacketReqs.TotalLength, NULL, 0, NULL, NULL);
			SignalSema(NetManIOSemaID);

			TxFIFODataToTransmit->PacketReqs.NumPackets=0;
			TxFIFODataToTransmit->PacketReqs.TotalLength=0;
		}
		else SignalSema(TxBankAccessSema);

		if(NetmanTxWaitingThread>=0){
			ThreadToWakeUp=NetmanTxWaitingThread;
			NetmanTxWaitingThread=-1;	//To prevent a race condition from occurring, invalidate NetmanTxWaitingThread before invoking WakeupThread.
			WakeupThread(ThreadToWakeUp);
		}
	}
}
Connection::~Connection()
{
	LogMessage("[%d] Connection Destroyed\n", m_RecvThreadHandle);
	
	KillConnection();
	
	// Let thread know it is terminated.
	if (!m_TcpThreadTerminated)
	{
		m_TcpThreadTerminated = true;
		WakeupThread();

		m_Mutex.Lock();
		Sleep(1);
		m_Mutex.Unlock();
	}

	delete m_SendQueue;
}
Connection * Connection::ReSetConnection(SOCKET s, ServerManager &server_mgr, short port, int server_type, unsigned long* ip_addr)
{
	if (!m_RecvThreadHandle) // This should never be needed, but it's in here just in case.
	{
		LogMessage("!Restarting TCP Connection receive thread\n");
#ifdef WIN32
		UINT uiThreadId = 0;
		m_RecvThreadHandle = (HANDLE)_beginthreadex(NULL, 1024, SocketRecvThread, this, 0, &uiThreadId);
#else
		pthread_mutex_init(&m_RecvThreadMtx, NULL);
		pthread_cond_init(&m_RecvThreadCond, NULL);
		pthread_create(&m_RecvThreadHandle, NULL, SocketRecvThread, this);
#endif
	}

	m_Mutex.Lock();

	m_ConnectionActive	= true;		// Mark this as an active connection
	m_PacketLoggingEnabled	= false;	// Disable packet logging
	m_KeysExchanged		= false;
	m_LoginHandoff		= false;
	m_InactivityTimer	= 0;

	// Temporarily set the AvatarID to 1, otherwise it might get killed off
	// too soon with a heavy load (lots of connections)
	m_AvatarID			= 1;

	m_Socket		= s;
	m_TcpPort		= port;
	m_ServerType		= server_type;
	
	if (ip_addr) m_IPaddr 	= *ip_addr;

	m_Mutex.Unlock();

	m_SendQueue->ResetQueue();

	LogMessage("[%d] Reanimating TCP Connection receive thread\n", m_RecvThreadHandle);

	WakeupThread();		

	return this;
}