 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Sun Nov 13, 2005 5:21 pm Post subject: threading issues |
|
|
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 |
|
 |
EEUG
Joined: 13 May 2005 Posts: 136 Location: The Netherlands
|
Posted: Mon Nov 14, 2005 5:28 am Post subject: |
|
|
| ...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 |
|
 |
apache37
Joined: 04 Jun 2004 Posts: 76
|
Posted: Mon Nov 14, 2005 7:50 am Post subject: |
|
|
| 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 |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Tue Nov 15, 2005 9:19 am Post subject: |
|
|
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 |
|
 |
radad
Joined: 19 May 2004 Posts: 246 Location: Melbourne, Australia
|
Posted: Tue Nov 15, 2005 10:21 am Post subject: |
|
|
| 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 |
|
 |
apache37
Joined: 04 Jun 2004 Posts: 76
|
Posted: Tue Nov 15, 2005 6:03 pm Post subject: |
|
|
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 |
|
 |
|
|
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
|