1
0
mirror of https://github.com/adtools/clib2.git synced 2025-12-08 14:59:05 +00:00
Files
amiga-clib2/library/sas_profile.c
Olaf Barthel 1550c6fef3 - When using the wildcard expansion code for command line
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
2005-02-25 10:14:22 +00:00

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();
}