Imported Upstream version 4.2
[platform/upstream/make.git] / w32 / w32os.c
1 /* Windows32-based operating system interface for GNU Make.
2 Copyright (C) 2016 Free Software Foundation, Inc.
3 This file is part of GNU Make.
4
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
8 version.
9
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include "makeint.h"
18
19 #include <stdio.h>
20 #include <string.h>
21
22 #include <windows.h>
23 #include <process.h>
24 #include <io.h>
25 #include "pathstuff.h"
26 #include "sub_proc.h"
27 #include "w32err.h"
28 #include "os.h"
29 #include "debug.h"
30
31 /* This section provides OS-specific functions to support the jobserver.  */
32
33 static char jobserver_semaphore_name[MAX_PATH + 1];
34 static HANDLE jobserver_semaphore = NULL;
35
36 unsigned int
37 jobserver_setup (int slots)
38 {
39   /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects
40    * and one of them is the job-server semaphore object.  Limit the
41    * number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */
42
43   if (slots >= MAXIMUM_WAIT_OBJECTS)
44     {
45       slots = MAXIMUM_WAIT_OBJECTS - 1;
46       DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), slots));
47     }
48
49   sprintf (jobserver_semaphore_name, "gmake_semaphore_%d", _getpid ());
50
51   jobserver_semaphore = CreateSemaphore (
52       NULL,                           /* Use default security descriptor */
53       slots,                          /* Initial count */
54       slots,                          /* Maximum count */
55       jobserver_semaphore_name);      /* Semaphore name */
56
57   if (jobserver_semaphore == NULL)
58     {
59       DWORD err = GetLastError ();
60       const char *estr = map_windows32_error_to_string (err);
61       ONS (fatal, NILF,
62            _("creating jobserver semaphore: (Error %ld: %s)"), err, estr);
63     }
64
65   return 1;
66 }
67
68 unsigned int
69 jobserver_parse_auth (const char *auth)
70 {
71   jobserver_semaphore = OpenSemaphore (
72       SEMAPHORE_ALL_ACCESS,   /* Semaphore access setting */
73       FALSE,                  /* Child processes DON'T inherit */
74       auth);                  /* Semaphore name */
75
76   if (jobserver_semaphore == NULL)
77     {
78       DWORD err = GetLastError ();
79       const char *estr = map_windows32_error_to_string (err);
80       fatal (NILF, strlen (auth) + INTSTR_LENGTH + strlen (estr),
81              _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
82              auth, err, estr);
83     }
84   DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), auth));
85
86   return 1;
87 }
88
89 char *
90 jobserver_get_auth ()
91 {
92   return xstrdup (jobserver_semaphore_name);
93 }
94
95 unsigned int
96 jobserver_enabled ()
97 {
98   return jobserver_semaphore != NULL;
99 }
100
101 /* Close jobserver semaphore */
102 void
103 jobserver_clear ()
104 {
105   if (jobserver_semaphore != NULL)
106     {
107       CloseHandle (jobserver_semaphore);
108       jobserver_semaphore = NULL;
109     }
110 }
111
112 void
113 jobserver_release (int is_fatal)
114 {
115   if (! ReleaseSemaphore (
116           jobserver_semaphore,    /* handle to semaphore */
117           1,                      /* increase count by one */
118           NULL))                  /* not interested in previous count */
119     {
120       if (is_fatal)
121         {
122           DWORD err = GetLastError ();
123           const char *estr = map_windows32_error_to_string (err);
124           ONS (fatal, NILF,
125                _("release jobserver semaphore: (Error %ld: %s)"), err, estr);
126         }
127       perror_with_name ("release_jobserver_semaphore", "");
128     }
129 }
130
131 unsigned int
132 jobserver_acquire_all ()
133 {
134   unsigned int tokens = 0;
135   while (1)
136     {
137       DWORD dwEvent = WaitForSingleObject (
138           jobserver_semaphore,    /* Handle to semaphore */
139           0);                     /* DON'T wait on semaphore */
140
141       if (dwEvent != WAIT_OBJECT_0)
142         return tokens;
143
144       ++tokens;
145     }
146 }
147
148 void
149 jobserver_signal ()
150 {
151 }
152
153 void jobserver_pre_child (int recursive)
154 {
155 }
156
157 void jobserver_post_child (int recursive)
158 {
159 }
160
161 void
162 jobserver_pre_acquire ()
163 {
164 }
165
166 /* Returns 1 if we got a token, or 0 if a child has completed.
167    The Windows implementation doesn't support load detection.  */
168 unsigned int
169 jobserver_acquire (int timeout)
170 {
171     HANDLE handles[MAXIMUM_WAIT_OBJECTS];
172     DWORD dwHandleCount;
173     DWORD dwEvent;
174
175     /* Add jobserver semaphore to first slot. */
176     handles[0] = jobserver_semaphore;
177
178     /* Build array of handles to wait for.  */
179     dwHandleCount = 1 + process_set_handles (&handles[1]);
180
181     dwEvent = WaitForMultipleObjects (
182         dwHandleCount,  /* number of objects in array */
183         handles,        /* array of objects */
184         FALSE,          /* wait for any object */
185         INFINITE);      /* wait until object is signalled */
186
187     if (dwEvent == WAIT_FAILED)
188       {
189         DWORD err = GetLastError ();
190         const char *estr = map_windows32_error_to_string (err);
191         ONS (fatal, NILF,
192              _("semaphore or child process wait: (Error %ld: %s)"),
193              err, estr);
194       }
195
196     /* WAIT_OBJECT_0 indicates that the semaphore was signalled.  */
197     return dwEvent == WAIT_OBJECT_0;
198 }