Part 1
요약·해설
Global type list → type별 object-core list → containing object offset의 관계와 통계 등록·조회·reset lifecycle을 설명합니다.
type · core lists
locked · unlocked
raw · query
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
934F4B52E8C85F1D14805C103550E27F8BAE6B2FECABFA3D5E643F859D14CB77
.. _object_cores_api:
Object Cores
############
Object cores are a kernel debugging tool that can be used to both identify and
perform operations on registered objects.
.. contents::
:local:
:depth: 2
Object Core Concepts
********************
Each instance of an object embeds an object core field named `obj_core`.
Objects of the same type are linked together via their respective object
cores to form a singly linked list. Each object core also links to the their
respective object type. Each object type contains a singly linked list
linking together all the object cores of that type. Object types are also
linked together via a singly linked list. Together, this can allow debugging
tools to traverse all the objects in the system.
Object cores have been integrated into following kernel objects:
* :ref:`Condition Variables <condvar>`
* :ref:`Events <events>`
* :ref:`FIFOs <fifos_v2>` and :ref:`LIFOs <lifos_v2>`
* :ref:`Mailboxes <mailboxes_v2>`
* :ref:`Memory Slabs <memory_slabs_v2>`
* :ref:`Message Queues <message_queues_v2>`
* :ref:`Mutexes <mutexes_v2>`
* :ref:`Pipes <pipes_v2>`
* :ref:`Semaphores <semaphores_v2>`
* :ref:`Threads <threads_v2>`
* :ref:`Timers <timers_v2>`
* :ref:`System Memory Blocks <sys_mem_blocks>`
Developers are free to integrate them if desired into other objects within
their projects.
Object Core Statistics Concepts
*******************************
A variety of kernel objects allow for the gathering and reporting of statistics.
Object cores provide a uniform means to retrieve that information via object
core statistics. When enabled, the object type contains a pointer to a
statistics descriptor that defines the various operations that have been
enabled for interfacing with the object's statistics. Additionally, the object
core contains a pointer to the "raw" statistical information associated with
that object. Raw data is the raw, unmanipulated data associated with the
statistics. Queried data may be "raw", but it may also have been manipulated in
some way by calculation (such as determining an average).
The following table indicates both what objects have been integrated into the
object core statistics as well as the structures used for both "raw" and
"queried" data.
===================== ============================== ==============================
Object Raw Data Type Query Data Type
===================== ============================== ==============================
struct mem_slab struct mem_slab_info struct sys_memory_stats
struct sys_mem_blocks struct sys_mem_blocks_info struct sys_memory_stats
struct k_thread struct k_cycle_stats struct k_thread_runtime_stats
struct _cpu struct k_cycle_stats struct k_thread_runtime_stats
struct z_kernel struct k_cycle_stats[num CPUs] struct k_thread_runtime_stats
===================== ============================== ==============================
Implementation
**************
Defining a New Object Type
==========================
An object type is defined using a global variable of type
:c:struct:`k_obj_type`. It must be initialized before any objects of that type
are initialized. The following code shows how a new object type can be
initialized for use with object cores and object core statistics.
.. code-block:: c
/* Unique object type ID */
#define K_OBJ_TYPE_MY_NEW_TYPE K_OBJ_TYPE_ID_GEN("UNIQ")
struct k_obj_type my_obj_type;
struct my_obj_type_raw_info {
...
};
struct my_obj_type_query_stats {
...
};
struct my_new_obj {
...
struct k_obj_core obj_core;
struct my_obj_type_raw_info info;
};
struct k_obj_core_stats_desc my_obj_type_stats_desc = {
.raw_size = sizeof(struct my_obj_type_raw_stats),
.query_size = sizeof(struct my_obj_type_query_stats),
.raw = my_obj_type_stats_raw,
.query = my_obj_type_stats_query,
.reset = my_obj_type_stats_reset,
.disable = NULL, /* Stats gathering is always on */
.enable = NULL, /* Stats gathering is always on */
};
void my_obj_type_init(void)
{
z_obj_type_init(&my_obj_type, K_OBJ_TYPE_MY_NEW_TYPE,
offsetof(struct my_new_obj, obj_core);
k_obj_type_stats_init(&my_obj_type, &my_obj_type_stats_desc);
}
Initializing a New Object Core
==============================
Kernel objects that have already been integrated into the object core framework
automatically have their object cores initialized when the object is
initialized. However, developers that wish to add their own objects into the
framework need to both initialize the object core and link it. The following
code builds on the example above and initializes the object core.
.. code-block:: c
void my_new_obj_init(struct my_new_obj *new_obj)
{
...
k_obj_core_init(K_OBJ_CORE(new_obj), &my_obj_type);
k_obj_core_link(K_OBJ_CORE(new_obj));
k_obj_core_stats_register(K_OBJ_CORE(new_obj), &new_obj->raw_stats,
sizeof(struct my_obj_type_raw_info));
}
Walking a List of Object Cores
==============================
Two routines exist for walking the list of object cores linked to an object
type. These are :c:func:`k_obj_type_walk_locked` and
:c:func:`k_obj_type_walk_unlocked`. The following code builds upon the example
above and prints the addresses of all the objects of that new object type.
.. code-block:: c
int walk_op(struct k_obj_core *obj_core, void *data)
{
uint8_t *ptr;
ptr = obj_core;
ptr -= obj_core->type->obj_core_offset;
printk("%p\n", ptr);
return 0;
}
void print_object_addresses(void)
{
struct k_obj_type *obj_type;
/* Find the object type */
obj_type = k_obj_type_find(K_OBJ_TYPE_MY_NEW_TYPE);
/* Walk the list of objects */
k_obj_type_walk_unlocked(obj_type, walk_op, NULL);
}
Object Core Statistics Querying
===============================
The following code builds on the examples above and shows how an object
integrated into the object core statistics framework can both retrieve queried
data and reset the stats associated with the object.
.. code-block:: c
struct my_new_obj my_obj;
...
void my_func(void)
{
struct my_obj_type_query_stats my_stats;
int status;
my_obj_type_init(&my_obj);
...
status = k_obj_core_stats_query(K_OBJ_CORE(&my_obj),
&my_stats, sizeof(my_stats));
if (status != 0) {
/* Failed to get stats */
...
} else {
k_obj_core_stats_reset(K_OBJ_CORE(&my_obj));
}
...
}
Configuration Options
*********************
Related configuration options:
* :kconfig:option:`CONFIG_OBJ_CORE`
* :kconfig:option:`CONFIG_OBJ_CORE_CONDVAR`
* :kconfig:option:`CONFIG_OBJ_CORE_EVENT`
* :kconfig:option:`CONFIG_OBJ_CORE_FIFO`
* :kconfig:option:`CONFIG_OBJ_CORE_LIFO`
* :kconfig:option:`CONFIG_OBJ_CORE_MAILBOX`
* :kconfig:option:`CONFIG_OBJ_CORE_MEM_SLAB`
* :kconfig:option:`CONFIG_OBJ_CORE_MSGQ`
* :kconfig:option:`CONFIG_OBJ_CORE_MUTEX`
* :kconfig:option:`CONFIG_OBJ_CORE_PIPE`
* :kconfig:option:`CONFIG_OBJ_CORE_SEM`
* :kconfig:option:`CONFIG_OBJ_CORE_STACK`
* :kconfig:option:`CONFIG_OBJ_CORE_THREAD`
* :kconfig:option:`CONFIG_OBJ_CORE_TIMER`
* :kconfig:option:`CONFIG_OBJ_CORE_SYS_MEM_BLOCKS`
* :kconfig:option:`CONFIG_OBJ_CORE_STATS`
* :kconfig:option:`CONFIG_OBJ_CORE_STATS_MEM_SLAB`
* :kconfig:option:`CONFIG_OBJ_CORE_STATS_THREAD`
* :kconfig:option:`CONFIG_OBJ_CORE_STATS_SYSTEM`
* :kconfig:option:`CONFIG_OBJ_CORE_STATS_SYS_MEM_BLOCKS`
API Reference
*************
.. doxygengroup:: obj_core_apis
.. doxygengroup:: obj_core_stats_apis
Part 3
한국어 전문 번역
Object core는 등록된 kernel object를 식별하고 operation을 수행하는 debugging tool입니다. Object 자체 안에 공통 core를 embed하고 type별 list에 연결하므로 debugger나 system tool이 특정 subsystem의 private layout을 모두 몰라도 system object를 탐색할 수 있습니다.
Object core 개념
각 object instance는 obj_core라는 field를 포함합니다. 같은 type의 object는 각 core의 singly linked list node로 서로 연결되고, 각 core는 자신이 속한 object type도 가리킵니다. Object type마다 그 type의 모든 core를 연결하는 list가 있으며 type 자체도 global singly linked list로 연결됩니다. 이 3단 관계 덕분에 tool이 모든 type과 모든 object를 순회할 수 있습니다.
Framework가 통합된 kernel object는 condition variable, event, FIFO, LIFO, mailbox, memory slab, message queue, mutex, pipe, semaphore, thread, timer와 system memory block입니다. Project의 custom object도 developer가 같은 방식으로 통합할 수 있습니다.
Object core statistics 개념
여러 kernel object가 통계를 수집·보고하며 object core statistics는 이를 얻는 공통 interface를 제공합니다. Statistics를 켜면 object type은 허용 operation을 정의하는 descriptor pointer를 갖고, 각 object core는 그 object의 raw statistics pointer를 가집니다.
Raw data는 계산이나 변환 전 내부 값입니다. Query data는 raw일 수도 있지만 평균 계산처럼 가공된 보고값일 수도 있습니다.
| Object | Raw data type | Query data type |
|---|---|---|
struct mem_slab | struct mem_slab_info | struct sys_memory_stats |
struct sys_mem_blocks | struct sys_mem_blocks_info | struct sys_memory_stats |
struct k_thread | struct k_cycle_stats | struct k_thread_runtime_stats |
struct _cpu | struct k_cycle_stats | struct k_thread_runtime_stats |
struct z_kernel | struct k_cycle_stats[num CPUs] | struct k_thread_runtime_stats |
구현
새 object type 정의
struct k_obj_type global variable로 type을 정의하고 그 type object보다 먼저 초기화합니다. 다음 예제는 unique 4-character ID, raw/query data type, embedded core와 statistics descriptor를 구성합니다.
/* Unique object type ID */
#define K_OBJ_TYPE_MY_NEW_TYPE K_OBJ_TYPE_ID_GEN("UNIQ")
struct k_obj_type my_obj_type;
struct my_obj_type_raw_info {
...
};
struct my_obj_type_query_stats {
...
};
struct my_new_obj {
...
struct k_obj_core obj_core;
struct my_obj_type_raw_info info;
};
struct k_obj_core_stats_desc my_obj_type_stats_desc = {
.raw_size = sizeof(struct my_obj_type_raw_stats),
.query_size = sizeof(struct my_obj_type_query_stats),
.raw = my_obj_type_stats_raw,
.query = my_obj_type_stats_query,
.reset = my_obj_type_stats_reset,
.disable = NULL, /* Stats gathering is always on */
.enable = NULL, /* Stats gathering is always on */
};
void my_obj_type_init(void)
{
z_obj_type_init(&my_obj_type, K_OBJ_TYPE_MY_NEW_TYPE,
offsetof(struct my_new_obj, obj_core);
k_obj_type_stats_init(&my_obj_type, &my_obj_type_stats_desc);
}z_obj_type_init()은 type ID와 containing object 안의 obj_core offset을 등록합니다. k_obj_type_stats_init()은 raw/query/reset operation과 선택적인 enable/disable operation descriptor를 연결합니다.
새 object core 초기화
이미 framework에 통합된 kernel object는 object 초기화 때 core도 자동으로 초기화합니다. Custom object는 core를 초기화한 뒤 type list에 link하고, 통계를 쓴다면 raw buffer도 등록해야 합니다.
void my_new_obj_init(struct my_new_obj *new_obj)
{
...
k_obj_core_init(K_OBJ_CORE(new_obj), &my_obj_type);
k_obj_core_link(K_OBJ_CORE(new_obj));
k_obj_core_stats_register(K_OBJ_CORE(new_obj), &new_obj->raw_stats,
sizeof(struct my_obj_type_raw_info));
}Object core list 순회
k_obj_type_walk_locked()과 k_obj_type_walk_unlocked() 두 방식이 있습니다. 예제 callback은 core pointer에서 type의 obj_core_offset을 빼 containing object 시작 주소를 복원하고 출력합니다.
int walk_op(struct k_obj_core *obj_core, void *data)
{
uint8_t *ptr;
ptr = obj_core;
ptr -= obj_core->type->obj_core_offset;
printk("%p\n", ptr);
return 0;
}
void print_object_addresses(void)
{
struct k_obj_type *obj_type;
/* Find the object type */
obj_type = k_obj_type_find(K_OBJ_TYPE_MY_NEW_TYPE);
/* Walk the list of objects */
k_obj_type_walk_unlocked(obj_type, walk_op, NULL);
}예제는 unique type ID로 k_obj_type을 찾은 뒤 unlocked 순회를 사용합니다. 실제 application은 순회 중 object link/unlink가 일어나지 않도록 자체 synchronization을 보장해야 합니다.
Object core statistics query
다음 예제는 object의 queried statistics를 읽고 성공하면 연결 통계를 reset합니다.
struct my_new_obj my_obj;
...
void my_func(void)
{
struct my_obj_type_query_stats my_stats;
int status;
my_obj_type_init(&my_obj);
...
status = k_obj_core_stats_query(K_OBJ_CORE(&my_obj),
&my_stats, sizeof(my_stats));
if (status != 0) {
/* Failed to get stats */
...
} else {
k_obj_core_stats_reset(K_OBJ_CORE(&my_obj));
}
...
}설정 옵션
전체 framework는 CONFIG_OBJ_CORE, statistics는 CONFIG_OBJ_CORE_STATS로 활성화합니다. Type별 통합 option은 다음과 같습니다.
CONFIG_OBJ_CORE_CONDVARCONFIG_OBJ_CORE_EVENTCONFIG_OBJ_CORE_FIFOCONFIG_OBJ_CORE_LIFOCONFIG_OBJ_CORE_MAILBOXCONFIG_OBJ_CORE_MEM_SLABCONFIG_OBJ_CORE_MSGQCONFIG_OBJ_CORE_MUTEXCONFIG_OBJ_CORE_PIPECONFIG_OBJ_CORE_SEMCONFIG_OBJ_CORE_STACKCONFIG_OBJ_CORE_THREADCONFIG_OBJ_CORE_TIMERCONFIG_OBJ_CORE_SYS_MEM_BLOCKS
Statistics 통합 option은 CONFIG_OBJ_CORE_STATS_MEM_SLAB, CONFIG_OBJ_CORE_STATS_THREAD, CONFIG_OBJ_CORE_STATS_SYSTEM, CONFIG_OBJ_CORE_STATS_SYS_MEM_BLOCKS입니다.
API 참고
Object core API: obj_core_apis
K_OBJ_CORE(kobj)Kernel object pointer를 그 object 안에 들어 있는 object core pointer로 변환합니다.
K_OBJ_TYPE_ID_GEN(s)네 글자 문자열을 바탕으로 새 object type ID를 생성합니다.
K_OBJ_TYPE_CONDVAR_IDCondition variable object type ID입니다.
K_OBJ_TYPE_CPU_IDCPU object type ID입니다.
K_OBJ_TYPE_EVENT_IDEvent object type ID입니다.
K_OBJ_TYPE_FIFO_IDFIFO object type ID입니다.
K_OBJ_TYPE_KERNEL_IDKernel object type ID입니다.
K_OBJ_TYPE_LIFO_IDLIFO object type ID입니다.
K_OBJ_TYPE_MEM_BLOCK_IDMemory block object type ID입니다.
K_OBJ_TYPE_MBOX_IDMailbox object type ID입니다.
K_OBJ_TYPE_MEM_SLAB_IDMemory slab object type ID입니다.
K_OBJ_TYPE_MSGQ_IDMessage queue object type ID입니다.
K_OBJ_TYPE_MUTEX_IDMutex object type ID입니다.
K_OBJ_TYPE_PIPE_IDPipe object type ID입니다.
K_OBJ_TYPE_SEM_IDSemaphore object type ID입니다.
K_OBJ_TYPE_STACK_IDStack object type ID입니다.
K_OBJ_TYPE_THREAD_IDThread object type ID입니다.
K_OBJ_TYPE_TIMER_IDTimer object type ID입니다.
struct k_obj_type *k_obj_type_find(uint32_t type_id)지정 ID에 연결된 object type을 global type list에서 찾습니다.
매개변수
type_id: 찾을 object type ID
반환값: 찾으면 k_obj_type pointer, 없으면 NULL입니다.
int k_obj_type_walk_locked(struct k_obj_type *type, int (*func)(struct k_obj_core*, void*), void *data)Global spinlock을 잡은 채 object type의 core list를 순회하고 각 element에 callback을 호출합니다. List 변경을 막지만 performance와 latency 비용이 큽니다. Callback이 0이면 계속하고 non-zero이면 즉시 중단합니다.
매개변수
type: 순회할 object type pointerfunc: 각 object core에 호출할 callbackdata: callback에 전달할 custom data
반환값: Callback이 중단하면 그 non-zero 값, 끝까지 돌면 0입니다.
int k_obj_type_walk_unlocked(struct k_obj_type *type, int (*func)(struct k_obj_core*, void*), void *data)Global spinlock 없이 object-core list를 순회합니다. Framework가 synchronization을 제공하지 않으므로 application이 순회 중 list mutation을 막아야 합니다. 그렇지 않으면 undefined/unreliable behavior, corruption 또는 crash가 날 수 있습니다. Callback 반환 규칙은 locked 변형과 같습니다.
매개변수
type: 순회할 object type pointerfunc: 각 core에 호출할 callbackdata: callback custom data
반환값: Callback 중단 시 non-zero, 완료 시 0입니다.
void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type)Kernel object core를 초기화하고 지정 object type과 연결합니다.
매개변수
obj_core: 초기화할 object core pointertype: 연결할 object type pointer
void k_obj_core_link(struct k_obj_core *obj_core)초기화된 kernel object를 type의 object list에 선택적으로 연결합니다. 연결된 object는 system tool이 순회하며 정보를 추출할 수 있습니다.
매개변수
obj_core: 연결할 object core pointer
void k_obj_core_init_and_link(struct k_obj_core *obj_core, struct k_obj_type *type)Object core 초기화와 type list 연결을 한 번에 수행하는 wrapper입니다.
매개변수
obj_core: 초기화·연결할 coretype: object type
void k_obj_core_unlink(struct k_obj_core *obj_core)Object를 type list에서 제거합니다. List에 연결된 object라면 lifecycle 끝에서 수행해야 합니다.
매개변수
obj_core: 제거할 object core
struct k_obj_core_stats_descObject-core statistics operation과 buffer 크기를 정의하는 descriptor이며
에 선언됩니다. size_t raw_size내부 표현(raw) statistics buffer 크기입니다.
size_t query_size보고용 queried statistics buffer 크기입니다.
int (*raw)(struct k_obj_core *obj_core, void *stats)내부 raw statistics를 가져오는 function pointer입니다.
int (*query)(struct k_obj_core *obj_core, void *stats)계산된 보고용 statistics를 가져오는 function pointer입니다.
int (*reset)(struct k_obj_core *obj_core)Object statistics를 reset하는 function pointer입니다.
int (*disable)(struct k_obj_core *obj_core)Statistics gathering을 끄는 function pointer입니다. 항상 켜진 type은 NULL일 수 있습니다.
int (*enable)(struct k_obj_core *obj_core)Statistics gathering을 켜는 function pointer입니다. 항상 켜진 type은 NULL일 수 있습니다.
struct k_obj_type같은 종류의 object core list와 unique ID를 보유하는 object-type 구조체이며
에 선언됩니다. sys_snode_t nodeObject type들의 global singly linked list 안에서 이 type을 연결하는 node입니다.
sys_slist_t list이 type에 속한 object core들의 singly linked list입니다.
uint32_t id고유 object type ID입니다.
size_t obj_core_offsetContaining object 시작에서 obj_core field까지의 offset입니다.
struct k_obj_core각 kernel object 안에 embed되는 core 구조체이며
에 선언됩니다. sys_snode_t node (k_obj_core)Object type의 core list에서 이 object를 연결하는 node입니다. 생성 API 이름은 type 구조체의 필드와 동일하게 node입니다.
struct k_obj_type *type이 object가 속한 object type pointer입니다.
Statistics API: obj_core_stats_apis
int k_obj_core_stats_register(struct k_obj_core *obj_core, void *stats, size_t stats_len)Kernel object가 statistics를 모으도록 raw buffer를 등록합니다. 등록하면 gathering도 자동으로 활성화합니다.
매개변수
obj_core: kernel object corestats: raw statistics pointerstats_len: raw buffer 크기
반환값: 성공은 0, 실패는 -errno입니다.
int k_obj_core_stats_deregister(struct k_obj_core *obj_core)Object core를 statistics gathering에서 등록 해제해 더는 수집하지 않게 합니다. Object lifecycle 끝에서 호출할 것으로 기대합니다.
매개변수
obj_core: kernel object core
반환값: 성공은 0, 실패는 -errno입니다.
int k_obj_core_stats_raw(struct k_obj_core *obj_core, void *stats, size_t stats_len)Object core의 raw statistics를 stats buffer로 복사합니다. stats_len은 object type statistics descriptor의 raw_size와 일치해야 합니다.
매개변수
obj_core: kernel object corestats: raw stats를 복사할 bufferstats_len: buffer 길이
반환값: 성공은 0, 실패는 -errno입니다.
int k_obj_core_stats_query(struct k_obj_core *obj_core, void *stats, size_t stats_len)Object statistics를 query buffer로 복사합니다. Raw data와 달리 평균 같은 계산값이 들어갈 수 있고 stats_len은 descriptor의 query_size와 일치해야 합니다.
매개변수
obj_core: kernel object corestats: queried stats를 쓸 bufferstats_len: buffer 길이
반환값: 성공은 0, 실패는 -errno입니다.
int k_obj_core_stats_reset(struct k_obj_core *obj_core)지정 object core에 연결된 statistics를 reset합니다.
매개변수
obj_core: kernel object core
반환값: 성공은 0, 실패는 -errno입니다.
int k_obj_core_stats_disable(struct k_obj_core *obj_core)지정 object의 statistics gathering을 일시 정지합니다. k_obj_core_stats_enable()로 재개할 수 있습니다.
매개변수
obj_core: kernel object core
반환값: 성공은 0, 실패는 -errno입니다.
int k_obj_core_stats_enable(struct k_obj_core *obj_core)지정 object core의 statistics gathering을 재개합니다. 생성 문서의 짧은 제목은 ‘Reset the stats’라고 되어 있지만 본문 동작은 resume입니다.
매개변수
obj_core: kernel object core
반환값: 성공은 0, 실패는 -errno입니다.
Source
출처
영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.