mirror of
https://github.com/deadw00d/AROS.git
synced 2026-03-17 07:41:59 +00:00
302 lines
9.8 KiB
C
302 lines
9.8 KiB
C
/*
|
||
Copyright (C) 2023-2025, The AROS Development Team. All rights reserved.
|
||
*/
|
||
|
||
#include <proto/exec.h>
|
||
#include <proto/kernel.h>
|
||
#include <proto/dos.h>
|
||
#include <proto/utility.h>
|
||
#include <proto/timer.h>
|
||
|
||
#include <proto/log.h>
|
||
#include <proto/alib.h>
|
||
|
||
#include <aros/libcall.h>
|
||
#include <aros/asmcall.h>
|
||
#include <aros/symbolsets.h>
|
||
|
||
#include <resources/log.h>
|
||
|
||
#include <stddef.h>
|
||
#include <string.h>
|
||
|
||
#include "log_intern.h"
|
||
|
||
#include LC_LIBDEFS_FILE
|
||
|
||
extern BOOL GM_UNIQUENAME(HaveDOS)(LIBBASETYPEPTR LIBBASE);
|
||
extern BOOL GM_UNIQUENAME(OpenUtility)(LIBBASETYPEPTR LIBBASE);
|
||
extern BOOL GM_UNIQUENAME(HaveTimer)(LIBBASETYPEPTR LIBBASE);
|
||
|
||
#define DOSBase LIBBASE->lrb_DosBase
|
||
#define TimerBase LIBBASE->lrb_TimerIOReq.tr_node.io_Device
|
||
#define UtilityBase LIBBASE->lrb_UtilityBase
|
||
#define KernelBase LIBBASE->lrb_KernelBase
|
||
|
||
AROS_LH1(VOID, logLockEntries,
|
||
AROS_LHA(ULONG, flags, D0),
|
||
LIBBASETYPEPTR, LIBBASE, 13, log)
|
||
{
|
||
AROS_LIBFUNC_INIT
|
||
struct ExecBase *SysBase = GM_SYSBASE_FIELD(LIBBASE);
|
||
ObtainSemaphore(&LIBBASE->lrb_ReentrantLock);
|
||
AROS_LIBFUNC_EXIT
|
||
}
|
||
|
||
AROS_LH1(VOID, logUnlockEntries,
|
||
AROS_LHA(ULONG, flags, D0),
|
||
LIBBASETYPEPTR, LIBBASE, 15, log)
|
||
{
|
||
AROS_LIBFUNC_INIT
|
||
struct ExecBase *SysBase = GM_SYSBASE_FIELD(LIBBASE);
|
||
ReleaseSemaphore(&LIBBASE->lrb_ReentrantLock);
|
||
AROS_LIBFUNC_EXIT
|
||
}
|
||
|
||
AROS_LH1(APTR, logNextEntry,
|
||
AROS_LHA(APTR *, entryHandle, A0),
|
||
LIBBASETYPEPTR, LIBBASE, 14, log)
|
||
{
|
||
AROS_LIBFUNC_INIT
|
||
|
||
struct logEntryPrivate *leP;
|
||
struct logEntry *le;
|
||
|
||
if (entryHandle) {
|
||
if (*entryHandle == (APTR)LOGEntry_First) {
|
||
leP = (struct logEntryPrivate *)GetHead(&LIBBASE->lrb_LRProvider.lrh_Entries);
|
||
if (leP)
|
||
*entryHandle = &leP->le_Node;
|
||
else
|
||
*entryHandle = (APTR)LOGEntry_Last;
|
||
}
|
||
else if (*entryHandle != (APTR)LOGEntry_Last) {
|
||
le = *entryHandle;
|
||
if (le->le_Node.ln_Type == NT_LOGENTRY) {
|
||
leP = (struct logEntryPrivate *)((IPTR)le - offsetof(struct logEntryPrivate, le_Node));
|
||
leP = (struct logEntryPrivate *)GetSucc(leP);
|
||
if (leP)
|
||
*entryHandle = &leP->le_Node;
|
||
else
|
||
*entryHandle = (APTR)LOGEntry_Last;
|
||
}
|
||
else
|
||
*entryHandle = (APTR)LOGEntry_Last;
|
||
} else {
|
||
// Return the last entry if called with LOGEntry_Last
|
||
}
|
||
return *entryHandle;
|
||
}
|
||
return NULL;
|
||
|
||
AROS_LIBFUNC_EXIT
|
||
}
|
||
|
||
AROS_LH2(IPTR, logGetEntryAttrs,
|
||
AROS_LHA(APTR, entryHandle, A0),
|
||
AROS_LHA(struct TagItem *, tags, A1),
|
||
LIBBASETYPEPTR, LIBBASE, 9, log)
|
||
{
|
||
AROS_LIBFUNC_INIT
|
||
|
||
struct logEntry *le = (struct logEntry *)entryHandle;
|
||
IPTR count = 0;
|
||
|
||
if (le && (le->le_Node.ln_Type == NT_LOGENTRY) && (GM_UNIQUENAME(OpenUtility)(LIBBASE))) {
|
||
struct logEntryPrivate *leP;
|
||
struct TagItem *ti;
|
||
leP = (struct logEntryPrivate *)((IPTR)le - offsetof(struct logEntryPrivate, le_Node));
|
||
|
||
if((ti = FindTagItem(LOGMA_Flags, tags))) {
|
||
*((ULONG *) ti->ti_Data) = (leP->lectx_Flags & ~LOGM_Flag_PrivateMask);
|
||
count++;
|
||
}
|
||
if((ti = FindTagItem(LOGMA_DateStamp, tags))) {
|
||
*((struct DateStamp **) ti->ti_Data) = &leP->le_DateStamp;
|
||
count++;
|
||
}
|
||
if((ti = FindTagItem(LOGMA_EventID, tags))) {
|
||
*((ULONG *) ti->ti_Data) = leP->le_eid;
|
||
count++;
|
||
}
|
||
if((ti = FindTagItem(LOGMA_Origin, tags))) {
|
||
*((char**) ti->ti_Data) = leP->lectx_Originator;
|
||
count++;
|
||
}
|
||
if((ti = FindTagItem(LOGMA_Component, tags))) {
|
||
if (leP->lep_Producer) {
|
||
struct LogResHandle *lrHandle = (struct LogResHandle *)leP->lep_Producer;
|
||
*((char**) ti->ti_Data) = lrHandle->lrh_Node.ln_Name;
|
||
count++;
|
||
}
|
||
}
|
||
if((ti = FindTagItem(LOGMA_SubComponent, tags))) {
|
||
*((char**) ti->ti_Data) = leP->lep_Node.ln_Name;
|
||
count++;
|
||
}
|
||
if((ti = FindTagItem(LOGMA_LogTag, tags))) {
|
||
*((char**) ti->ti_Data) = leP->le_Node.ln_Name;
|
||
count++;
|
||
}
|
||
if((ti = FindTagItem(LOGMA_Entry, tags))) {
|
||
*((char**) ti->ti_Data) = leP->le_Entry;
|
||
count++;
|
||
}
|
||
}
|
||
|
||
return count;
|
||
|
||
AROS_LIBFUNC_EXIT
|
||
}
|
||
|
||
/*****************************************************************************
|
||
|
||
NAME */
|
||
|
||
AROS_LH7(struct logEntry *, logAddEntryA,
|
||
|
||
/* SYNOPSIS */
|
||
AROS_LHA(ULONG, flags, D0),
|
||
AROS_LHA(APTR, loghandle, A0),
|
||
AROS_LHA(STRPTR, sub, A1),
|
||
AROS_LHA(STRPTR, src, A2),
|
||
AROS_LHA(ULONG, eventid, D1),
|
||
AROS_LHA(STRPTR, fmtstr, A3),
|
||
AROS_LHA(RAWARG, fmtdata, A4),
|
||
|
||
/* LOCATION */
|
||
LIBBASETYPEPTR, LIBBASE, 10, log)
|
||
|
||
/* FUNCTION
|
||
Creates and queues a new log entry associated with the given
|
||
logging handle. The entry includes timestamp, event ID,
|
||
optional subsystem/source strings, originator information,
|
||
and a formatted message string built from 'fmtstr' and 'fmtdata'.
|
||
|
||
INPUTS
|
||
flags - Logging flags and priority level (LOGM_*).
|
||
loghandle - Handle to an open log resource (struct LogResHandle *).
|
||
sub - Optional subsystem string, may be NULL.
|
||
src - Optional source string, may be NULL.
|
||
eventid - User-supplied event identifier.
|
||
fmtstr - Format string for the log message.
|
||
fmtdata - Argument data matching the format string.
|
||
|
||
RESULT
|
||
Pointer to a logEntry structure if successful,
|
||
or NULL if the entry could not be created.
|
||
|
||
NOTES
|
||
The returned logEntry is owned by log.resource and should not
|
||
be modified or freed by the caller. The timestamp source depends
|
||
on availability of DOS, timer.device, or kernel facilities.
|
||
|
||
EXAMPLE
|
||
struct logEntry *e = logAddEntryA(LOGM_Flag_Info, myLogHandle,
|
||
"filesystem", "disk.device", 42,
|
||
"Mounted volume %s", (RAWARG)"DH0:");
|
||
|
||
BUGS
|
||
Kernel timestamp support is incomplete (marked TODO in source).
|
||
|
||
SEE ALSO
|
||
|
||
INTERNALS
|
||
Allocates a logEntryPrivate from the handle<6C>s pool.
|
||
Uses logCopyStrFmtA() to duplicate the formatted message.
|
||
Links the entry into the handle<6C>s list unless producer is provider.
|
||
Posts an EHMB_ADDENTRY message to the log resource service port.
|
||
|
||
******************************************************************************/
|
||
{
|
||
AROS_LIBFUNC_INIT
|
||
|
||
struct LogResHandle *lrHandle = (struct LogResHandle *)loghandle;
|
||
if ((LIBBASE->lrb_Task) && (lrHandle)) {
|
||
struct ExecBase *SysBase = GM_SYSBASE_FIELD(LIBBASE);
|
||
struct logEntryPrivate *leP;
|
||
if ((leP = AllocVecPooled(lrHandle->lrh_Pool, sizeof(struct logEntryPrivate)))) {
|
||
memset(leP, 0, sizeof(struct logEntryPrivate));
|
||
leP->lep_Node.ln_Pri = (flags & LOGM_Flag_LevelMask);
|
||
leP->lectx_Level = flags;
|
||
leP->lep_Producer = loghandle;
|
||
|
||
if((leP->le_Entry = logCopyStrFmtA(fmtstr, fmtdata))) {
|
||
struct Task *thisTask = FindTask(NULL);
|
||
|
||
if (sub)
|
||
leP->lep_Node.ln_Name = logCopyStr(sub);
|
||
|
||
if (src)
|
||
leP->le_Node.ln_Name = logCopyStr(src);
|
||
|
||
leP->lectx_Originator = logCopyStrFmt("0x%p %s", thisTask, ((struct Node *)thisTask)->ln_Name);
|
||
leP->le_eid = eventid;
|
||
|
||
if(GM_UNIQUENAME(HaveDOS)(LIBBASE)) {
|
||
DateStamp(&leP->le_DateStamp);
|
||
leP->lectx_Flags &= ~(LOGF_Flag_Private_STMPTimer|LOGF_Flag_Private_STMPKrn);
|
||
} else if (GM_UNIQUENAME(HaveTimer)(LIBBASE)) {
|
||
struct timerequest tr;
|
||
CopyMem(&LIBBASE->lrb_TimerIOReq, &tr, sizeof(struct timerequest));
|
||
tr.tr_node.io_Command = TR_GETSYSTIME;
|
||
DoIO((struct IORequest *) &tr);
|
||
leP->le_DateStamp.ds_Days = tr.tr_time.tv_secs / (24*60*60);
|
||
leP->le_DateStamp.ds_Minute = (tr.tr_time.tv_secs / 60) % 60;
|
||
leP->le_DateStamp.ds_Tick = (tr.tr_time.tv_secs % 60) * 50;
|
||
leP->lectx_Flags |= LOGF_Flag_Private_STMPTimer;
|
||
} else {
|
||
leP->lectx_Flags |= LOGF_Flag_Private_STMPKrn;
|
||
if (KernelBase) {
|
||
UQUAD stamp = KrnTimeStamp();
|
||
if (stamp != 0) {
|
||
// TODO:
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
Forbid();
|
||
if (leP->lep_Producer != &LIBBASE->lrb_LRProvider)
|
||
AddTail(&lrHandle->lrh_Entries, &leP->le_Node);
|
||
Permit();
|
||
|
||
leP->le_Node.ln_Type = EHMB_ADDENTRY;
|
||
PutMsg(LIBBASE->lrb_ServicePort, (struct Message *)leP);
|
||
|
||
return((struct logEntry *)&leP->le_Node);
|
||
}
|
||
FreeVecPooled(lrHandle->lrh_Pool, leP);
|
||
}
|
||
}
|
||
|
||
return(NULL);
|
||
|
||
AROS_LIBFUNC_EXIT
|
||
}
|
||
|
||
AROS_LH1(void, logRemEntry,
|
||
AROS_LHA(struct logEntry *, le, A0),
|
||
LIBBASETYPEPTR, LIBBASE, 11, log)
|
||
{
|
||
AROS_LIBFUNC_INIT
|
||
|
||
if (le) {
|
||
struct ExecBase *SysBase = GM_SYSBASE_FIELD(LIBBASE);
|
||
struct logEntryPrivate *leP;
|
||
leP = (struct logEntryPrivate *)((IPTR)le - offsetof(struct logEntryPrivate, le_Node));
|
||
|
||
Forbid();
|
||
Remove(&leP->lep_Node);
|
||
if (leP->lep_Producer != &LIBBASE->lrb_LRProvider)
|
||
Remove(&leP->le_Node);
|
||
Permit();
|
||
|
||
if (LIBBASE->lrb_Task) {
|
||
leP->le_Node.ln_Type = EHMB_REMENTRY;
|
||
PutMsg(LIBBASE->lrb_ServicePort, (struct Message *)leP);
|
||
}
|
||
}
|
||
AROS_LIBFUNC_EXIT
|
||
}
|