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.
Code: Select all
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)