1 /* COPYING ******************************************************************
2 For copyright and licensing terms, see the file named COPYING.
3 // **************************************************************************
4 */
5 
6 #include <cstring>
7 #include <cstdlib>
8 #include <iostream>
9 #include <iomanip>
10 #include <unistd.h>
11 #include <poll.h>
12 #include "redo.h"
13 #include "jobserver.h"
14 
15 /* The GNU make jobserver ***************************************************
16 // **************************************************************************
17 */
18 
19 using namespace jobserver;
20 
21 int jobserver::fds[2] = { -1, -1 };
22 
23 static unsigned implicit_jobs = 1;
24 
25 bool
try_procure_slot(const char * prog)26 jobserver::try_procure_slot(
27 	const char * prog
28 ) {
29 	if (implicit_jobs) {
30 		--implicit_jobs;
31 		if (debug) {
32 			msg(prog, "INFO") << "Procured implicit job slot that is this process itself.\n";
33 		}
34 		return true;
35 	}
36 	if (-1 != fds[0]) {
37 		pollfd p;
38 		p.fd = fds[0];
39 		p.events = POLLIN;
40 		const int r0(poll(&p, sizeof p/sizeof(pollfd), 0));
41 		if ((0 <= r0) && (p.revents & POLLIN)) {
42 			char c;
43 			const ssize_t r(read(fds[0], &c, sizeof c));
44 			if (debug) {
45 				if (0 < r)
46 					msg(prog, "INFO") << "Procured a job slot from the jobserver.\n";
47 				else
48 					msg(prog, "INFO") << "Failed to procure a job slot from the jobserver.\n";
49 			}
50 			return 0 < r;
51 		}
52 	}
53 	return false;
54 }
55 
56 bool
procure_slot(const char * prog)57 jobserver::procure_slot(
58 	const char * prog
59 ) {
60 	if (implicit_jobs) {
61 		--implicit_jobs;
62 		if (debug) {
63 			msg(prog, "INFO") << "Procured implicit job slot that is this process itself.\n";
64 		}
65 		return true;
66 	}
67 	if (-1 != fds[0]) {
68 		char c;
69 		const ssize_t r(read(fds[0], &c, sizeof c));
70 		if (debug) {
71 			if (0 < r)
72 				msg(prog, "INFO") << "Procured a job slot from the jobserver.\n";
73 			else
74 				msg(prog, "INFO") << "Failed to procure a job slot from the jobserver.\n";
75 		}
76 		return 0 < r;
77 	}
78 	return false;
79 }
80 
81 void
vacate_slot(const char * prog)82 jobserver::vacate_slot(
83 	const char * prog
84 ) {
85 	if (!implicit_jobs) {
86 		++implicit_jobs;
87 		if (debug) {
88 			msg(prog, "INFO") << "Vacated implicit job slot that is this process itself.\n";
89 		}
90 	} else
91 	if (-1 != fds[1]) {
92 		const char c('\0');
93 		write(fds[1], &c, sizeof c);
94 		if (debug) {
95 			msg(prog, "INFO") << "Vacated a job slot to the jobserver.\n";
96 		}
97 	}
98 }
99