/*
 * \brief  Basic types used by the tracing infrastructure
 * \author Norman Feske
 * \date   2013-08-12
 */

/*
 * Copyright (C) 2013-2017 Genode Labs GmbH
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU Affero General Public License version 3.
 */

#ifndef _INCLUDE__BASE__TRACE__TYPES_H_
#define _INCLUDE__BASE__TRACE__TYPES_H_

/* Genode includes */
#include <util/string.h>
#include <base/affinity.h>
#include <base/exception.h>
#include <base/fixed_stdint.h>
#include <base/session_label.h>

namespace Genode { namespace Trace {

	using Thread_name = String<32>;

	struct Num_subjects { unsigned value; };
	struct Policy_size  { size_t num_bytes; };
	struct Buffer_size  { size_t num_bytes; };

	struct Policy_id;
	struct Subject_id;
	struct Execution_time;
	struct Subject_info;
} }


/**
 * Session-local policy identifier
 */
struct Genode::Trace::Policy_id
{
	unsigned id { };

	bool operator == (Policy_id const &other) const { return id == other.id; }
};


/**
 * Session-local trace-subject identifier
 */
struct Genode::Trace::Subject_id
{
	unsigned id { };

	bool operator == (Subject_id const &other) const { return id == other.id; }
};


/**
 * Execution time of trace subject
 *
 * The value is kernel specific.
 */
struct Genode::Trace::Execution_time
{
	uint64_t thread_context = 0;
	uint64_t scheduling_context = 0;
	unsigned quantum  { 0 };
	unsigned priority { 0 };

	Execution_time() { }

	Execution_time(uint64_t thread_context, uint64_t scheduling_context)
	:
		thread_context(thread_context), scheduling_context(scheduling_context)
	{ }

	Execution_time(uint64_t thread_context, uint64_t scheduling_context,
	               unsigned quantum, unsigned priority)
	:
		thread_context(thread_context), scheduling_context(scheduling_context),
		quantum(quantum), priority(priority)
	{ }
};


/**
 * Subject information
 */
class Genode::Trace::Subject_info
{
	public:

		enum State { INVALID, UNATTACHED, ATTACHED, TRACED, FOREIGN, ERROR, DEAD };

		static char const *state_name(State state)
		{
			switch (state) {
			case INVALID:    return "INVALID";
			case UNATTACHED: return "UNATTACHED";
			case ATTACHED:   return "ATTACHED";
			case TRACED:     return "TRACED";
			case FOREIGN:    return "FOREIGN";
			case ERROR:      return "ERROR";
			case DEAD:       return "DEAD";
			}
			return "INVALID";
		}

	private:

		Session_label      _session_label  { };
		Thread_name        _thread_name    { };
		State              _state          { INVALID };
		Policy_id          _policy_id      { 0 };
		Execution_time     _execution_time { 0, 0 };
		Affinity::Location _affinity       { };

	public:

		Subject_info() { }

		Subject_info(Session_label const &session_label,
		             Thread_name   const &thread_name,
		             State state, Policy_id policy_id,
		             Execution_time execution_time,
		             Affinity::Location affinity)
		:
			_session_label(session_label), _thread_name(thread_name),
			_state(state), _policy_id(policy_id),
			_execution_time(execution_time), _affinity(affinity)
		{ }

		Session_label const &session_label()  const { return _session_label; }
		Thread_name   const &thread_name()    const { return _thread_name; }
		State                state()          const { return _state; }
		Policy_id            policy_id()      const { return _policy_id; }
		Execution_time       execution_time() const { return _execution_time; }
		Affinity::Location   affinity()       const { return _affinity; }
};

#endif /* _INCLUDE__BASE__TRACE__TYPES_H_ */
