2013-04-30 21 views
5

Dưới đây là mẹo được sử dụng trong hạt nhân Linux cho các vật có giá trị trên mỗi cpu. Khi nhận xét cho biết, nó có thể đạt được hai mục tiêu sau:Làm thế nào để đảm bảo tính độc đáo của các biểu tượng toàn cầu và hạn chế phạm vi của nó trong C?

1. phạm vi bắt buộc.

2.đảm bảo tính duy nhất, thậm chí là tính năng tĩnh.

Sau đây là cách các vở kịch ma thuật (Để đơn giản, tôi subsititude của một số MACRO):

/* 
* __pcpu_scope_* dummy variable is used to enforce scope. It 
* receives the static modifier when it's used in front of 
* DEFINE_PER_CPU() and will trigger build failure if 
* DECLARE_PER_CPU() is used for the same variable. 
* 
* __pcpu_unique_* dummy variable is used to enforce symbol uniqueness 
* such that hidden weak symbol collision, which will cause unrelated 
* variables to share the same address, can be detected during build. 
*/ 
#define DECLARE_PER_CPU_SECTION(type, name, sec)      \ 
extern __attribute__((section(".discard"), unused))      \ 
       char __pcpu_scope_##name;         \ 
extern __attribute__((section(sec))) __typeof__(type) name 

#define DEFINE_PER_CPU_SECTION(type, name, sec)       \ 
__attribute__((section(".discard"), unused)) char __pcpu_scope_##name; \ 
extern __attribute__((section(".discard"), unused))      \ 
      char __pcpu_unique_##name;         \ 
__attribute__((section(".discard"), unused)) char __pcpu_unique_##name; \ 
__attribute__((section(sec))) __attribute__((weak))     \ 
       __typeof__(type) name 

Câu hỏi của tôi là

  1. nhất cho mục tiêu # 1. Làm thế nào nó có thể thực thi phạm vi? Liệu nó làm việc như thế này:

    Khi DECLARE * và DEFINE * tồn tại trong cùng đơn vị traslation, nó sẽ biến biến trong câu hỏi để liên kết nội bộ, và do đó, bất kỳ DECLARE * thêm cho cùng một biến sẽ kích hoạt xây dựng thất bại (nguyên nhân họ không đồng ý về mối liên hệ)

    Nhưng nếu điều này là đúng, sau đó

    • Làm thế nào các công trình interal-liên kết-receivement? Từ C99 6.9.2.2 (Định nghĩa đối tượng bên ngoài), điều này chỉ xảy ra cho định nghĩa dự kiến ​​, nhưng trường hợp này có vẻ không phải là định nghĩa dự kiến ​​?
    • Điều này không vi phạm quy tắc "One-definition-and-mutiple-declarationations-are-OK"?
  2. nhất cho mục tiêu # 2, hai __pcpu_unique _ ## tên decalation (chính xác, một là tuyên bố, một trong những khác là định nghĩa) có vẻ chơi trcik giống như __pcpu_scope _ ## tên, thì làm sao nó giúp đỡ để đảm bảo tính độc đáo?

FYI, các mã trong câu hỏi có thể được xem tại đây: http://lxr.linux.no/linux+v3.9/include/linux/percpu-defs.h#L61

Trả lời

4

Tôi không nghĩ rằng đây là thực thi bởi trình biên dịch. Xem ARM vmlinux.lds.S, vmlinux.lds.hpercpu.h; tệp liên kết được xử lý trước để sử dụng kernel biến cấu hình. Các phần ".discard" là một loạt các biểu tượng sẽ gây xung đột liên kết trên nhiều định nghĩa; nhưng chúng được bỏ đi và không biến nó thành nhị phân.

Xem macroPER_CPU, PER_CPU_FIRST, PER_CPU_SHARED_ALIGNED, vv Những macro chỉ mất một loại tên.

Mở rộng vĩ mô của bạn không chính xác.

#define DECLARE_PER_CPU_SECTION(type, name, sec)      \ 
extern __attribute__((section(".discard"), unused))      \ 
       char __pcpu_scope_##name;         \ 
extern __attribute__((section(PER_CPU_BASE_SECTION sec))) __typeof__(type) name 

Các giây thông số thực sự là một tiểu mục; lưu ý PER_CPU_BASE_SECTION và nối chuỗi.

Như tôi đã hiểu, Nó nhận được công cụ sửa đổi tĩnh ... có vẻ gây hiểu nhầm. Nó sẽ được thể hiện rõ hơn là Nếunó nhận được .... Vì vậy, những trường hợp này là khác nhau,

static DEFINE_PER_CPU_PAGE_ALIGNED(... /* Cause error with DECLARE */ 
DEFINE_PER_CPU(unsigned int, irq_count) = -1; /* Fine with DECLARE */ 

Trong mọi trường hợp, điều này không được thực thi bởi trình biên dịch, nhưng do GNU mối liên kết (hoặc ít nhất là cả hai) là điều quan trọng là những giá trị này là bộ nhớ cache liên kết và trong một số trường hợp, kích thước bộ nhớ cache được cấu hình bởi cơ sở hạ tầng kbuild.

Nó cũng quan trọng cần lưu ý một lời nhận xét trước đó liên quan đến thế hệ mã,

* s390 and alpha modules require percpu variables to be defined as 
* weak to force the compiler to generate GOT based external 
* references for them. This is necessary because percpu sections 
* will be located outside of the usually addressable area. 
* This definition puts the following two extra restrictions when 
* defining percpu variables. 
* 
* 1. The symbol must be globally unique, even the static ones. 
* 2. Static percpu variables cannot be defined inside a function. 
* 
* Archs which need weak percpu definitions should define 
* ARCH_NEEDS_WEAK_PER_CPU in asm/percpu.h when necessary. 

Ie, các __attribute__((weak)) đang được sử dụng không cho độ phân giải biểu tượng nhưng đối với tác dụng phụ hệ mã. Có một điều kiện #else trong đó biến chứng weak không bị làm phiền.

Bây giờ để trả lời câu hỏi của bạn một thời gian ngắn,

nhất cho mục tiêu # 1. Làm thế nào nó có thể thực thi phạm vi?

Cả một tổ chức phi tĩnh kết quả khai tĩnhkhi chúng ta có,

DECLARE_PER_CPU_PAGE_ALIGNED(int,foobar); 
static DEFINE_PER_CPU_PAGE_ALIGNED(int,foobar); 

nhất cho mục tiêu # 2, ... __pcpu_unique_##name, thì làm sao nó giúp đảm bảo sự độc đáo ?

Nhiều biểu tượng weak không gây ra lỗi. __pcpu_unique_##name không phải là weak do đó nó đang được sử dụng để thực thi tính duy nhấtweak đang được sử dụng cho các lý do tạo mã.

Xem Gcc's function attributes và tìm kiếm yếu, trong trường hợp mục đích thông thường của yếu không được hiểu.

+0

Đối với những người quan tâm, Google: [lkml + DECLARE_PER_CPU_SECTION + yếu] (https://www.google.ca/#q=lkml+DECLARE_PER_CPU_SECTION+weak) –

+0

Cảm ơn rất nhiều :) – larmbr

Các vấn đề liên quan