| View previous topic :: View next topic |
| Author |
Message |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Tue May 20, 2008 1:00 am Post subject: Exception handling capabilities |
|
|
I'm developing a small C++ library that heavily uses inheritance and polymorphinsm, and depends upon exceptions implementation. I'm not using std in any way (i'm not satisfied of it on certain technical and license aspects) but a quick look into some source code made me aim my attention on -fno-exceptions flag (that -if i understood well- makes code workaround the lack of hw exceptions handling background with a serie of if-like structures). Speaking of PSP-specific code, i noticed -fno-exceptions is ALWAYS set in all sources i inspected. Why? And: is PSP technically capable of handling exceptions "the classical way"??
Thanks for your attention
jean |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Tue May 20, 2008 5:12 am Post subject: |
|
|
the lack of hw exceptions ?
no, -fno-exceptions option has nothing about hardware exceptions. This is merely two different definitions indeed. c++ exceptions are used through "try/catch".
if I'm not wrong, to have c++ exception handling (with RTTI for dynamic_cast as well), you need to provide specifically some files with run-time functions to handle c++ exceptions properly. I guess we use -fno-exceptions because those files are probably not adapted so they could work on PSP.
To be frank, I'm not sure having -fno-exception(s) would prevent you from using "try/catch" (using for instance a simple setjmp/longjmp version) because I never tried so |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Tue May 20, 2008 8:30 am Post subject: |
|
|
| sorry, that "hw" before "exception" was not intended...it escaped from my fingers :) !! (i was to mean the "traditional" built-in way of handling exceptions) In fact the only thing i care is performance when making heavy use of software try..catch that surely has nothing to do with hw exception like a cpu issued "div by zero" (even if visual c++ seems to merge the two things in a weird manner...) Are you basically saying "if you don't try, you'll never know" ? |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Tue May 20, 2008 8:41 am Post subject: |
|
|
| jean wrote: | | Are you basically saying "if you don't try, you'll never know" ? |
kinda :)
I'm not sure a lot of us were paying any attention about -fno-exceptions -no-rtti and were using them because they were already set in template or sample Makefiles.
EDIT:
"try/catch" are accepted when compiled but there is no special generated code to handle c++ exception (as if they were comments). However, "throw" is refused : "error: exception handling disabled, use -fexceptions to enable" |
|
| Back to top |
|
 |
pspZorba
Joined: 22 Sep 2007 Posts: 156 Location: NY
|
Posted: Tue May 20, 2008 9:05 am Post subject: |
|
|
| Quote: | | I'm not sure a lot of us were paying any attention about -fno-exceptions -no-rtti and were using them because they were already set in template or sample Makefiles. |
actually generally rtti slows the exe and makes it fatter. And the cases in which you really need them are rather rare.
and even if try/catch is more usefull, unfortunatly it makes the code unreadable (IMHO). That's probably why nobody never change those options. _________________ --pspZorba--
NO to K1.5 ! |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Wed May 21, 2008 6:52 pm Post subject: |
|
|
| Quote: | | That's probably why nobody never change those options. |
Ok, I'll try to use -fexceptions .... |
|
| Back to top |
|
 |
Heimdall
Joined: 10 Nov 2005 Posts: 259 Location: Netherlands
|
Posted: Wed Feb 18, 2009 11:46 pm Post subject: |
|
|
Any success with exception handling? I'm trying to get it work but aparently it just hangs, here's the code:
| Code: | #include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
/* Define printf, just to make typing easier */
#define printf pspDebugScreenPrintf
/* Define the module info section */
PSP_MODULE_INFO("cppException", 0, 1, 1);
/* Define the main thread's attribute value (optional) */
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
#include <exception>
using namespace std;
class myexception: public exception
{
virtual const char* what() const throw()
{
return "My exception happened";
}
} myex;
int main (void)
{
pspDebugScreenInit();
SceCtrlData pad;
try
{
throw myex;
}
catch (exception& e)
{
printf("%s\n", e.what());
}
printf("\nPress X to quit.\n");
for (;;)
{
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS)
break;
}
sceKernelExitGame();
return 0;
}
|
Am i doing something wrong? |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Thu Feb 19, 2009 7:25 pm Post subject: |
|
|
Since then, i used exceptions extensively and without issues... Don't know, maybe your makefile... let me look into an old project of mine....
makefile:
| Code: | TARGET = SERIAL_ROBOT
OBJS = main.o Command.o GetMotorCommand.o GetSensorCommand.o MotorPacket.o Packet.o PacketFactory.o RcvGetMotorPacket.o RcvGetSensorPacket.o SerialComm.o serialPacketReaderMachine.o SetMotorCommand.o SndGetMotorPacket.o SndGetSensorPacket.o SndSetMotorPacket.o sioDriver.o callbacks.o MotorController.o
BUILD_PRX=1
PSP_FW_VERSION=390
INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fexceptions -fno-rtti -D "__PSP"
ASFLAGS = $(CFLAGS)
LIBS = -lstdc++
LIBDIR =
LDFLAGS =
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = SERIAL_ROBOT
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak |
i specified my own type of base exception, never inherited from std::exception
exceptions.hpp:
| Code: | #ifndef __Exceptions_H__
#define __Exceptions_H__
/// \brief RException class.
class RException
{
};
/// \brief CommInitException class.
class CommInitException: public RException
{
};
/// \brief WrongMachineStateException class.
class WrongMachineStateException: public RException
{
};
// ...etc...
#endif // __Exceptions_H__
|
Anyhow, where does the code hang? You can easily track the exact point setting some printf(); around: if it does hang on throw, try to write mujltiple catch statements ending with the (...) one just to make that code not hang, then you can dig the reason why you con't catch that type.
| Code: | try
{
// throwing code
}
catch (specializedException1 e)
{
// ...
}
catch (specializedException2 e)
{
// ...
}
catch (baseException e)
{
// ...
}
catch (...) // you can never know what can happen...
{
// ...
}
|
|
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Fri Feb 20, 2009 9:41 am Post subject: |
|
|
| If i'm not wrong, you need to provide a c++ exception handling implementation for PSP in gcc source. Gcc can generate calls to some functions and you need to implement them as they may be dependent on OS. As far as i know psp-gcc has no such implementation. |
|
| Back to top |
|
 |
Heimdall
Joined: 10 Nov 2005 Posts: 259 Location: Netherlands
|
Posted: Fri Feb 20, 2009 4:53 pm Post subject: |
|
|
that was what i thought hlide, and started to add a simple threading implementation to gcc based on an old haiku-os implementation that only tels gcc that this device can handle mutexes, however when i throw an exception the mutex locks everything (i guess i got it all wrong from the gcc barely existing docs).
I've reverted my patch and exceptions work out of the box like jean says both with base user defined exception or using the sdt::exception one.
I've tested with gcc 4.3.3 and newlib 1.16 / gcc 4.3.3 and newlib 1.17 |
|
| Back to top |
|
 |
Torch

Joined: 28 May 2008 Posts: 842
|
Posted: Fri Feb 20, 2009 5:16 pm Post subject: |
|
|
| Can someone explain exactly how to set this up and get try-catch working for a normal makefile? |
|
| Back to top |
|
 |
Heimdall
Joined: 10 Nov 2005 Posts: 259 Location: Netherlands
|
Posted: Fri Feb 20, 2009 7:50 pm Post subject: |
|
|
This is my test cpp file:
| Code: | #include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
/* Define printf, just to make typing easier */
#define printf pspDebugScreenPrintf
/* Define the module info section */
PSP_MODULE_INFO("cppException", 0, 1, 1);
/* Define the main thread's attribute value (optional) */
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | HREAD_ATTR_VFPU);
#include <exception>
using namespace std;
class myexception: public exception
{
virtual const char* what() const throw()
{
return "My exception happened";
}
} myex;
int main (void)
{
pspDebugScreenInit();
SceCtrlData pad;
try
{
throw myex;
}
catch (exception& e)
{
printf("%s\n", e.what());
}
printf("\nPress X to quit.\n");
for (;;)
{
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS)
break;
}
sceKernelExitGame();
return 0;
}
|
and this is my makefile:
| Code: | TARGET = CppException
OBJS = main.o
LIBS = -lstdc++
INCDIR =
CFLAGS = -G0 -Wall -O2
CXXFLAGS = $(CFLAGS) -fno-rtti -fexceptions
SFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS =
XTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = C++ Exception Sample
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
|
the the usual, make, copy eboot and run :) on the makefile the only difference is that i define -fexceptions instead of -fno-exceptions on the CXXFLAGS variable, and obviously link againts -lstdc++ because this is a cpp sample.
PS: I'm adding this sample to the SDK in my builds. |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Sat Feb 21, 2009 5:41 am Post subject: |
|
|
| Heimdall wrote: | that was what i thought hlide, and started to add a simple threading implementation to gcc based on an old haiku-os implementation that only tels gcc that this device can handle mutexes, however when i throw an exception the mutex locks everything (i guess i got it all wrong from the gcc barely existing docs).
I've reverted my patch and exceptions work out of the box like jean says both with base user defined exception or using the sdt::exception one.
I've tested with gcc 4.3.3 and newlib 1.16 / gcc 4.3.3 and newlib 1.17 |
so you can use -fexception but not rtti (dynamic_cast<> unusable). If a bus error occurs, do you catch a C++ exception ? |
|
| Back to top |
|
 |
Heimdall
Joined: 10 Nov 2005 Posts: 259 Location: Netherlands
|
Posted: Sat Feb 21, 2009 6:06 am Post subject: |
|
|
| hlide wrote: | | so you can use -fexception but not rtti (dynamic_cast<> unusable). If a bus error occurs, do you catch a C++ exception ? |
It works for user defined exceptions that are programatically thrown, meaning all classes that extend std::exception (or not, like jean example ) can be throw and catched. For bus errors I haven't tested those thoroughly. For those I need to have at least mutexes working, but my gcc code failed:
| Code: |
static inline int
__gthread_mutex_lock (__gthread_mutex_t * mutex)
{
int stat;
int thid;
int own;
int rtn;
if (mutex->semid < 0)
{
mutex->semid = sceKernelCreateSema ("libgccMutex", 0x0100, 1, 1, 0);
}
thid = sceKernelGetThreadId ();
stat = sceKernelCpuSuspendIntr ();
if (mutex->owner < 0)
{
mutex->owner = thid;
own = 1;
}
else
own = 0;
sceKernelCpuResumeIntr (stat);
if (own || mutex->owner != thid)
{
rtn = sceKernelWaitSema (mutex->semid, 1, 0);
}
else
{
mutex->count++;
rtn = 0;
}
return rtn;
}
static inline int
__gthread_mutex_trylock (__gthread_mutex_t * mutex)
{
int stat;
int thid;
int own;
int rtn;
if (mutex->semid < 0)
{
mutex->semid = sceKernelCreateSema ("libgccMutex", 0x0100, 1, 1, 0);
}
thid = sceKernelGetThreadId ();
stat = sceKernelCpuSuspendIntr ();
if (mutex->owner < 0)
{
mutex->owner = thid;
own = 1;
}
else
own = 0;
sceKernelCpuResumeIntr (stat);
if (own || mutex->owner != thid)
{
rtn = sceKernelPollSema (mutex->semid, 1);
}
else
{
mutex->count++;
rtn = 0;
}
return rtn;
}
static inline int
__gthread_mutex_unlock (__gthread_mutex_t * mutex)
{
int rtn;
if (mutex->owner == sceKernelGetThreadId ())
{
if (mutex->count > 0 && --mutex->count == 0)
{
rtn = sceKernelSignalSema (mutex->semid, 1);
mutex->owner = -1;
sceKernelDeleteSema (mutex->semid);
mutex->semid = -1;
}
}
else if (mutex->owner >= 0)
{
rtn = sceKernelSignalSema (mutex->semid, 1);
mutex->owner = -1;
sceKernelDeleteSema (mutex->semid);
mutex->semid = -1;
mutex->count = 0;
}
else
rtn = -1;
return rtn;
}
|
I tryed to get it working like they did on the Haiku project before they had a pthread implementation... but this is wrong, because this will cause a hand on every throw clause.
Maybe I understood the semaphore api wrong or passing the wrong arguments either...[/code] |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Sat Feb 21, 2009 7:27 am Post subject: |
|
|
if you need a mutex, why not using those :
sceKernelCreateMutex
sceKernelDeleteMutex
sceKernelLockMutex
sceKernelLockMutexCB
sceKernelTryLockMutex
sceKernelUnlockMutex |
|
| Back to top |
|
 |
Heimdall
Joined: 10 Nov 2005 Posts: 259 Location: Netherlands
|
Posted: Sat Feb 21, 2009 7:45 pm Post subject: |
|
|
| i guess you're right, i didn't look for the mutex api, and it contains what gcc needs :) I'll try that... |
|
| Back to top |
|
 |
Heimdall
Joined: 10 Nov 2005 Posts: 259 Location: Netherlands
|
Posted: Mon Feb 23, 2009 6:34 pm Post subject: |
|
|
| hlide wrote: | if you need a mutex, why not using those :
sceKernelCreateMutex
sceKernelDeleteMutex
sceKernelLockMutex
sceKernelLockMutexCB
sceKernelTryLockMutex
sceKernelUnlockMutex |
humm... those functions are only available in the SDK or DA SDK meaning I don't know the method signature... more work to do... |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Tue Feb 24, 2009 6:39 am Post subject: |
|
|
| Heimdall wrote: | | hlide wrote: | if you need a mutex, why not using those :
sceKernelCreateMutex
sceKernelDeleteMutex
sceKernelLockMutex
sceKernelLockMutexCB
sceKernelTryLockMutex
sceKernelUnlockMutex |
humm... those functions are only available in the SDK or DA SDK meaning I don't know the method signature... more work to do... |
ok,
| Code: |
SceUID sceKernelCreateMutex(
const char *name,
unsigned int attributes, /* using a FIFO (0) or PRIORITIZED (256) THREAD QUEUE */
int initial_count, /* the initial count of mutex when created */
void *optional_parameters /* just pass 0 */
); // returns Mutex UID if >0
int sceKernelDeleteMutex(
SceUID id /* Mutex UID */
); // returns 0 if OK
int sceKernelLockMutex(
SceUID id, /* Mutex UID */
int lock_count, /* > 0 */
unsigned int *timeout /* In : 0 if no timeout or a pointer to a placeholder containing the max time value in ms. Out: time remaining when mutex is acquired */
); // returns 0 if OK or 0x800201a8 if timeout
int sceKernelLockMutexCB(
SceUID id, /* Mutex UID */
int lock_count, /* > 0 */
unsigned int *timeout /* In : 0 if no timeout or a pointer to a placeholder containing the max time value in ms. Out: time remaining when mutex is acquired */
); // returns 0 if OK or 0x800201a8 if timeout
int sceKernelTryLockMutex(
SceUID id, /* Mutex UID */
int lock_count /* > 0 */
); // returns 0x800201c4 if current thread failed to own mutex or 0 if success
int sceKernelUnlockMutex(
SceUID id, /* Mutex UID */
int unlock_count /* >= 0 */
); // returns 0 if OK
|
|
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Mon Mar 09, 2009 8:42 am Post subject: |
|
|
Ok let's imagine we have a kernel prx wich installs a exception handler and that we can call a handler individually for each different cause :
void exc_install_handler(int cause, void (*handler)(int, exc_t *exc));
Basically, the general exception we installed through a kernel prx will be called when an exception is raised. This exception will call the right handler in an array where the cause is index. The previous function exported by the kernel prx allows us to define an handler per cause : bus error, FPU error, etc.
Now, we can define some C++ exceptions this way :
| Code: |
class HardwareException
{
public:
HardwareException(exc_t *exc)
{
m_exc = exc;
}
protected:
exc_t m_exc;
};
template <class ExceptionClass> class ExceptionTranslator
{
private:
class SingletonTranslator
{
public:
SingletonTranslator()
{
exc_install_handler(ExceptionClass::cause(), handler);
}
static void handler(int, exc_t *exc)
{
throw ExceptionClass(exc);
}
};
public:
ExceptionTranslator()
{
static SingletonTranslator s_obj_Translator;
}
};
// An example for BUS_ERROR
class SegmentationFault : public HardwareException, public exception
{
public:
SegmentationFault(exc_t *exc) : HardwareException(exc), exception() {}
static int cause() { return BUS_ERROR; }
...
};
ExceptionTranslator<SegmentationFault> g_obj_SegmentationFaultTranslator;
// An example for FPU_ERROR
class FloatingPointException : public HardwareException, public exception
{
public:
FloatingPointException(exc_t *exc) : HardwareException(exc), exception() {}
static int cause() { return FPU_ERROR; }
...
};
ExceptionTranslator<FloatingPointException> g_obj_FloatingPointExceptionTranslator;
|
|
|
| Back to top |
|
 |
coolkehon
Joined: 20 Oct 2008 Posts: 355
|
Posted: Tue Mar 10, 2009 10:32 am Post subject: |
|
|
| sorry to intrude on this post but how can i use c++ in a kernel prx i have been having a problem with that for the longest it never compiles |
|
| Back to top |
|
 |
hlide
Joined: 10 Sep 2006 Posts: 750
|
Posted: Tue Mar 10, 2009 9:14 pm Post subject: |
|
|
huh this is just an example to show how we could handle C++ exception to throw when an hardware exception occurs (access to null pointer, divide error, etc.) which are not catchable with the actual psp-gcc.
I think if we could tweak the source of exception.prx (not sure about the name) which is a homebrew kernel prx to allow a user application to catch every hardware exception and dump the details with a blue screen of death.
I think we can modify it so we can add an array of exception handlers and an exported function to install a user handler to call. Nothing is in C++.
The code I posted in C++ shows how in our c++ application we can try to make hardware exceptions turn into c++ exception. To do so, we could load this kernel prx and import such a function to install a user handler per hardware exception category to call the right "throw".
This is just an idea for those who are interested with.
Last edited by hlide on Tue Mar 10, 2009 10:45 pm; edited 1 time in total |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Tue Mar 10, 2009 9:31 pm Post subject: |
|
|
| very very nice...thank you for sharing: will surely use something like this. |
|
| Back to top |
|
 |
|