#include <FTrace_chunk.h>
#include <FTrace_types.h>
#include <FTrace_OSD.h>
#define FTRACE_DEBUG
/* Globals */
FTrace_Chunk_Ptr ChunkTable
[MAX_CHUNK
]; /* Chunk array */
FTrace_Chunk_Ptr ActualChunk
= NULL
; /* Actual Chunk */
/* Global Pointers */
BYTE OSD_pointers
[FTRACE_OSD_CHUNK_HEAD
];
int FTraceInit
= 0;
int FTraceEnable
= 0;
/* Init a chunk with default value */
static int FTrace_chunk_init
(FTrace_Chunk_Ptr c
, int number
, int size
, int emergency_size
, FTrace_flags flags
)
{
c
->id
= FTRACE_CHUNK_ID
; /* Std ID */
c
->number
= number
; /* Chunk number */
c
->flags
= flags
; /* Chunk flags */
c
->size
= size
; /* Chunk size */
c
->emergency_size
= emergency_size
; /* Chunk emergency size */
c
->osd
= (DWORD
)((DWORD
)(c
) + sizeof(struct FTrace_Chunk
));
return FTrace_OSD_chunk_init
(c
, size
, emergency_size
, flags
);
}
/* Find a free slot in ChunkTable */
static int FTrace_find_free_slot
()
{
int i
;
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
return -1;
}
for (i
= 0;i
< MAX_CHUNK
;i
++)
if (ChunkTable
[i
] == NULL
)
return i
;
return -1;
}
/* Init the FTrace */
static int FTrace_Init
()
{
int i
,err
;
/* Check if it's just initialized */
if (FTraceInit
== 1)
return 0;
FTrace_lock
();
memset(OSD_pointers
,0,sizeof(OSD_pointers
));
for (i
= 0;i
< MAX_CHUNK
;i
++)
ChunkTable
[i
] = NULL
;
/* Init System Dependet Part */
err
= FTrace_OSD_init
();
if (err
!= 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace OSD not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
FTraceInit
= 1;
FTrace_unlock
();
return 0;
}
/* Enable Tracer */
int FTrace_enable
()
{
if (FTraceInit
== 0 || ActualChunk
== NULL
) return -1;
FTrace_fsave
();
FTraceEnable
= 1;
FTrace_frestore
();
return 0;
}
/* Disable Tracer */
int FTrace_disable
()
{
if (FTraceInit
== 0) return -1;
FTrace_fsave
();
FTraceEnable
= 0;
FTrace_frestore
();
return 0;
}
int FTrace_chunk_create
(int n
, int size
, int emergency_size
, FTrace_flags flags
)
{
FTrace_Chunk_Ptr FT_temp
;
int i
, number
, err
;
FTrace_lock
();
if (FTraceInit
== 0) {
err
= FTrace_Init
();
if (err
!= 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Initialization fail\n");
#endif
FTrace_unlock
();
return -1;
}
}
for (i
= 0;i
< n
;i
++) {
number
= FTrace_find_free_slot
();
if (number
== -1) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: cannot find free slot for chunk\n");
#endif
FTrace_unlock
();
return -1;
}
FT_temp
= (FTrace_Chunk_Ptr
)FTrace_malloc
(sizeof(struct FTrace_Chunk
) + FTRACE_OSD_CHUNK_HEAD
+ size
+ emergency_size
);
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: cannot allocate memory for chunk\n");
#endif
FTrace_unlock
();
return -1;
}
memset(FT_temp
,0,sizeof(struct FTrace_Chunk
) + FTRACE_OSD_CHUNK_HEAD
+ size
+ emergency_size
);
err
= FTrace_chunk_init
(FT_temp
, number
, size
, emergency_size
, flags
);
if (err
!= 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: cannot initialized the new chunk\n");
#endif
FTrace_unlock
();
return -1;
}
/* Set the ChunkTable */
ChunkTable
[number
] = FT_temp
;
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Debug: Chunk %d created at addr %x\n",number
,(int)FT_temp
);
#endif
}
FTrace_unlock
();
return 0;
}
/* Delete a Chunk */
int FTrace_chunk_delete
(int number
)
{
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk not present\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
->flags
& FTRACE_CHUNK_FLAG_NODEL
) {
FTrace_unlock
();
return 0;
}
FTrace_free
(FT_temp
);
ChunkTable
[number
] = NULL
;
FTrace_unlock
();
return 0;
}
/* Set the chunk flags */
int FTrace_set_chunk_flags
(int number
, FTrace_flags flags
)
{
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk not present\n");
#endif
FTrace_unlock
();
return -1;
}
FT_temp
->flags
= flags
;
FTrace_OSD_update_chunk_flags
(FT_temp
);
return 0;
}
/* Get the chunk flags */
int FTrace_get_chunk_flags
(int number
, FTrace_flags
*flags
)
{
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk not present\n");
#endif
FTrace_unlock
();
return -1;
}
*flags
= FT_temp
->flags
;
return 0;
}
/* Select the actual chunk */
int FTrace_actual_chunk_select
(int number
)
{
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk not present\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
->flags
& FTRACE_CHUNK_FLAG_FREE
) {
/* Set as used */
FT_temp
->flags
&= ~FTRACE_CHUNK_FLAG_FREE
;
FTrace_OSD_update_chunk_flags
(FT_temp
);
/* Update the actual_chunk and OSD_pointers */
FTrace_fsave
();
FTrace_OSD_save_pointers
();
ActualChunk
= FT_temp
;
FTrace_OSD_load_pointers
();
FTrace_frestore
();
} else {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk is not free\n");
#endif
FTrace_unlock
();
return -1;
}
FTrace_unlock
();
return 0;
}
/* Find the first chunk with specific flags*/
int FTrace_get_first_chunk
(FTrace_flags flags
) {
int i
;
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
for (i
= 0;i
< MAX_CHUNK
;i
++) {
if (ChunkTable
[i
]->flags
& flags
) {
FTrace_unlock
();
return i
;
}
}
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Free chunk not found\n");
#endif
FTrace_unlock
();
return -1;
}
/* Get chunk table */
FTrace_Chunk_Ptr
*FTrace_get_chunk_table
()
{
return ChunkTable
;
}
/* Link two chunks */
int FTrace_chunk_link
(int chunk_A
, int chunk_B
, int osd_flags
)
{
FTrace_Chunk_Ptr ckA
= ChunkTable
[chunk_A
];
FTrace_Chunk_Ptr ckB
= ChunkTable
[chunk_B
];
int err
;
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (ckA
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk A not present\n");
#endif
FTrace_unlock
();
return -1;
}
if (ckB
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk B not present\n");
#endif
FTrace_unlock
();
return -1;
}
if (!(ckB
->flags
& FTRACE_CHUNK_FLAG_FREE
)) {
ckB
->flags
&= ~FTRACE_CHUNK_FLAG_FREE
;
FTrace_OSD_update_chunk_flags
(ckB
);
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk B is not free\n");
#endif
FTrace_unlock
();
return -1;
}
/* FTrace Low Level Blocking Part */
FTrace_fsave
();
FTrace_OSD_save_pointers
();
err
= FTrace_OSD_chunk_link
(ckA
,ckB
,osd_flags
);
if (err
!= 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Cannot link the chunks\n");
#endif
return -1;
}
FTrace_OSD_load_pointers
();
FTrace_frestore
();
FTrace_unlock
();
return 0;
}
/* Update the OSD of actual chunk */
int FTrace_update_actual_chunk
()
{
FTrace_lock
();
if (ActualChunk
== NULL
) return 0;
FTrace_fsave
();
FTrace_OSD_save_pointers
();
FTrace_frestore
();
FTrace_unlock
();
return 0;
}
/* Create a new memory region where the compressed data are stored */
int FTrace_compress_chunk
(int number
, FTrace_flags new_flags
)
{
void *temp_data
;
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
int err
, data_size
;
FTrace_Chunk_Ptr New_chunk
;
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk not present\n");
#endif
FTrace_unlock
();
return -1;
}
FT_temp
->flags
|= FTRACE_CHUNK_FLAG_BUSY
;
FTrace_unlock
();
/* Alloc temp memory for */
temp_data
= (void *)FTrace_malloc
(FT_temp
->size
+FT_temp
->emergency_size
);
if (temp_data
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Cannot allocate memory\n");
#endif
return -1;
}
/* Compress the chunk. Temp_data are a temporary region where
store the compressed chunk. Data_size is the size of compressed
data */
err
= FTrace_OSD_compress_chunk
(number
,temp_data
,&data_size
);
if (err
!= 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: OSD Compressing function failed\n");
#endif
return -1;
}
New_chunk
= (FTrace_Chunk_Ptr
)FTrace_malloc
(sizeof(struct FTrace_Chunk
) + FTRACE_OSD_CHUNK_HEAD
+ data_size
);
if (New_chunk
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Cannot allocate memory\n");
#endif
return -1;
}
memcpy(New_chunk
,temp_data
,data_size
);
FTrace_free
(temp_data
);
FTrace_lock
();
/* Free the memory of the old chunk */
FTrace_free
(FT_temp
);
/* Set the new chunk flags and update the main table */
New_chunk
->flags
= new_flags
;
New_chunk
->flags
|= FTRACE_CHUNK_FLAG_COMPR
;
ChunkTable
[number
] = New_chunk
;
FTrace_unlock
();
return 0;
}
/* Send the chunk out from the memory */
int FTrace_send_chunk
(int number
, int osd_flags
, FTrace_flags new_flags
)
{
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
int err
;
FTrace_lock
();
if (FTraceInit
== 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: FTrace not initialized\n");
#endif
FTrace_unlock
();
return -1;
}
if (FT_temp
== NULL
) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Chunk not present\n");
#endif
FTrace_unlock
();
return -1;
}
FT_temp
->flags
|= FTRACE_CHUNK_FLAG_BUSY
;
FTrace_unlock
();
err
= FTrace_OSD_send_chunk
(number
, osd_flags
);
if (err
!= 0) {
#ifdef FTRACE_DEBUG
FTrace_printf
("FTrace Error: Cannot send the chunk\n");
#endif
return -1;
}
FTrace_lock
();
/* Set the new chunk flags */
FT_temp
->flags
= new_flags
;
FTrace_unlock
();
return 0;
}
void FTrace_chunk_dump
(int number
) {
FTrace_Chunk_Ptr FT_temp
= ChunkTable
[number
];
int i
,t
;
DWORD p
;
FTrace_update_actual_chunk
();
cprintf
("ID = %x\n",FT_temp
->id
);
cprintf
("NUM = %d\n",FT_temp
->number
);
cprintf
("FLAGS = %d\n",FT_temp
->flags
);
cprintf
("SIZE = %d\n",FT_temp
->size
);
cprintf
("EMERG = %d\n",FT_temp
->emergency_size
);
for (i
=0; i
<0xFF; i
++) {
p
= *(DWORD
*)(FT_temp
->osd
+ 8);
t
= 0;
while((p
+ 16) < *(DWORD
*)(FT_temp
->osd
+ 8) + *(DWORD
*)(FT_temp
->osd
+ 12)) {
if (*(WORD
*)(p
+2) == i
) t
++;
p
+= 16;
}
if (t
!= 0)
cprintf
("Event type %02x => %d\n",i
,t
);
}
}
void FTrace_OSD_dump
() {
void *p
= OSD_pointers
;
int i
;
for (i
=0;i
<FTRACE_OSD_CHUNK_HEAD
;i
+=4)
cprintf
("DATA %d = %x\n",i
,*(unsigned int *)(p
+i
));
}