kernel/object_cores/index.html · kernel/object_cores/index.rst 공식 원문 ↗

Zephyr 3.7.0 · Kernel · Object Cores

Object Cores

Kernel object에 공통 core를 embed해 type별로 등록·순회하고 raw·query statistics를 동일한 interface로 다룹니다.

Official pathkernel/object_cores/index.html
Source filekernel/object_cores/index.rst
Source versionZephyr 3.7.0
TranslationFull · reviewed

본문 기준: Zephyr 3.7.0 LTS3 · 이후 유지보수 패치는 별도입니다.

Part 1

요약·해설

Global type list → type별 object-core list → containing object offset의 관계와 통계 등록·조회·reset lifecycle을 설명합니다.

Registry

type · core lists

Traversal

locked · unlocked

Statistics

raw · query

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 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일 수도 있지만 평균 계산처럼 가공된 보고값일 수도 있습니다.

ObjectRaw data typeQuery data type
struct mem_slabstruct mem_slab_infostruct sys_memory_stats
struct sys_mem_blocksstruct sys_mem_blocks_infostruct sys_memory_stats
struct k_threadstruct k_cycle_statsstruct k_thread_runtime_stats
struct _cpustruct k_cycle_statsstruct k_thread_runtime_stats
struct z_kernelstruct 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_CONDVAR
  • CONFIG_OBJ_CORE_EVENT
  • CONFIG_OBJ_CORE_FIFO
  • CONFIG_OBJ_CORE_LIFO
  • CONFIG_OBJ_CORE_MAILBOX
  • CONFIG_OBJ_CORE_MEM_SLAB
  • CONFIG_OBJ_CORE_MSGQ
  • CONFIG_OBJ_CORE_MUTEX
  • CONFIG_OBJ_CORE_PIPE
  • CONFIG_OBJ_CORE_SEM
  • CONFIG_OBJ_CORE_STACK
  • CONFIG_OBJ_CORE_THREAD
  • CONFIG_OBJ_CORE_TIMER
  • CONFIG_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_ID

Condition variable object type ID입니다.

K_OBJ_TYPE_CPU_ID

CPU object type ID입니다.

K_OBJ_TYPE_EVENT_ID

Event object type ID입니다.

K_OBJ_TYPE_FIFO_ID

FIFO object type ID입니다.

K_OBJ_TYPE_KERNEL_ID

Kernel object type ID입니다.

K_OBJ_TYPE_LIFO_ID

LIFO object type ID입니다.

K_OBJ_TYPE_MEM_BLOCK_ID

Memory block object type ID입니다.

K_OBJ_TYPE_MBOX_ID

Mailbox object type ID입니다.

K_OBJ_TYPE_MEM_SLAB_ID

Memory slab object type ID입니다.

K_OBJ_TYPE_MSGQ_ID

Message queue object type ID입니다.

K_OBJ_TYPE_MUTEX_ID

Mutex object type ID입니다.

K_OBJ_TYPE_PIPE_ID

Pipe object type ID입니다.

K_OBJ_TYPE_SEM_ID

Semaphore object type ID입니다.

K_OBJ_TYPE_STACK_ID

Stack object type ID입니다.

K_OBJ_TYPE_THREAD_ID

Thread object type ID입니다.

K_OBJ_TYPE_TIMER_ID

Timer 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 pointer
  • func: 각 object core에 호출할 callback
  • data: 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 pointer
  • func: 각 core에 호출할 callback
  • data: 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 pointer
  • type: 연결할 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: 초기화·연결할 core
  • type: 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_desc

Object-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 node

Object 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_offset

Containing 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 core
  • stats: raw statistics pointer
  • stats_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 core
  • stats: raw stats를 복사할 buffer
  • stats_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 core
  • stats: queried stats를 쓸 buffer
  • stats_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

출처

영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.