/**
@file transport_id.h
@brief Id of the transport
@details Copyright (c) 2024 Acronis International GmbH
@author Denis Kopyrin (denis.kopyrin@acronis.com)
@since $Id: $
*/
#pragma once
#include <linux/types.h> // bool, [u]int(8|16|32|64)_t, pid_t
#ifdef KERNEL_MOCK
#include <mock/mock.h>
#endif
// Limits max size of 'transport_index'
#define MAX_TRANSPORT_SIZE 4
// Memory layout of transport id is
// struct {
// uint64_t seq_num : 55;
// uint64_t taken: 1;
// uint64_t index : 8;
// } id;
// The reason why I am not using it is because I want to be able to compare transport ids between each other.
// Larger transport id is expected to arrive after smaller transport id so it takes precedence.
// transport_id == 0 is reserved for invalid/empty transport id and can never be used
typedef uint64_t transport_id_t;
#define TRANSPORT_ID_TAKEN_BIT (1 << 8)
#define TRANSPORT_ID_INDEX_MASK 0xFF
#define TRANSPORT_ID_SEQ_NUM_SHIFT (8 + 1)
static inline uint64_t transport_id_taken(transport_id_t id)
{
return id & TRANSPORT_ID_TAKEN_BIT;
}
static inline uint64_t transport_id_seq_num(transport_id_t id)
{
return id >> TRANSPORT_ID_SEQ_NUM_SHIFT;
}
static inline int transport_id_index(transport_id_t id)
{
return id & TRANSPORT_ID_INDEX_MASK;
}
static inline transport_id_t transport_id_make(uint64_t seq_num, int index)
{
return (seq_num << TRANSPORT_ID_SEQ_NUM_SHIFT) | TRANSPORT_ID_TAKEN_BIT | index;
}
// This is useful to keep the index correct but not mark transport as taken
// Any id with 'transport_id_make' will be larger than id made by 'transport_id_make_not_taken'
static inline transport_id_t transport_id_make_not_taken(unsigned index)
{
return index;
}
typedef union {
transport_id_t ids[MAX_TRANSPORT_SIZE];
} transport_ids_t;
|