Page 1 of 1

USBD - command callback sync?

Posted: Sun Jun 13, 2004 7:55 pm
by ole
How to make a programm to execute usbd calls (and their callbacks) in the exact order i specify?
All usbd commands (UsbControllTransfer , UsbBulkTransfer etc..) have their own callback function (for error-status checking and out-data reporting) that is called by other thread - and apparently in random order.

Current result:
call 1
call 2
callBack 1
call 3
callBack 3
callBack 2


I want to get this result:
call 1
callBack 1
call 2
callBack 2
call 3
callBack 3


I can understand that call2 must be "somehow" synchronized and executed after the callBack1. Could semaphore help me out? If so, how to use it (what exactly WaitSema and SignalSema means? Will it work if WaitSema and SignalSema are called from within different thread?). Or is there other solution?

Posted: Sun Jun 13, 2004 8:29 pm
by Oobles
If you make three calls to UsbBulkTransfer you can't know exactly which one will finish first. If you want to make sure they operate in order you can use a semaphore. The KLSI usb ethernet driver which is in cvs (http://cvs.ps2dev.org/ps2eth/ps2klsi/) has in driver.c the following

Code: Select all

static void kue_callback( int resultCode, int bytes, void *arg)
{
  int semh = (int) arg;
  SignalSema( semh );
}

/*
 * kue_do_request - Performs a USB request.
 */ 

static int kue_do_request( int dev, UsbDeviceRequest *req, void *data)
{
   struct t_sema sem;
   int semh;

   sem.attr = 0;
   sem.option = 0;
   sem.init_count = 0;
   sem.max_count = 1;

   semh = CreateSema( &sem );
   UsbTransfer( cepid, data, req->length, req, kue_callback, semh ); 

   WaitSema( semh ); 

   DeleteSema( semh );
}
there is plenty of tutorials on the behaviour of sempahores online. They basically just stop one thread from executing when they call WaitSema.. until another thread calls SignalSema. They can be used for both mutual exclusion and event notification.

In the above it is basically sending an event to the waiting thread to say that it has completed sending and it is ok to continue.

Hope that helps.
Oobles

Posted: Mon Jun 14, 2004 2:01 am
by ole
Thanks Oobles,

generally it works now, but there is some exception (and I'm wondering why I allways stumble upon some problem in the first place...).
I can't get it to work (that example with samphore you wrote) when calling my first such a call - UsbSetDeviceConfiguration. Other calls are ok now (using semaphore) - they are called and callbacked in the correct order just like I wanted.

I noticed that you use (in the ps2klsi) OpenBulkEndpoint function that is missing in the ps2lib usbd header. So without the code you linked I would have never know that function exist...
Thanks again.
Ole

Semaphores - penaly when using ?

Posted: Tue Jul 06, 2004 3:09 am
by ole
How much IOP resources the creation and deletion of the semaphores takes? Are these time/resource consuming operations?

Let's assume that I want to transfer about 400kb per second - it 's about 800 sectors. Each transfer of the sector (over bulk usb endpoind) requires at least 3 semaphores (the command, the data, the response). It makes 2400 semaphores / sec and 4800 operations (create semaphore / delete semaphore) per sec.

So my next question is: can one semaphore be reused many times? If so, how to set it up? What these attributes (attr, option, init_count, max_count) means?

Btw. currently my ps2_usb_mass_storage driver can transfer 40kbytes /sec - which is barely usable value.

Posted: Tue Jul 06, 2004 8:22 am
by Oobles
Yes you can re-use the same semaphore multiple times. The only thing you need to worry about it multiple threads trying to use the same semaphore. This is the reason the semaphore was allocated each time.

Another way is to create a mutex semaphore to surround the use of the event semaphore. A mutex is created with an initial value of 1.. then a thread requests it (causing it to go to 0).. then does some work.. then releases it (back to 1). You then use the setup above to create an event semaphore with an initial value of 0. Then when the call back happens, it is signaled(back to 1)..

So.. something like:

mutex.request
event.reset
start send
event.wait
mutex.release

Oobles.

Posted: Wed Jul 07, 2004 8:56 am
by ole
thanks Oobles, the transfer speed jumped up at least 10 times when the iop is not stressed !