2010-09-22 32 views
7

Mặc dù chủ đề này đã được thảo luận nhiều lần trong diễn đàn này và tất cả các diễn đàn khác, tôi vẫn còn nghi ngờ. Hãy giúp tôi.cách thực hiện {} trong khi (0) hoạt động trong macro?

Làm cách nào để do{} while(0) hoạt động vĩ mô trong hạt nhân Linux? Ví dụ:

#define preempt_disable() do { } while (0) 

Làm cách nào để vô hiệu hóa chế độ xem trước?

#define might_resched() do { } while (0) 

Làm cách nào để lên lịch lại?

Tương tự như vậy tôi đã thấy các macro cho khóa mutex và các loại khác. Điều này giúp ích như thế nào? Tôi hiểu cho vấn đề sau nhưng không phải cho các ví dụ trên.

#define foo(x) do { do something } while(0) 

Edit:

gì về đoạn mã sau cho rt_mutex_lock?

/** 
* rt_mutex_lock - lock a rt_mutex 
* 
* @lock: the rt_mutex to be locked 
*/ 
void __sched rt_mutex_lock(struct rt_mutex *lock) 
{ 
     might_sleep(); 
     rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock); 
} 
EXPORT_SYMBOL_GPL(rt_mutex_lock); 


/* 
* debug aware fast/slowpath lock,trylock,unlock 
* 
* The atomic acquire/release ops are compiled away, when either the 
* architecture does not support cmpxchg or when debugging is enabled. 
*/ 

static inline int rt_mutex_fastlock(struct rt_mutex *lock, 
    int state, int detect_deadlock, int (*slowfn)(struct rt_mutex *lock, 
    int state, struct hrtimer_sleeper *timeout, int detect_deadlock)) 
{ 
     if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { 
       rt_mutex_deadlock_account_lock(lock, current); 
       return 0; 
     } else{ 
       return slowfn(lock, state, NULL, detect_deadlock); 
     } 
} 

Tôi đang bối rối vì rt_mutex_deadlock_account_lock là xác định ở hai nơi trong kernel:

Trong kernel/rtmutex-debug.c:

void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, 
    struct task_struct *task) 
{ 
    //.... 
} 

Trong kernel/rtmutex.h:

#define rt_mutex_deadlock_account_lock(m, t) do { } while (0) 

Trong hạt nhân mới 2.6. 35.4 trong trình điều khiển i2c rt_mutex_lock(&adap->bus_lock); ha s đã thay thế số mutex_lock(). Làm thế nào để khóa này sau đó?

+0

trông giống như tôi định nghĩa lại chức năng đó để không làm gì cả. – mpen

+0

@Mark: Âm thanh thuyết phục. ravspratapsingh: Chúng ta có đúng không đối với hai câu trên, không có gì thực sự giữa niềng răng? Hay bạn chỉ đơn giản hóa mã theo cách này? – chiccodoro

+0

có thể trùng lặp của [Việc sử dụng làm gì trong khi (0) khi chúng tôi xác định macro?] (Http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we- define-a-macro) – paxdiablo

Trả lời

5

@Kragen đã trả lời những việc cần làm ... trong khi xây dựng cho - về cơ bản nó làm cho macro trở nên an toàn hơn nhiều để sử dụng.

Tuy nhiên, tôi không nghĩ rằng nó trả lời câu hỏi "làm thế nào không làm việc này?":

#define preempt_disable() do { } while (0) 

Các vĩ mô được xác định để làm gì . Tại sao bạn không muốn làm gì?

  • Trong một số trường hợp, bạn muốn sử dụng macro làm trình giữ chỗ để thực hiện điều gì đó.Ví dụ, bạn có thể viết mã trên một hệ thống mà "preempt" không phải là một vấn đề, nhưng bạn biết mã có thể được chuyển đến một hệ thống nơi "preempt" cần xử lý đặc biệt. Vì vậy, bạn sử dụng macro ở mọi nơi mà hệ thống thứ hai cần nó (để việc xử lý dễ dàng kích hoạt sau), nhưng đối với hệ thống đầu tiên, bạn xác định macro đó là macro trống.

  • Trong một số trường hợp, bạn có thể muốn làm những việc như công việc được tạo thành từ các phần khác nhau, (ví dụ: START_TABLE(); TABLE_ENTRY (1); TABLE_ENTRY (2); END_TABLE();). Điều này làm cho việc thực hiện rõ ràng rõ ràng trong bảng của bạn. Nhưng sau đó bạn thấy rằng bạn không thực sự cần macro END_TABLE(). Để giữ mã khách hàng gọn gàng, bạn để macro được xác định và chỉ cần xác định nó để không làm gì cả. Bằng cách đó, tất cả các bảng của bạn có một END_TABLE và mã dễ đọc hơn. Một trường hợp tương tự có thể xảy ra với hai trạng thái (cho phép/vô hiệu hóa) trong đó một trạng thái cần macro để làm điều gì đó, nhưng trạng thái khác chỉ xảy ra theo mặc định, vì vậy việc thực hiện một là "trống" - bạn vẫn sử dụng macro vì nó làm cho mã máy khách dễ hiểu hơn, vì nó nêu rõ các địa điểm nơi mọi thứ được kích hoạt hoặc vô hiệu hóa.

+0

nếu 'do {} trong khi (0)' không làm gì cả. Trình biên dịch có tạo ra các hướng dẫn rác vì nó hay vòng lặp sẽ được tối ưu hóa không? – Zingam

+1

Trình biên dịch có trình tối ưu hóa rất tốt những ngày này, vì vậy bạn rất khó có thể tìm thấy một trong những chất thải thời gian trên một trường hợp trống rỗng rõ ràng như thế này. –

11

Xem this link để có giải thích tốt hơn tôi có thể cung cấp.

+2

+1 Chỉ cần bật lên một mức không giới hạn, trích dẫn đầu tiên sẽ trả lời câu hỏi: (từ Dave Miller) Các câu lệnh trống đưa ra cảnh báo từ trình biên dịch vì vậy đây là lý do tại sao bạn thấy '#define FOO do {} trong khi (0) '. –

3

IIRC việc sử dụng các do-while trong macro là làm cho chúng trông giống như một lời gọi hàm bình thường; có một số vấn đề cú pháp tinh tế xung quanh các câu lệnh if và những thứ tương tự như vậy. Không có macro trong khi macro có thể trông giống như một lời gọi hàm bình thường nhưng sẽ hoạt động khác nhau.

Tôi đoán rằng trong trường hợp này, các macro này đang được sử dụng để các cuộc gọi chức năng nhất định không được biên dịch; có vẻ như đó là những gì bạn nhận được nếu CONFIG_PREEMPT không được thiết lập, vì vậy một số phần nhất định của hạt nhân chỉ cần thiết cho việc từ chối đơn giản là biến mất mà không có nó. Vì vậy, các vòng lặp đó không vô hiệu hóa trước hoặc lên lịch lại bất cứ điều gì; sẽ có một định nghĩa khác (có thể là một hàm thực) ở đâu đó trong nguồn kernel.

+0

Cảm ơn, tôi hiểu điều này làm việc như thế nào nhưng vẫn còn nhầm lẫn về khóa mutex. Xin vui lòng xem trả lời của tôi về rt_mutex_lock – iSegFault

+1

Tôi giả định khóa mutex là một cái gì đó tương tự - có một "thực sự" thực hiện và một "giả" một trong đó không có gì. Có lẽ trong một số trường hợp, giả được sử dụng nếu hạt nhân được cấu hình sao cho không bao giờ cần đến nó - có thể nếu CONFIG_SMP không được kích hoạt? – Peter

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