Receiving UDP data thru socket in its own thread

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

Moderators: cheriff, TyRaNiD

Post Reply
AudioMonster
Posts: 37
Joined: Wed Sep 07, 2005 3:41 am
Contact:

Receiving UDP data thru socket in its own thread

Post by AudioMonster »

Hello,

I'm trying to receive some data sent by my PC UDP client over WiFi.
I would like to receive them in a separate thread :


bool PspUDPrx::StartListening()
{

sceNetInetBind( _socketRX, (struct sockaddr* )&_addr, sizeof(_addr));


int tmp = sceKernelCreateThread("PspUDPrx",PspUDPrx::UdpRxThread, 0x18, 0x10000, 0, 0);

if(tmp >= 0)
{
sceKernelStartThread(tmp, sizeof(PspUDPrx*), this);
}
else
return false;

// ListenInOwnThread();

return true;
}

// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
int PspUDPrx::UdpRxThread(SceSize args, void *argp)
{

PspUDPrx* pRx = (PspUDPrx*)argp;
pRx->ListenInOwnThread();

return 0;
}


Unfortunately, the sceNetInetRecv of the method ListenInOwnThread() does not work if i create that thread. It works fine if i don't create the thread and just call that method instead.

I presume i don't initialize the thread properly, is there some special parameter i should pass ? i tried PSP_THREAD_ATTR_USBWLAN without success.
Or maybe it's inside UdpRxThread(SceSize args, void *argp) that i don't cast properly the argp ?
AudioMonster
Posts: 37
Joined: Wed Sep 07, 2005 3:41 am
Contact:

C++ : Passing "this" pointer to sceKernelStartThre

Post by AudioMonster »

It seems my problem is about passing "this" to sceKernelStartThread.
So inside the function ListenInOwnThread() i don't have access to the real data member of that instance of my object.

in StartListening() i do

if(tmp >= 0)
{
printf("this = %x\n",(unsigned int)this);
sceKernelStartThread(tmp, sizeof(PspUDPrx*), this);
}

and in UdpRxThread() i do

PspUDPrx* pRx = (PspUDPrx*)argp;
printf("pRx = %x\n",(unsigned int)pRx);
pRx->ListenInOwnThread();

the 2 printf give a different value for the address of the instance of my object. Do i do something wrong in the way i cast ?
PspPet
Posts: 210
Joined: Wed Mar 30, 2005 2:13 am
Contact:

Post by PspPet »

re: sceKernelStartThread
BTW: If you want to access any global variables (or static variables in your class) you need a smaller assembler stub that sets the GP register before calling "PspUDPrx::UdpRxThread"

The args passed between threads are a *COPY* of the data you pass to "sceKernelStartThread". Your existing code can't handle that.

Add a "&" and "*" it should work. Instead use:
sceKernelStartThread(tmp, sizeof(PspUDPrx*), &this);
and:
PspUDPrx* pRx = *(*PspUDPrx*)argp;

Ideally put them into a structure
AudioMonster
Posts: 37
Joined: Wed Sep 07, 2005 3:41 am
Contact:

Post by AudioMonster »

int sceKernelStartThread (SceUID thid, SceSize args, void* argp)

Aaah so sceKernelStartThread actually contains a buffer of size
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

PspPet wrote:re: sceKernelStartThread
BTW: If you want to access any global variables (or static variables in your class) you need a smaller assembler stub that sets the GP register before calling "PspUDPrx::UdpRxThread"
GP is set by the kernel before executing the app (it needs no assistance from crt0). GP is shared across the entire program. GP only needs to be saved and restored if calling into a custom PRX that also uses GP (and this is usually done by the PRX itself).
AudioMonster
Posts: 37
Joined: Wed Sep 07, 2005 3:41 am
Contact:

Post by AudioMonster »

Opps sorry for last post.

int sceKernelStartThread (SceUID thid, SceSize args, void* argp)

Aaah so the thread actually contains a buffer of size args and do an actually copy of argp into that internal buffer and pass it to the thread function ? That's very unusual ! :-P
Well, so i guess i was receiving the first 4 bytes of my object and not the actual address...

BTW: If you want to access any global variables (or static variables in your class) you need a smaller assembler stub that sets the GP register before calling "PspUDPrx::UdpRxThread"
What do you mean by that ?
AudioMonster
Posts: 37
Joined: Wed Sep 07, 2005 3:41 am
Contact:

Post by AudioMonster »

sceKernelStartThread(tmp, sizeof(PspUDPrx*), &this);

PspUDPrx.cpp:163: error: invalid lvalue in unary '&'

It seems like i need to use and intermediate variable.

PspUDPrx* pThis = this;
sceKernelStartThread(tmp, sizeof(PspUDPrx*), &pThis);

Any direct way to do this ?
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

AudioMonster wrote:BTW: If you want to access any global variables (or static variables in your class) you need a smaller assembler stub that sets the GP register before calling "PspUDPrx::UdpRxThread"
What do you mean by that ?
Read my post, you can pretty much ignore that. But if you want optimized access to global variables, pass -G8 instead of -G0 on the command line.
Post Reply