Files
bullet3/Extras/software_cache/spu_printf_server.ppu.c
erwin.coumans dc8692ba94 Added IBM Cell SDK 2.x software_cache to Bullet/Extras. There is an option to enable it for the BulletMultiThreaded Cell version.
See USE_SOFTWARE_CACHE in Bullet\src\BulletMultiThreaded\SpuNarrowPhaseCollisionTask\SpuGatheringCollisionTask.cpp
It improves the Bullet midphase collision detection (triangle/vertex fetch)
The license is CommonPublicLicense-1.0, see included license docs.
2008-11-18 01:33:30 +00:00

205 lines
5.3 KiB
C

/*
* SCE CONFIDENTIAL
* PLAYSTATION(R)3 Programmer Tool Runtime Library 085.007
* Copyright (C) 2005 Sony Computer Entertainment Inc.
* All Rights Reserved.
*
* The SPU printf server is a PPU thread which collaborates with an SPU to
* output strings.
*
* On SPU-side, spu_printf() places the output string and arguments on a stack
* in the local storage, and passes its local-storage address with an SPU
* thread user event from SPU port 1 to PPU. On PPU-side,
* spu_thread_sprintf fetches the stack in the local stroage by DMA, and parse
* it to string-format.
*
* The SPU printf server takes charge of the tasks on PPU-side. The sequence
* of its task is as follows.
* 1. Receive events by sys_event_queue_receive()
* 2. Parse the received spu_printf stack address by spu_thread_snprintf.
* 3. Output the parsed string by printf(), and go back to step 1.
*
* Initialization of the SPU printf server and registeration of SPU threads to
* the SPU printf server is required. These can be done by
* spu_printf_server_initilize() and spu_printf_server_register().
* What they actually do is to create a PPU thread and event queue, and
* connect the SPU thread to the event queue.
*/
#include <stdio.h>
#include <sys/ppu_thread.h>
#include <sys/spu_thread.h>
#include <sys/event.h>
#include <spu_printf.h>
#include "spu_printf_server.h"
#define STACK_SIZE 4096
#define PRIO 200
static sys_ppu_thread_t thread;
static sys_event_queue_t equeue;
static sys_event_queue_attribute_t eattr;
static sys_event_port_t terminating_port;
#define TERMINATING_PORT_NAME 0xFEE1DEAD
#define SPU_PORT_PRINTF 0x1
int spu_printf_server_initialize()
{
int ret;
/* Create event */
sys_event_queue_attribute_initialize(eattr);
ret = sys_event_queue_create(&equeue, &eattr, SYS_EVENT_PORT_LOCAL, 127);
if (ret) {
printf("sys_event_queue_create faild %d\n", ret);
return -1;
}
/* Create PPU thread */
ret = sys_ppu_thread_create(&thread, spu_printf_server_entry, 0UL, PRIO,
STACK_SIZE,
SYS_PPU_THREAD_CREATE_JOINABLE,
(char*)"spu_printf_server");
if (ret) {
printf ("spu_printf_server_initialize: sys_ppu_thread_create failed %d\n", ret);
return -1;
}
/*
* Create the terminating port. This port is used only in
* sys_printf_server_finalize().
*/
ret = sys_event_port_create(&terminating_port,
SYS_EVENT_PORT_LOCAL,
TERMINATING_PORT_NAME);
if (ret) {
printf ("spu_printf_server_initialize: sys_event_port_create failed %d\n", ret);
return -1;
}
ret = sys_event_port_connect_local(terminating_port, equeue);
if (ret) {
printf ("spu_printf_server_initialize: sys_event_port_connect_local failed %d\n", ret);
return -1;
}
return 0;
}
/*
* Before call this, SPU threads which are registered finishes to send
* printf event.
*/
int spu_printf_server_finalize()
{
int ret;
/*
* Send an event from the terminating port to notify the termination to
* the SPU printf server
*/
ret = sys_event_port_send(terminating_port, 0, 0, 0);
if (ret) {
printf("sys_event_queue_cancel failed %d\n", ret);
return -1;
}
/* Wait for the termination of the SPU printf server */
uint64_t exit_status;
ret = sys_ppu_thread_join(thread, &exit_status);
if (ret) {
printf("sys_ppu_thread_join failed %d\n", ret);
return -1;
}
/* Disconnect and destroy the terminating port */
ret = sys_event_port_disconnect(terminating_port);
if (ret) {
printf("sys_event_disconnect failed %d\n", ret);
}
ret = sys_event_port_destroy(terminating_port);
if (ret) {
printf("sys_event_port_destroy failed %d\n", ret);
}
/* Destroy the event queue */
ret = sys_event_queue_destroy(equeue, 0);
if (ret) {
printf("sys_event_queue_destroy failed %d\n", ret);
return -1;
}
return 0;
}
int spu_printf_server_register(sys_spu_thread_t spu)
{
int ret;
ret = sys_spu_thread_connect_event(spu, equeue,
SYS_SPU_THREAD_EVENT_USER, SPU_PORT_PRINTF);
if (ret) {
printf("sys_spu_thread_connect_event faild %d\n", ret);
return -1;
}
return 0;
}
int spu_printf_server_unregister(sys_spu_thread_t spu)
{
int ret;
ret = sys_spu_thread_disconnect_event(spu,
SYS_SPU_THREAD_EVENT_USER, SPU_PORT_PRINTF);
if (ret) {
printf("sys_spu_thread_disconnect_event faild %d\n", ret);
return -1;
}
return 0;
}
void spu_printf_server_entry(uint64_t arg)
{
(void)arg; /* This thread does not use the argument */
int ret;
sys_event_t event;
sys_spu_thread_t spu;
for (;;) {
ret = sys_event_queue_receive(equeue, &event, SYS_NO_TIMEOUT);
if (ret) {
printf("sys_event_queue_receive failed %d\n", ret);
break;
}
/*
* If an event is sent from the terminating port, the SPU printf
* server exits.
*/
if (event.source == TERMINATING_PORT_NAME) {
printf("Finalize the SPU printf server.\n");
break;
}
spu = event.data1;
int sret = spu_thread_printf(spu, event.data3);
ret = sys_spu_thread_write_spu_mb(spu, sret);
if (ret) {
printf("sys_spu_thread_write_spu_mb failed %d\n", ret);
break;
}
}
sys_ppu_thread_exit(0);
}