2009-03-19 41 views
6

Tôi gặp sự cố lạ. Tôi có đoạn mã sau:pthread_cond_timedwait trả lại ngay lập tức

dbg("condwait: timeout = %d, %d\n", 
     abs_timeout->tv_sec, abs_timeout->tv_nsec); 
    ret = pthread_cond_timedwait(&q->q_cond, &q->q_mtx, abs_timeout); 
    if (ret == ETIMEDOUT) 
    { 
     dbg("cond timed out\n"); 
     return -ETIMEDOUT; 
    } 

dbg cuộc gọi gettimeofday trước mỗi dòng và prepends những phù hợp với thời gian. Nó là kết quả trong đầu ra sau đây:

7.991151: condwait: timeout = 5, 705032704 
    7.991158: cond timed out 

Như bạn có thể thấy, chỉ có 7 micro thông qua vào giữa hai dòng debug, nhưng pthread_cond_timedwait trở ETIMEDOUT. Làm thế nào điều này có thể xảy ra? Tôi thậm chí đã thử đặt đồng hồ thành một thứ khác khi khởi tạo biến số:

int ret; 
ret = pthread_condattr_init(&attributes); 
if (ret != 0) printf("CONDATTR INIT FAILED: %d\n", ret); 
ret = pthread_condattr_setclock(&attributes, CLOCK_REALTIME); 
if (ret != 0) printf("SETCLOCK FAILED: %d\n", ret); 
ret = pthread_cond_init(&q->q_cond, &attributes); 
if (ret != 0) printf("COND INIT FAILED: %d\n", ret); 

(không có thông báo lỗi nào được in ra). Tôi đã thử cả hai CLOCK_REALTIMECLOCK_MONOTONIC.

Mã này là một phần của hàng đợi chặn. Tôi cần chức năng như vậy mà nếu không có gì được đưa vào hàng đợi này trong 5 giây, cái gì khác xảy ra. Các mutex và cond đều được khởi tạo, vì hàng đợi chặn hoạt động tốt nếu tôi không sử dụng pthread_cond_timedwait.

Trả lời

14

pthread_cond_timedwait mất thời gian tuyệt đối, không phải thời gian tương đối. Bạn cần phải làm cho thời gian chờ đợi của bạn tuyệt đối bằng cách thêm vào thời gian hiện tại để giá trị thời gian chờ của bạn.

+0

Tôi hiểu rồi. Bạn có thể sử dụng pthread_get_expiration_np() để tìm ra thời gian abs là gì. – Claudiu

+3

@Claudiu pthread_get_expiration_np() không khả dụng trên GNU/Linux của tôi. Thay vào đó, tôi phải: 'thời gian bây giờ; gettimeofday (& bây giờ, NULL); long int abstime_ns_large = now.tv_usec * 1000 + delay_ns; timespec abstime = {now.tv_sec + (abstime_ns_large/1000000000), abstime_ns_large% 1000000000}; 'trong đó delay_ns là độ trễ mong muốn trong nano giây.Sau đó sử dụng abstime trong cuộc gọi pthread_cond_timedwait của bạn. –

3

Biến điều kiện có thể bỏ chặn giả. Bạn cần phải kiểm tra nó trong một vòng lặp và kiểm tra tình trạng mỗi lần. Có thể bạn sẽ cần phải cập nhật giá trị thời gian chờ quá.

Tôi đã tìm thấy một số tài liệu cho pthread_cond_timedwaithere.

Khi sử dụng các biến điều kiện có luôn là một vị từ Boolean liên quan đến biến chia sẻ liên với mỗi tình trạng chờ đợi đó là sự thật nếu thread nên tiếp tục. Giả mạo các lần đánh thức từ các chức năng pthread_cond_timedwait() hoặc pthread_cond_wait() có thể xảy ra. Vì lợi tức từ pthread_cond_timedwait() hoặc pthread_cond_wait() không ngụ ý bất kỳ điều gì về giá trị của thuộc tính này , vị từ phải được đánh giá lại khi trả lại như vậy.

7

Luồng tràn trong timespec thường là thủ phạm gây ra thời gian chờ lạ.
Kiểm tra EINVAL:

void timespec_add(struct timespec* a, struct timespec* b, struct timespec* out) 
{ 
    time_t sec = a->tv_sec + b->tv_sec; 
    long nsec = a->tv_nsec + b->tv_nsec; 

    sec += nsec/1000000000L; 
    nsec = nsec % 1000000000L; 

    out->tv_sec = sec; 
    out->tv_nsec = nsec; 
} 
0

Như đã có trong câu trả lời khác được đề cập, bạn phải sử dụng thời gian tuyệt đối. Vì C11 bạn có thể sử dụng timespec_get().

struct timespec time; 
timespec_get(&time, TIME_UTC); 
time.tv_sec += 5; 

pthread_cond_timedwait(&cond, &mutex, &time); 
Các vấn đề liên quan