aboutsummaryrefslogtreecommitdiff
path: root/src/pth.c
blob: b727436898461910582fcfd6dc7bfadddc20dfb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <errno.h>

#include "util_rt.h"
#include "pth.h"


void prne_init_worker (prne_worker_t *w) {
	w->ctx = NULL;
	w->entry = NULL;
	w->fin = NULL;
	w->free_ctx = NULL;
	w->pth = NULL;
}

void prne_free_worker (prne_worker_t *w) {
	if (w->ctx != NULL) {
		prne_assert(w->free_ctx != NULL);	
		w->free_ctx(w->ctx);
		w->ctx = NULL;
	}
}

void prne_fin_worker (prne_worker_t *w) {
	if (w->fin != NULL) {
		w->fin(w->ctx);
	}
}

bool prne_pth_cv_notify (prne_pth_cv_t *cv) {
	bool ret;

	if (pth_mutex_acquire(cv->lock, FALSE, NULL)) {
		ret = pth_cond_notify(cv->cond, cv->broadcast) == 0;
		prne_assert(pth_mutex_release(cv->lock));
	}
	else {
		ret = false;
	}

	return ret;
}

bool prne_pth_cond_timedwait (prne_pth_cv_t *cv, const struct timespec *timeout, bool *to_reached) {
	pth_event_t ev;
	bool ret, reached;

	if (timeout != NULL) {
		ev = pth_event(PTH_EVENT_TIME, pth_timeout(timeout->tv_sec, timeout->tv_nsec / 1000));
		if (ev == NULL) {
			return -1;
		}
	}
	else {
		ev = NULL;
	}

	if (pth_mutex_acquire(cv->lock, FALSE, NULL)) {
		ret = pth_cond_await(cv->cond, cv->lock, ev);
		prne_assert(pth_mutex_release(cv->lock));
	}
	else {
		ret = false;
	}
	
	if (ev != NULL && pth_event_occurred(ev)) {
		ret = true;
		reached = true;
	}
	else {
		reached = false;
	}

	if (to_reached != NULL) {
		*to_reached = reached;
	}

	pth_event_free(ev, FALSE);
	return ret;
}

int prne_unint_pth_poll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout) {
	pth_event_t ev;
	int ret;

	if (timeout != NULL) {
		ev = pth_event(PTH_EVENT_TIME, pth_timeout(timeout->tv_sec, timeout->tv_nsec / 1000));
		if (ev == NULL) {
			return -1;
		}
	}
	else {
		ev = NULL;
	}

	do {
		ret = pth_poll_ev(fds, nfds, -1, ev);
		if (ev != NULL && pth_event_occurred(ev)) {
			ret = 0;
			break;
		}
		if (ret < 0 && errno == EINTR) {
			continue;
		}
	} while (false);

	pth_event_free(ev, FALSE);
	return ret;
}

void prne_unint_pth_nanosleep (struct timespec dur) {
	struct timespec rem;

	while (pth_nanosleep(&dur, &rem) < 0 && errno == EINTR) {
		dur = rem;
	}
}