GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../waitq.c Lines: 0 29 0.0 %
Date: 2017-11-13 Branches: 0 62 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: waitq.c,v 1.5 2015/01/20 17:37:54 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/socket.h>
21
#include <sys/queue.h>
22
#include <sys/tree.h>
23
#include <sys/uio.h>
24
25
#include <imsg.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <limits.h>
29
30
#include "smtpd.h"
31
32
struct waiter {
33
	TAILQ_ENTRY(waiter)	 entry;
34
	void			(*cb)(void *, void *, void *);
35
	void			*arg;
36
};
37
38
struct waitq {
39
	SPLAY_ENTRY(waitq)	 entry;
40
	void			*tag;
41
	TAILQ_HEAD(, waiter)	 waiters;
42
};
43
44
static int waitq_cmp(struct waitq *, struct waitq *);
45
46
SPLAY_HEAD(waitqtree, waitq);
47
SPLAY_PROTOTYPE(waitqtree, waitq, entry, waitq_cmp);
48
49
static struct waitqtree waitqs = SPLAY_INITIALIZER(&waitqs);
50
51
static int
52
waitq_cmp(struct waitq *a, struct waitq *b)
53
{
54
	if (a->tag < b->tag)
55
		return (-1);
56
	if (a->tag > b->tag)
57
		return (1);
58
	return (0);
59
}
60
61
SPLAY_GENERATE(waitqtree, waitq, entry, waitq_cmp);
62
63
int
64
waitq_wait(void *tag, void (*cb)(void *, void *, void *), void *arg)
65
{
66
	struct waitq	*wq, key;
67
	struct waiter	*w;
68
69
	key.tag = tag;
70
	wq = SPLAY_FIND(waitqtree, &waitqs, &key);
71
	if (wq == NULL) {
72
		wq = xmalloc(sizeof *wq, "waitq_wait");
73
		wq->tag = tag;
74
		TAILQ_INIT(&wq->waiters);
75
		SPLAY_INSERT(waitqtree, &waitqs, wq);
76
	}
77
78
	w = xmalloc(sizeof *w, "waitq_wait");
79
	w->cb = cb;
80
	w->arg = arg;
81
	TAILQ_INSERT_TAIL(&wq->waiters, w, entry);
82
83
	return (w == TAILQ_FIRST(&wq->waiters));
84
}
85
86
void
87
waitq_run(void *tag, void *result)
88
{
89
	struct waitq	*wq, key;
90
	struct waiter	*w;
91
92
	key.tag = tag;
93
	wq = SPLAY_FIND(waitqtree, &waitqs, &key);
94
	SPLAY_REMOVE(waitqtree, &waitqs, wq);
95
96
	while ((w = TAILQ_FIRST(&wq->waiters))) {
97
		TAILQ_REMOVE(&wq->waiters, w, entry);
98
		w->cb(tag, w->arg, result);
99
		free(w);
100
	}
101
	free(wq);
102
}