Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / 3rd-party / zisofs_tools / workers.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 #ident "$Id: workers.c,v 1.3 2006/07/04 04:57:42 hpa Exp $"
14 /* ----------------------------------------------------------------------- *
15  *   
16  *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
17  *
18  *   This program is free software; you can redistribute it and/or modify
19  *   it under the terms of the GNU General Public License as published by
20  *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
21  *   USA; either version 2 of the License, or (at your option) any later
22  *   version; incorporated herein by reference.
23  *
24  * ----------------------------------------------------------------------- */
25
26 /*
27  * workers.c
28  *
29  * Parallel job maintenance
30  */
31
32 #include "mkzftree.h"           /* Must be included first! */
33
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <sys/wait.h>
40
41 /* Global option */
42 extern int parallel;            /* Number of parallel jobs */
43
44 /* Functions related to parallel execution */
45 static volatile int work_threads = 0;
46 static int is_worker = 0;
47
48 /* This waits for one worker to finish */
49 static void wait_for_one_worker(void)
50 {
51   int status;
52
53   if ( wait(&status) > 0 ) {
54     work_threads--;
55     
56     if ( WIFSIGNALED(status) ) {
57       kill(getpid(), WTERMSIG(status));
58       exit(EX_SOFTWARE);
59     } else if ( WEXITSTATUS(status) ) {
60       exit(WEXITSTATUS(status));
61     }
62   }
63 }  
64
65 /* This waits for *all* workers to finish */
66 void wait_for_all_workers(void)
67 {
68   while ( work_threads )
69     wait_for_one_worker();
70 }
71
72 /* This returns 1 if the "job" at hand should be performed */
73 int spawn_worker(void)
74 {
75   pid_t f;
76   
77   if ( opt.parallel == 0 )
78     return 1;
79
80   fflush(NULL);
81
82   /* Wait for a work slot */
83   while ( work_threads >= opt.parallel )
84     wait_for_one_worker();
85   
86   /* Spawn worker process */
87   work_threads++;               /* Avoids race conditions */
88   f = fork();
89   if ( f == -1 ) {
90     work_threads--;
91     return 1;                   /* Do it ourselves */
92   }
93
94   if ( f == 0 ) {
95     /* Worker process */
96     is_worker = 1;
97     return 1;
98   } else {
99     /* Control process */
100     return 0;
101   }
102 }
103
104 /* Routine to perform at the end of the job */
105 void end_worker(int err)
106 {
107   if ( is_worker ) {
108     exit(err);
109   }
110 }
111