forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

threading issues

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PS2 Development
View previous topic :: View next topic  
Author Message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Sun Nov 13, 2005 5:21 pm    Post subject: threading issues Reply with quote

I am working on a multithreaded app. It crashes occasionally and I not completely sure why. It seems to happen when I make an rpc call.

Are the rpc and dma modules thread safe? Can two threads make an rpc call or dma at the same time? And even if they do I assume they get queued up at the iop end.
Back to top
View user's profile Send private message
EEUG



Joined: 13 May 2005
Posts: 136
Location: The Netherlands

PostPosted: Mon Nov 14, 2005 5:28 am    Post subject: Reply with quote

...well, in SMS these threads are a pain in the ... Somehow they work now and I'm quite afraid to touch anything :). I would try to put semaphores to guard "critical" sections of the code...
Back to top
View user's profile Send private message
apache37



Joined: 04 Jun 2004
Posts: 76

PostPosted: Mon Nov 14, 2005 7:50 am    Post subject: Reply with quote

Is there a good reference where I can learn about threads/semaphores on ps2? I would like to know if variables can be protected or locked as well as joining threads.
Back to top
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Tue Nov 15, 2005 9:19 am    Post subject: Reply with quote

I found the issue, it appears that rpc calls are not thread safe, at least not if they share the same t_SifRpcClientData . Not sure about dma but I haven't any issues with it yet.

Here are the changes:
Code:
Index: audsrv/include/audsrv.h
===================================================================
--- audsrv/include/audsrv.h   (revision 1232)
+++ audsrv/include/audsrv.h   (working copy)
@@ -43,6 +43,7 @@
 #define AUDSRV_ERR_NO_MORE_CHANNELS        0x0007
 
 #define AUDSRV_ERR_FAILED_TO_LOAD_ADPCM    0x0010
+#define AUDSRV_ERR_FAILED_TO_CREATE_SEMA    0x0011
 
 /** structure used to set new format */
 typedef struct audsrv_fmt_t
Index: audsrv/src/audsrv_rpc.c
===================================================================
--- audsrv/src/audsrv_rpc.c   (revision 1232)
+++ audsrv/src/audsrv_rpc.c   (working copy)
@@ -35,6 +35,7 @@
 
 static int initialized = 0;
 static int audsrv_error = AUDSRV_ERR_NOERROR;
+static int completion_sema;
 
 /* nasty forwards */
 static void fillbuf_requested(void *pkt, void *arg);
@@ -48,6 +49,11 @@
    audsrv_error = err;
 }
 
+static void _audsrv_intr()
+{
+   iSignalSema(completion_sema);
+}
+
 /** Returns the last error audsrv raised
     @returns error code
 */
@@ -63,8 +69,10 @@
 */
 static int call_rpc_1(int func, int arg)
 {
+   WaitSema(completion_sema);
+
    sbuff[0] = arg;
-   SifCallRpc(&cd0, func, 0, sbuff, 1*4, sbuff, 4, 0, 0);
+   SifCallRpc(&cd0, func, 0, sbuff, 1*4, sbuff, 4, _audsrv_intr, 0);
    FlushCache(0);
 
    set_error(sbuff[0]);
@@ -79,9 +87,11 @@
 */
 static int call_rpc_2(int func, int arg1, int arg2)
 {
+   WaitSema(completion_sema);
+
    sbuff[0] = arg1;
    sbuff[1] = arg2;
-   SifCallRpc(&cd0, func, 0, sbuff, 2*4, sbuff, 4, 0, 0);
+   SifCallRpc(&cd0, func, 0, sbuff, 2*4, sbuff, 4, _audsrv_intr, 0);
    FlushCache(0);
 
    set_error(sbuff[0]);
@@ -93,7 +103,9 @@
 */
 int audsrv_quit()
 {
-   SifCallRpc(&cd0, AUDSRV_QUIT, 0, sbuff, 1*4, sbuff, 4, 0, 0);
+   WaitSema(completion_sema);
+
+   SifCallRpc(&cd0, AUDSRV_QUIT, 0, sbuff, 1*4, sbuff, 4, _audsrv_intr, 0);
    set_error(AUDSRV_ERR_NOERROR);
    return 0;
 }
@@ -109,10 +121,12 @@
 */
 int audsrv_set_format(struct audsrv_fmt_t *fmt)
 {
+   WaitSema(completion_sema);
+
    sbuff[0] = fmt->freq;
    sbuff[1] = fmt->bits;
    sbuff[2] = fmt->channels;
-   SifCallRpc(&cd0, AUDSRV_SET_FORMAT, 0, sbuff, 3*4, sbuff, 4, 0, 0);
+   SifCallRpc(&cd0, AUDSRV_SET_FORMAT, 0, sbuff, 3*4, sbuff, 4, _audsrv_intr, 0);
    FlushCache(0);
    set_error(sbuff[0]);
    return sbuff[0];
@@ -268,11 +282,13 @@
    maxcopy = sizeof(sbuff) - sizeof(int);
    while (bytes > 0)
    {
+      WaitSema(completion_sema);
+
       copy = MIN(bytes, maxcopy);
       sbuff[0] = copy;
       memcpy(&sbuff[1], chunk, copy);
       packet_size = copy + sizeof(int);
-      SifCallRpc(&cd0, AUDSRV_PLAY_AUDIO, 0, sbuff, packet_size, sbuff, 1*4, 0, 0);
+      SifCallRpc(&cd0, AUDSRV_PLAY_AUDIO, 0, sbuff, packet_size, sbuff, 1*4, _audsrv_intr, 0);
       FlushCache(0);
 
       if (sbuff[0] < 0)
@@ -331,6 +347,12 @@
       nopdelay();
    }
 
+   ee_sema_t compSema;
+   compSema.init_count = 1;
+   compSema.max_count = 1;
+   compSema.option = 0;
+   completion_sema = CreateSema(&compSema);
+
    SifCallRpc(&cd0, AUDSRV_INIT, 0, sbuff, 64, sbuff, 64, 0, 0);
    FlushCache(0);
    ret = sbuff[0];
@@ -374,6 +396,8 @@
    SifDmaTransfer_t sifdma;
    int id;
 
+   WaitSema(completion_sema);
+
    iop_addr = SifAllocIopHeap(size);
    if (iop_addr == 0)
    {
@@ -393,7 +417,7 @@
    sbuff[1] = size;
    sbuff[2] = (int)adpcm; /* use as id */
 
-   SifCallRpc(&cd0, AUDSRV_LOAD_ADPCM, 0, sbuff, 12, sbuff, 16, 0, 0);
+   SifCallRpc(&cd0, AUDSRV_LOAD_ADPCM, 0, sbuff, 12, sbuff, 16, _audsrv_intr, 0);
    SifFreeIopHeap(iop_addr);
 
    if(sbuff[0] != 0)
Back to top
View user's profile Send private message
radad



Joined: 19 May 2004
Posts: 246
Location: Melbourne, Australia

PostPosted: Tue Nov 15, 2005 10:21 am    Post subject: Reply with quote

apache37 wrote:
Is there a good reference where I can learn about threads/semaphores on ps2? I would like to know if variables can be protected or locked as well as joining threads.


There is only one synchronisation object on the PS2, they call it a sema. It is a basic atomic increment/decrement object with a wait state when it reaches zero.

You can use it like a traditional simple mutex. Simple meaning it doesn't support recursive locking.

You can use it like a traditional simple semaphore. Simple meaning only one waiting thread will wake up. Also if no thread is currently waiting then the next thread to wait will wake up immediately.

You can also use it build up more complex mutexes. One which support recursive locking.

Or to buid up complex semaphores. Ones which can wake all waiting threads. And only wake currently waiting threads.

Lastly there is no direct support for thread joining. You can build your own from this basic sema though. Just get the thread to signal the sema when it exits.
Back to top
View user's profile Send private message
apache37



Joined: 04 Jun 2004
Posts: 76

PostPosted: Tue Nov 15, 2005 6:03 pm    Post subject: Reply with quote

Than you for the response. I think I can achieve what I need with simple threads for now.

Also is there a way to kill all threads in the ps2 even if I didnt start them?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PS2 Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group