1 | /* |
2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"). |
5 | * You may not use this file except in compliance with the License. |
6 | * A copy of the License is located at |
7 | * |
8 | * http://aws.amazon.com/apache2.0 |
9 | * |
10 | * or in the "license" file accompanying this file. This file is distributed |
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
12 | * express or implied. See the License for the specific language governing |
13 | * permissions and limitations under the License. |
14 | */ |
15 | |
16 | #include <aws/common/condition_variable.h> |
17 | |
18 | #include <aws/common/clock.h> |
19 | #include <aws/common/mutex.h> |
20 | |
21 | #include <errno.h> |
22 | |
23 | static int process_error_code(int err) { |
24 | switch (err) { |
25 | case ENOMEM: |
26 | return aws_raise_error(AWS_ERROR_OOM); |
27 | case ETIMEDOUT: |
28 | return aws_raise_error(AWS_ERROR_COND_VARIABLE_TIMED_OUT); |
29 | default: |
30 | return aws_raise_error(AWS_ERROR_COND_VARIABLE_ERROR_UNKNOWN); |
31 | } |
32 | } |
33 | |
34 | int aws_condition_variable_init(struct aws_condition_variable *condition_variable) { |
35 | if (pthread_cond_init(&condition_variable->condition_handle, NULL)) { |
36 | return aws_raise_error(AWS_ERROR_COND_VARIABLE_INIT_FAILED); |
37 | } |
38 | |
39 | return AWS_OP_SUCCESS; |
40 | } |
41 | |
42 | void aws_condition_variable_clean_up(struct aws_condition_variable *condition_variable) { |
43 | pthread_cond_destroy(&condition_variable->condition_handle); |
44 | } |
45 | |
46 | int aws_condition_variable_notify_one(struct aws_condition_variable *condition_variable) { |
47 | int err_code = pthread_cond_signal(&condition_variable->condition_handle); |
48 | |
49 | if (err_code) { |
50 | return process_error_code(err_code); |
51 | } |
52 | |
53 | return AWS_OP_SUCCESS; |
54 | } |
55 | |
56 | int aws_condition_variable_notify_all(struct aws_condition_variable *condition_variable) { |
57 | int err_code = pthread_cond_broadcast(&condition_variable->condition_handle); |
58 | |
59 | if (err_code) { |
60 | return process_error_code(err_code); |
61 | } |
62 | |
63 | return AWS_OP_SUCCESS; |
64 | } |
65 | |
66 | int aws_condition_variable_wait(struct aws_condition_variable *condition_variable, struct aws_mutex *mutex) { |
67 | int err_code = pthread_cond_wait(&condition_variable->condition_handle, &mutex->mutex_handle); |
68 | |
69 | if (err_code) { |
70 | return process_error_code(err_code); |
71 | } |
72 | |
73 | return AWS_OP_SUCCESS; |
74 | } |
75 | |
76 | int aws_condition_variable_wait_for( |
77 | struct aws_condition_variable *condition_variable, |
78 | struct aws_mutex *mutex, |
79 | int64_t time_to_wait) { |
80 | |
81 | uint64_t current_sys_time = 0; |
82 | if (aws_sys_clock_get_ticks(¤t_sys_time)) { |
83 | return AWS_OP_ERR; |
84 | } |
85 | |
86 | time_to_wait += current_sys_time; |
87 | |
88 | struct timespec ts; |
89 | uint64_t remainder = 0; |
90 | ts.tv_sec = |
91 | (time_t)aws_timestamp_convert((uint64_t)time_to_wait, AWS_TIMESTAMP_NANOS, AWS_TIMESTAMP_SECS, &remainder); |
92 | ts.tv_nsec = (long)remainder; |
93 | |
94 | int err_code = pthread_cond_timedwait(&condition_variable->condition_handle, &mutex->mutex_handle, &ts); |
95 | |
96 | if (err_code) { |
97 | return process_error_code(err_code); |
98 | } |
99 | |
100 | return AWS_OP_SUCCESS; |
101 | } |
102 | |