MediaProcessors
interr_usleep.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, 2018 Rafael Antoniello
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
35 #include "interr_usleep.h"
36 
37 #include <stdlib.h>
38 #include <pthread.h>
39 #include <errno.h>
40 
41 #include "log.h"
42 #include "stat_codes.h"
43 #include "check_utils.h"
44 
45 /* **** Definitions **** */
46 
50 typedef struct interr_usleep_ctx_s {
51  volatile int flag_exit;
52  pthread_mutex_t interr_mutex;
53  pthread_cond_t interr_signal;
55 
60 #define UNLOCK() \
61  interr_usleep_ctx->flag_exit= 1; \
62  pthread_mutex_lock(&interr_usleep_ctx->interr_mutex); \
63  pthread_cond_broadcast(&interr_usleep_ctx->interr_signal); \
64  pthread_mutex_unlock(&interr_usleep_ctx->interr_mutex);
65 
66 /* **** Prototypes **** */
67 
68 /* **** Implementations **** */
69 
71 {
72  pthread_condattr_t condattr;
73  int ret_code, end_code= STAT_ERROR;
74  interr_usleep_ctx_t *interr_usleep_ctx= NULL;
75  LOG_CTX_INIT(NULL);
76 
77  /* Allocate context structure */
78  interr_usleep_ctx= (interr_usleep_ctx_t*)calloc(1, sizeof(
80  CHECK_DO(interr_usleep_ctx!= NULL, goto end);
81 
82  /* **** Initialize context structure **** */
83 
84  interr_usleep_ctx->flag_exit= 0;
85 
86  ret_code= pthread_mutex_init(&interr_usleep_ctx->interr_mutex, NULL);
87  CHECK_DO(ret_code== 0, goto end);
88 
89  pthread_condattr_init(&condattr);
90  pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
91  ret_code= pthread_cond_init(&interr_usleep_ctx->interr_signal,
92  &condattr);
93  CHECK_DO(ret_code== 0, goto end);
94 
95  end_code= STAT_SUCCESS;
96 end:
97  if(end_code!= STAT_SUCCESS)
98  interr_usleep_close(&interr_usleep_ctx);
99  return interr_usleep_ctx;
100 }
101 
102 void interr_usleep_close(interr_usleep_ctx_t **ref_interr_usleep_ctx)
103 {
104  interr_usleep_ctx_t *interr_usleep_ctx;
105  LOG_CTX_INIT(NULL);
106 
107  if(ref_interr_usleep_ctx== NULL ||
108  (interr_usleep_ctx= *ref_interr_usleep_ctx)== NULL)
109  return;
110 
111  /* Set exit flag and send signal to eventually unlock MUTEX */
112  UNLOCK();
113 
114  /* Release MUTEX and conditional */
115  ASSERT(pthread_mutex_destroy(&interr_usleep_ctx->interr_mutex)== 0);
116  ASSERT(pthread_cond_destroy(&interr_usleep_ctx->interr_signal)== 0);
117 
118  free(interr_usleep_ctx);
119  *ref_interr_usleep_ctx= NULL;
120 }
121 
123 {
124  LOG_CTX_INIT(NULL);
125 
126  /* Check arguments */
127  CHECK_DO(interr_usleep_ctx!= NULL, return);
128 
129  /* Set exit flag and send signal to eventually unlock MUTEX */
130  UNLOCK();
131 }
132 
133 int interr_usleep(interr_usleep_ctx_t *interr_usleep_ctx, uint32_t usec)
134 {
135  register uint64_t curr_nsec;
136  struct timespec monotime_curr, monotime_tout;
137  int ret_code;
138  LOG_CTX_INIT(NULL);
139 
140  /* Check arguments */
141  CHECK_DO(interr_usleep_ctx!= NULL, return STAT_ERROR);
142 
143  /* Get current time */
144  CHECK_DO(clock_gettime(CLOCK_MONOTONIC, &monotime_curr)== 0,
145  return STAT_ERROR);
146  curr_nsec= (uint64_t)monotime_curr.tv_sec*1000000000+
147  (uint64_t)monotime_curr.tv_nsec;
148 
149  /* Compute time-out */
150  curr_nsec+= ((uint64_t)usec)* 1000;
151  //LOGV("+tout_nsec: %"PRId64"\n", curr_nsec); //comment-me
152  monotime_tout.tv_sec= curr_nsec/ 1000000000;
153  monotime_tout.tv_nsec= curr_nsec% 1000000000;
154  //curr_nsec= (uint64_t)monotime_tout.tv_sec*1000000000+
155  // (uint64_t)monotime_tout.tv_nsec; //comment-me
156  //LOGV("tout_nsec: %"PRId64"\n", curr_nsec); //comment-me
157 
158  /* While exit is not signaled, block for the given time */
159  pthread_mutex_lock(&interr_usleep_ctx->interr_mutex);
160  ret_code= STAT_SUCCESS;
161  while(interr_usleep_ctx->flag_exit== 0 && ret_code!= ETIMEDOUT) {
162  ret_code= pthread_cond_timedwait(
163  &interr_usleep_ctx->interr_signal,
164  &interr_usleep_ctx->interr_mutex, &monotime_tout);
165  }
166  pthread_mutex_unlock(&interr_usleep_ctx->interr_mutex);
167  return (ret_code== ETIMEDOUT)? STAT_SUCCESS: STAT_EINTR;
168 }
interr_usleep_ctx_t * interr_usleep_open()
Definition: interr_usleep.c:70
void interr_usleep_unblock(interr_usleep_ctx_t *interr_usleep_ctx)
General status codes enumeration.
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
#define UNLOCK()
Definition: interr_usleep.c:60
#define ASSERT(COND)
Definition: check_utils.h:51
struct interr_usleep_ctx_s interr_usleep_ctx_t
int interr_usleep(interr_usleep_ctx_t *interr_usleep_ctx, uint32_t usec)
Interruptible usleep module. This module ("interruptible usleep") implements a wrapper to the &#39;usleep...
void interr_usleep_close(interr_usleep_ctx_t **ref_interr_usleep_ctx)