mirror of
https://github.com/adtools/clib2.git
synced 2025-12-08 14:59:05 +00:00
parameters (which is by default linked in with libunix.a),
regular expressions can no longer prompt dos.library requesters
to appear. However, to be on the safe side, if you are expecting
to pass regular expressions on the command line, do not use
the wildcard expansion code such as by overriding the library
symbols with dummy functions such as are used in the file
"stdlib_wildcard_expand.c".
- Added a new variable '__open_locale' which can be used to
restrict all library functions to use the "C" language locale
rather than the current system locale settings. In addition
to that, two new functions __locale_exit() and __locale_init()
can be used to close and (re-)open the system locale at a
later time.
- Local ("static") functions are now identified by the STATIC
qualifier. This was done in preparation for changes that will
deal with global and local data and the issue of thread safety.
git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@14839 87f5fb63-7c3d-0410-a384-fd976d0f7a62
320 lines
6.4 KiB
C
320 lines
6.4 KiB
C
/*
|
|
* $Id: sas_profile.c,v 1.3 2005-02-25 10:14:21 obarthel Exp $
|
|
*
|
|
* :ts=4
|
|
*
|
|
* Adapted from SAS/C runtime library code.
|
|
*/
|
|
|
|
#include <exec/memory.h>
|
|
#include <exec/ports.h>
|
|
#include <exec/devices.h>
|
|
|
|
#include <devices/timer.h>
|
|
|
|
/****************************************************************************/
|
|
|
|
#define __NOLIBBASE__
|
|
#define __NOGLOBALIFACE__
|
|
|
|
#include <proto/exec.h>
|
|
#include <proto/timer.h>
|
|
|
|
/****************************************************************************/
|
|
|
|
extern struct Library * SysBase;
|
|
|
|
/****************************************************************************/
|
|
|
|
#include "macros.h"
|
|
#include "debug.h"
|
|
|
|
/****************************************************************************/
|
|
|
|
struct SPROFMSG
|
|
{
|
|
struct Message message;
|
|
|
|
struct Process * process;
|
|
ULONG clock_value;
|
|
char * id;
|
|
ULONG stack_pointer;
|
|
ULONG flags;
|
|
};
|
|
|
|
/****************************************************************************/
|
|
|
|
/* Values for the 'flags' field of SPROFMSG */
|
|
#define SPROF_INIT 0x00000001 /* Initialize connection */
|
|
#define SPROF_ENTRY 0x00000002 /* Function entry */
|
|
#define SPROF_EXIT 0x00000004 /* Function exit */
|
|
#define SPROF_TERM 0x00000008 /* Terminate connection, program continues */
|
|
#define SPROF_ABORT 0x00000010 /* Abort program */
|
|
#define SPROF_DENIED 0x00000020 /* Connection refused */
|
|
|
|
/****************************************************************************/
|
|
|
|
static struct Library * TimerBase;
|
|
|
|
/****************************************************************************/
|
|
|
|
static struct MsgPort * profiler_port;
|
|
static struct MsgPort * reply_port;
|
|
|
|
static struct MsgPort * time_port;
|
|
static struct timerequest * time_request;
|
|
|
|
static struct Process * this_process;
|
|
|
|
static struct EClockVal start_time;
|
|
static ULONG eclock_frequency;
|
|
static struct EClockVal last_time;
|
|
static ULONG overhead;
|
|
|
|
static ULONG num_messages_allocated;
|
|
|
|
static BOOL initialized;
|
|
|
|
/****************************************************************************/
|
|
|
|
STATIC int send_profiler_message(ULONG clock_value, char *id, ULONG flags);
|
|
STATIC ULONG get_current_time(void);
|
|
STATIC void update_overhead(void);
|
|
STATIC void __profile_init(void);
|
|
STATIC void __profile_exit(void);
|
|
|
|
/****************************************************************************/
|
|
|
|
void ASM _PROLOG(REG(a0, char *id));
|
|
void ASM _EPILOG(REG(a0, char *id));
|
|
|
|
/****************************************************************************/
|
|
|
|
STATIC int
|
|
send_profiler_message(ULONG clock_value,char * id,ULONG flags)
|
|
{
|
|
extern long __builtin_getreg(int);
|
|
|
|
struct SPROFMSG * spm;
|
|
int result = -1;
|
|
|
|
spm = (struct SPROFMSG *)GetMsg(reply_port);
|
|
if(spm != NULL)
|
|
{
|
|
if(flags != SPROF_TERM && spm->flags == SPROF_TERM)
|
|
{
|
|
PutMsg(reply_port,(struct Message *)spm);
|
|
|
|
__profile_exit();
|
|
goto out;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
spm = AllocMem(sizeof(*spm),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
|
|
if(spm == NULL)
|
|
{
|
|
__profile_exit();
|
|
goto out;
|
|
}
|
|
|
|
spm->message.mn_Length = sizeof(*spm);
|
|
spm->message.mn_ReplyPort = reply_port;
|
|
spm->process = this_process;
|
|
|
|
num_messages_allocated++;
|
|
}
|
|
|
|
spm->clock_value = clock_value;
|
|
spm->id = id;
|
|
spm->stack_pointer = __builtin_getreg(15); /* getreg(REG_A7) */
|
|
spm->flags = flags;
|
|
|
|
PutMsg(profiler_port,(struct Message *)spm);
|
|
WaitPort(reply_port);
|
|
|
|
result = 0;
|
|
|
|
out:
|
|
|
|
return(result);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
STATIC ULONG
|
|
get_current_time(void)
|
|
{
|
|
ULONG result;
|
|
|
|
ReadEClock(&last_time);
|
|
|
|
result = (last_time.ev_lo - start_time.ev_lo - overhead) / eclock_frequency;
|
|
|
|
return(result);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
STATIC void
|
|
update_overhead(void)
|
|
{
|
|
struct EClockVal ev;
|
|
|
|
ReadEClock(&ev);
|
|
|
|
overhead += (ev.ev_lo - last_time.ev_lo);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void ASM
|
|
_PROLOG(REG(a0,char * id))
|
|
{
|
|
if(initialized)
|
|
{
|
|
if(send_profiler_message(get_current_time(),id,SPROF_ENTRY) == OK)
|
|
update_overhead();
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void ASM
|
|
_EPILOG(REG(a0,char * id))
|
|
{
|
|
if(initialized)
|
|
{
|
|
if(send_profiler_message(get_current_time(),id,SPROF_EXIT) == OK)
|
|
update_overhead();
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
STATIC VOID
|
|
__profile_init(void)
|
|
{
|
|
struct SPROFMSG * spm;
|
|
BOOL ready = FALSE;
|
|
|
|
this_process = (struct Process *)FindTask(NULL);
|
|
|
|
time_port = CreateMsgPort();
|
|
if(time_port == NULL)
|
|
goto out;
|
|
|
|
time_request = (struct timerequest *)CreateIORequest(time_port,sizeof(*time_request));
|
|
if(time_request == NULL)
|
|
goto out;
|
|
|
|
if(OpenDevice(TIMERNAME,UNIT_ECLOCK,(struct IORequest *)time_request,0) != OK)
|
|
goto out;
|
|
|
|
TimerBase = (struct Library *)time_request->tr_node.io_Device;
|
|
|
|
reply_port = CreateMsgPort();
|
|
if(reply_port == NULL)
|
|
goto out;
|
|
|
|
Forbid();
|
|
|
|
profiler_port = FindPort("SPROF_Profiler");
|
|
if(profiler_port == NULL)
|
|
{
|
|
Permit();
|
|
|
|
goto out;
|
|
}
|
|
|
|
if(send_profiler_message(0,NULL,SPROF_INIT) != OK)
|
|
{
|
|
Permit();
|
|
|
|
goto out;
|
|
}
|
|
|
|
initialized = TRUE;
|
|
|
|
Permit();
|
|
|
|
while((spm = (struct SPROFMSG *)GetMsg(reply_port)) == NULL)
|
|
WaitPort(reply_port),
|
|
|
|
PutMsg(reply_port,(struct Message *)spm);
|
|
|
|
if(spm->flags == SPROF_DENIED || spm->flags == SPROF_TERM)
|
|
goto out;
|
|
|
|
eclock_frequency = ReadEClock(&start_time) / 1000;
|
|
|
|
ready = TRUE;
|
|
|
|
out:
|
|
|
|
if(NOT ready)
|
|
__profile_exit();
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
STATIC VOID
|
|
__profile_exit(void)
|
|
{
|
|
if(initialized)
|
|
{
|
|
send_profiler_message(0,NULL,SPROF_TERM);
|
|
|
|
initialized = FALSE;
|
|
}
|
|
|
|
if(reply_port != NULL)
|
|
{
|
|
struct SPROFMSG * spm;
|
|
|
|
while(num_messages_allocated > 0)
|
|
{
|
|
while((spm = (struct SPROFMSG *)GetMsg(reply_port)) == NULL)
|
|
WaitPort(reply_port),
|
|
|
|
FreeMem(spm,sizeof(*spm));
|
|
|
|
num_messages_allocated--;
|
|
}
|
|
|
|
DeleteMsgPort(reply_port);
|
|
reply_port = NULL;
|
|
}
|
|
|
|
if(time_request != NULL)
|
|
{
|
|
if(time_request->tr_node.io_Device != NULL)
|
|
CloseDevice((struct IORequest *)time_request);
|
|
|
|
DeleteIORequest((struct IORequest *)time_request);
|
|
time_request = NULL;
|
|
}
|
|
|
|
if(time_port != NULL)
|
|
{
|
|
DeleteMsgPort(time_port);
|
|
time_port = NULL;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
PROFILE_CONSTRUCTOR(profile_init)
|
|
{
|
|
__profile_init();
|
|
|
|
CONSTRUCTOR_SUCCEED();
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
PROFILE_DESTRUCTOR(profile_exit)
|
|
{
|
|
__profile_exit();
|
|
}
|