Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * Copyright (c) 2018 Oticon A/S
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef SUBSYS_DEBUG_TRACING_CTF_TOP_H
#define SUBSYS_DEBUG_TRACING_CTF_TOP_H

#include <stddef.h>
#include <string.h>
#include <ctf_map.h>
#include <tracing/tracing_format.h>

/* Limit strings to 20 bytes to optimize bandwidth */
#define CTF_MAX_STRING_LEN 20

/*
 * Obtain a field's size at compile-time.
 */
#define CTF_INTERNAL_FIELD_SIZE(x)      + sizeof(x)

/*
 * Append a field to current event-packet.
 */
#define CTF_INTERNAL_FIELD_APPEND(x)			 \
	{						 \
		memcpy(epacket_cursor, &(x), sizeof(x)); \
		epacket_cursor += sizeof(x);		 \
	}

/*
 * Gather fields to a contiguous event-packet, then atomically emit.
 */
#define CTF_GATHER_FIELDS(...)						    \
{									    \
	u8_t epacket[0 MAP(CTF_INTERNAL_FIELD_SIZE, ##__VA_ARGS__)];	    \
	u8_t *epacket_cursor = &epacket[0];				    \
									    \
	MAP(CTF_INTERNAL_FIELD_APPEND, ##__VA_ARGS__)			    \
	tracing_format_raw_data(epacket, sizeof(epacket));		    \
}

#ifdef CONFIG_TRACING_CTF_TIMESTAMP
#define CTF_EVENT(...)							    \
	{								    \
		const u32_t tstamp = k_cycle_get_32();			    \
									    \
		CTF_GATHER_FIELDS(tstamp, __VA_ARGS__)			    \
	}
#else
#define CTF_EVENT(...)							    \
	{								    \
		CTF_GATHER_FIELDS(__VA_ARGS__)				    \
	}
#endif

/* Anonymous compound literal with 1 member. Legal since C99.
 * This permits us to take the address of literals, like so:
 *  &CTF_LITERAL(int, 1234)
 *
 * This may be required if a ctf_bottom layer uses memcpy.
 *
 * NOTE string literals already support address-of and sizeof,
 * so string literals should not be wrapped with CTF_LITERAL.
 */
#define CTF_LITERAL(type, value)  ((type) { (type)(value) })

typedef enum {
	CTF_EVENT_THREAD_SWITCHED_OUT   =  0x10,
	CTF_EVENT_THREAD_SWITCHED_IN    =  0x11,
	CTF_EVENT_THREAD_PRIORITY_SET   =  0x12,
	CTF_EVENT_THREAD_CREATE         =  0x13,
	CTF_EVENT_THREAD_ABORT          =  0x14,
	CTF_EVENT_THREAD_SUSPEND        =  0x15,
	CTF_EVENT_THREAD_RESUME         =  0x16,
	CTF_EVENT_THREAD_READY          =  0x17,
	CTF_EVENT_THREAD_PENDING        =  0x18,
	CTF_EVENT_THREAD_INFO           =  0x19,
	CTF_EVENT_THREAD_NAME_SET       =  0x1A,
	CTF_EVENT_ISR_ENTER             =  0x20,
	CTF_EVENT_ISR_EXIT              =  0x21,
	CTF_EVENT_ISR_EXIT_TO_SCHEDULER =  0x22,
	CTF_EVENT_IDLE                  =  0x30,
	CTF_EVENT_ID_START_CALL         =  0x41,
	CTF_EVENT_ID_END_CALL           =  0x42
} ctf_event_t;


typedef struct {
	char buf[CTF_MAX_STRING_LEN];
} ctf_bounded_string_t;


static inline void ctf_top_thread_switched_out(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_SWITCHED_OUT),
		thread_id
		);
}

static inline void ctf_top_thread_switched_in(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_SWITCHED_IN),
		thread_id
		);
}

static inline void ctf_top_thread_priority_set(u32_t thread_id, s8_t prio)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_PRIORITY_SET),
		thread_id,
		prio
		);
}

static inline void ctf_top_thread_create(
	u32_t thread_id,
	s8_t prio,
	ctf_bounded_string_t name
	)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_CREATE),
		thread_id,
		name
		);
}

static inline void ctf_top_thread_abort(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_ABORT),
		thread_id
		);
}

static inline void ctf_top_thread_suspend(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_SUSPEND),
		thread_id
		);
}

static inline void ctf_top_thread_resume(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_RESUME),
		thread_id
		);
}

static inline void ctf_top_thread_ready(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_READY),
		thread_id
		);
}

static inline void ctf_top_thread_pend(u32_t thread_id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_PENDING),
		thread_id
		);
}

static inline void ctf_top_thread_info(
	u32_t thread_id,
	u32_t stack_base,
	u32_t stack_size
	)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_INFO),
		thread_id,
		stack_base,
		stack_size
		);
}

static inline void ctf_top_thread_name_set(
	u32_t thread_id,
	ctf_bounded_string_t name
	)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_THREAD_NAME_SET),
		thread_id,
		name
		);
}

static inline void ctf_top_isr_enter(void)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_ISR_ENTER)
		);
}

static inline void ctf_top_isr_exit(void)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_ISR_EXIT)
		);
}

static inline void ctf_top_isr_exit_to_scheduler(void)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_ISR_EXIT_TO_SCHEDULER)
		);
}

static inline void ctf_top_idle(void)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_IDLE)
		);
}

static inline void ctf_top_void(u32_t id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_ID_START_CALL),
		id
		);
}

static inline void ctf_top_end_call(u32_t id)
{
	CTF_EVENT(
		CTF_LITERAL(u8_t, CTF_EVENT_ID_END_CALL),
		id
		);
}

#endif /* SUBSYS_DEBUG_TRACING_CTF_TOP_H */