summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/runqueue.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/runqueue.py')
-rw-r--r--bitbake/lib/bb/runqueue.py124
1 files changed, 62 insertions, 62 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index c5f4380c86..a4aea6c004 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -22,15 +22,15 @@ Handles preparation and execution of a queue of tasks
22# with this program; if not, write to the Free Software Foundation, Inc., 22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 24
25from bb import msg, data, event, mkdirhier, utils
26import bb, os, sys 25import bb, os, sys
26from bb import msg, data, event
27import signal 27import signal
28import stat 28import stat
29import fcntl 29import fcntl
30 30
31class TaskFailure(Exception): 31class TaskFailure(Exception):
32 """Exception raised when a task in a runqueue fails""" 32 """Exception raised when a task in a runqueue fails"""
33 def __init__(self, x): 33 def __init__(self, x):
34 self.args = x 34 self.args = x
35 35
36 36
@@ -60,7 +60,7 @@ class RunQueueStats:
60 def taskActive(self): 60 def taskActive(self):
61 self.active = self.active + 1 61 self.active = self.active + 1
62 62
63# These values indicate the next step due to be run in the 63# These values indicate the next step due to be run in the
64# runQueue state machine 64# runQueue state machine
65runQueuePrepare = 2 65runQueuePrepare = 2
66runQueueRunInit = 3 66runQueueRunInit = 3
@@ -76,7 +76,7 @@ class RunQueueScheduler:
76 """ 76 """
77 def __init__(self, runqueue): 77 def __init__(self, runqueue):
78 """ 78 """
79 The default scheduler just returns the first buildable task (the 79 The default scheduler just returns the first buildable task (the
80 priority map is sorted by task numer) 80 priority map is sorted by task numer)
81 """ 81 """
82 self.rq = runqueue 82 self.rq = runqueue
@@ -109,8 +109,7 @@ class RunQueueSchedulerSpeed(RunQueueScheduler):
109 109
110 self.rq = runqueue 110 self.rq = runqueue
111 111
112 sortweight = deepcopy(self.rq.runq_weight) 112 sortweight = sorted(deepcopy(self.rq.runq_weight))
113 sortweight.sort()
114 copyweight = deepcopy(self.rq.runq_weight) 113 copyweight = deepcopy(self.rq.runq_weight)
115 self.prio_map = [] 114 self.prio_map = []
116 115
@@ -123,10 +122,10 @@ class RunQueueSchedulerSpeed(RunQueueScheduler):
123 122
124class RunQueueSchedulerCompletion(RunQueueSchedulerSpeed): 123class RunQueueSchedulerCompletion(RunQueueSchedulerSpeed):
125 """ 124 """
126 A scheduler optimised to complete .bb files are quickly as possible. The 125 A scheduler optimised to complete .bb files are quickly as possible. The
127 priority map is sorted by task weight, but then reordered so once a given 126 priority map is sorted by task weight, but then reordered so once a given
128 .bb file starts to build, its completed as quickly as possible. This works 127 .bb file starts to build, its completed as quickly as possible. This works
129 well where disk space is at a premium and classes like OE's rm_work are in 128 well where disk space is at a premium and classes like OE's rm_work are in
130 force. 129 force.
131 """ 130 """
132 def __init__(self, runqueue): 131 def __init__(self, runqueue):
@@ -135,7 +134,7 @@ class RunQueueSchedulerCompletion(RunQueueSchedulerSpeed):
135 134
136 #FIXME - whilst this groups all fnids together it does not reorder the 135 #FIXME - whilst this groups all fnids together it does not reorder the
137 #fnid groups optimally. 136 #fnid groups optimally.
138 137
139 basemap = deepcopy(self.prio_map) 138 basemap = deepcopy(self.prio_map)
140 self.prio_map = [] 139 self.prio_map = []
141 while (len(basemap) > 0): 140 while (len(basemap) > 0):
@@ -231,7 +230,7 @@ class RunQueue:
231 if chain1[index] != chain2[index]: 230 if chain1[index] != chain2[index]:
232 return False 231 return False
233 return True 232 return True
234 233
235 def chain_array_contains(chain, chain_array): 234 def chain_array_contains(chain, chain_array):
236 """ 235 """
237 Return True if chain_array contains chain 236 Return True if chain_array contains chain
@@ -286,7 +285,7 @@ class RunQueue:
286 285
287 def calculate_task_weights(self, endpoints): 286 def calculate_task_weights(self, endpoints):
288 """ 287 """
289 Calculate a number representing the "weight" of each task. Heavier weighted tasks 288 Calculate a number representing the "weight" of each task. Heavier weighted tasks
290 have more dependencies and hence should be executed sooner for maximum speed. 289 have more dependencies and hence should be executed sooner for maximum speed.
291 290
292 This function also sanity checks the task list finding tasks that its not 291 This function also sanity checks the task list finding tasks that its not
@@ -307,7 +306,7 @@ class RunQueue:
307 weight[listid] = 1 306 weight[listid] = 1
308 task_done[listid] = True 307 task_done[listid] = True
309 308
310 while 1: 309 while True:
311 next_points = [] 310 next_points = []
312 for listid in endpoints: 311 for listid in endpoints:
313 for revdep in self.runq_depends[listid]: 312 for revdep in self.runq_depends[listid]:
@@ -318,7 +317,7 @@ class RunQueue:
318 task_done[revdep] = True 317 task_done[revdep] = True
319 endpoints = next_points 318 endpoints = next_points
320 if len(next_points) == 0: 319 if len(next_points) == 0:
321 break 320 break
322 321
323 # Circular dependency sanity check 322 # Circular dependency sanity check
324 problem_tasks = [] 323 problem_tasks = []
@@ -345,7 +344,7 @@ class RunQueue:
345 344
346 def prepare_runqueue(self): 345 def prepare_runqueue(self):
347 """ 346 """
348 Turn a set of taskData into a RunQueue and compute data needed 347 Turn a set of taskData into a RunQueue and compute data needed
349 to optimise the execution order. 348 to optimise the execution order.
350 """ 349 """
351 350
@@ -365,12 +364,12 @@ class RunQueue:
365 # Step A - Work out a list of tasks to run 364 # Step A - Work out a list of tasks to run
366 # 365 #
367 # Taskdata gives us a list of possible providers for every build and run 366 # Taskdata gives us a list of possible providers for every build and run
368 # target ordered by priority. It also gives information on each of those 367 # target ordered by priority. It also gives information on each of those
369 # providers. 368 # providers.
370 # 369 #
371 # To create the actual list of tasks to execute we fix the list of 370 # To create the actual list of tasks to execute we fix the list of
372 # providers and then resolve the dependencies into task IDs. This 371 # providers and then resolve the dependencies into task IDs. This
373 # process is repeated for each type of dependency (tdepends, deptask, 372 # process is repeated for each type of dependency (tdepends, deptask,
374 # rdeptast, recrdeptask, idepends). 373 # rdeptast, recrdeptask, idepends).
375 374
376 def add_build_dependencies(depids, tasknames, depends): 375 def add_build_dependencies(depids, tasknames, depends):
@@ -411,12 +410,12 @@ class RunQueue:
411 410
412 if fnid not in taskData.failed_fnids: 411 if fnid not in taskData.failed_fnids:
413 412
414 # Resolve task internal dependencies 413 # Resolve task internal dependencies
415 # 414 #
416 # e.g. addtask before X after Y 415 # e.g. addtask before X after Y
417 depends = taskData.tasks_tdepends[task] 416 depends = taskData.tasks_tdepends[task]
418 417
419 # Resolve 'deptask' dependencies 418 # Resolve 'deptask' dependencies
420 # 419 #
421 # e.g. do_sometask[deptask] = "do_someothertask" 420 # e.g. do_sometask[deptask] = "do_someothertask"
422 # (makes sure sometask runs after someothertask of all DEPENDS) 421 # (makes sure sometask runs after someothertask of all DEPENDS)
@@ -424,7 +423,7 @@ class RunQueue:
424 tasknames = task_deps['deptask'][taskData.tasks_name[task]].split() 423 tasknames = task_deps['deptask'][taskData.tasks_name[task]].split()
425 add_build_dependencies(taskData.depids[fnid], tasknames, depends) 424 add_build_dependencies(taskData.depids[fnid], tasknames, depends)
426 425
427 # Resolve 'rdeptask' dependencies 426 # Resolve 'rdeptask' dependencies
428 # 427 #
429 # e.g. do_sometask[rdeptask] = "do_someothertask" 428 # e.g. do_sometask[rdeptask] = "do_someothertask"
430 # (makes sure sometask runs after someothertask of all RDEPENDS) 429 # (makes sure sometask runs after someothertask of all RDEPENDS)
@@ -432,7 +431,7 @@ class RunQueue:
432 taskname = task_deps['rdeptask'][taskData.tasks_name[task]] 431 taskname = task_deps['rdeptask'][taskData.tasks_name[task]]
433 add_runtime_dependencies(taskData.rdepids[fnid], [taskname], depends) 432 add_runtime_dependencies(taskData.rdepids[fnid], [taskname], depends)
434 433
435 # Resolve inter-task dependencies 434 # Resolve inter-task dependencies
436 # 435 #
437 # e.g. do_sometask[depends] = "targetname:do_someothertask" 436 # e.g. do_sometask[depends] = "targetname:do_someothertask"
438 # (makes sure sometask runs after targetname's someothertask) 437 # (makes sure sometask runs after targetname's someothertask)
@@ -467,8 +466,8 @@ class RunQueue:
467 newdep = [] 466 newdep = []
468 bb.msg.debug(2, bb.msg.domain.RunQueue, "Task %s (%s %s) contains self reference! %s" % (task, taskData.fn_index[taskData.tasks_fnid[task]], taskData.tasks_name[task], depends)) 467 bb.msg.debug(2, bb.msg.domain.RunQueue, "Task %s (%s %s) contains self reference! %s" % (task, taskData.fn_index[taskData.tasks_fnid[task]], taskData.tasks_name[task], depends))
469 for dep in depends: 468 for dep in depends:
470 if task != dep: 469 if task != dep:
471 newdep.append(dep) 470 newdep.append(dep)
472 depends = newdep 471 depends = newdep
473 472
474 self.runq_fnid.append(taskData.tasks_fnid[task]) 473 self.runq_fnid.append(taskData.tasks_fnid[task])
@@ -482,7 +481,7 @@ class RunQueue:
482 # 481 #
483 # Build a list of recursive cumulative dependencies for each fnid 482 # Build a list of recursive cumulative dependencies for each fnid
484 # We do this by fnid, since if A depends on some task in B 483 # We do this by fnid, since if A depends on some task in B
485 # we're interested in later tasks B's fnid might have but B itself 484 # we're interested in later tasks B's fnid might have but B itself
486 # doesn't depend on 485 # doesn't depend on
487 # 486 #
488 # Algorithm is O(tasks) + O(tasks)*O(fnids) 487 # Algorithm is O(tasks) + O(tasks)*O(fnids)
@@ -513,7 +512,7 @@ class RunQueue:
513 if len(runq_recrdepends[task]) > 0: 512 if len(runq_recrdepends[task]) > 0:
514 taskfnid = self.runq_fnid[task] 513 taskfnid = self.runq_fnid[task]
515 for dep in reccumdepends[taskfnid]: 514 for dep in reccumdepends[taskfnid]:
516 # Ignore self references 515 # Ignore self references
517 if dep == task: 516 if dep == task:
518 continue 517 continue
519 for taskname in runq_recrdepends[task]: 518 for taskname in runq_recrdepends[task]:
@@ -631,11 +630,11 @@ class RunQueue:
631 for dep in revdeps: 630 for dep in revdeps:
632 if dep in self.runq_depends[listid]: 631 if dep in self.runq_depends[listid]:
633 #self.dump_data(taskData) 632 #self.dump_data(taskData)
634 bb.msg.fatal(bb.msg.domain.RunQueue, "Task %s (%s) has circular dependency on %s (%s)" % (taskData.fn_index[self.runq_fnid[dep]], self.runq_task[dep] , taskData.fn_index[self.runq_fnid[listid]], self.runq_task[listid])) 633 bb.msg.fatal(bb.msg.domain.RunQueue, "Task %s (%s) has circular dependency on %s (%s)" % (taskData.fn_index[self.runq_fnid[dep]], self.runq_task[dep], taskData.fn_index[self.runq_fnid[listid]], self.runq_task[listid]))
635 634
636 bb.msg.note(2, bb.msg.domain.RunQueue, "Compute totals (have %s endpoint(s))" % len(endpoints)) 635 bb.msg.note(2, bb.msg.domain.RunQueue, "Compute totals (have %s endpoint(s))" % len(endpoints))
637 636
638 # Calculate task weights 637 # Calculate task weights
639 # Check of higher length circular dependencies 638 # Check of higher length circular dependencies
640 self.runq_weight = self.calculate_task_weights(endpoints) 639 self.runq_weight = self.calculate_task_weights(endpoints)
641 640
@@ -657,7 +656,7 @@ class RunQueue:
657 for prov in self.dataCache.fn_provides[fn]: 656 for prov in self.dataCache.fn_provides[fn]:
658 if prov not in prov_list: 657 if prov not in prov_list:
659 prov_list[prov] = [fn] 658 prov_list[prov] = [fn]
660 elif fn not in prov_list[prov]: 659 elif fn not in prov_list[prov]:
661 prov_list[prov].append(fn) 660 prov_list[prov].append(fn)
662 error = False 661 error = False
663 for prov in prov_list: 662 for prov in prov_list:
@@ -703,7 +702,7 @@ class RunQueue:
703 buildable.append(task) 702 buildable.append(task)
704 703
705 def check_buildable(self, task, buildable): 704 def check_buildable(self, task, buildable):
706 for revdep in self.runq_revdeps[task]: 705 for revdep in self.runq_revdeps[task]:
707 alldeps = 1 706 alldeps = 1
708 for dep in self.runq_depends[revdep]: 707 for dep in self.runq_depends[revdep]:
709 if dep in unchecked: 708 if dep in unchecked:
@@ -774,7 +773,7 @@ class RunQueue:
774 #print "Not current: %s" % notcurrent 773 #print "Not current: %s" % notcurrent
775 774
776 if len(unchecked) > 0: 775 if len(unchecked) > 0:
777 bb.fatal("check_stamps fatal internal error") 776 bb.msg.fatal(bb.msg.domain.RunQueue, "check_stamps fatal internal error")
778 return current 777 return current
779 778
780 def check_stamp_task(self, task): 779 def check_stamp_task(self, task):
@@ -811,10 +810,10 @@ class RunQueue:
811 try: 810 try:
812 t2 = os.stat(stampfile2)[stat.ST_MTIME] 811 t2 = os.stat(stampfile2)[stat.ST_MTIME]
813 if t1 < t2: 812 if t1 < t2:
814 bb.msg.debug(2, bb.msg.domain.RunQueue, "Stampfile %s < %s" % (stampfile,stampfile2)) 813 bb.msg.debug(2, bb.msg.domain.RunQueue, "Stampfile %s < %s" % (stampfile, stampfile2))
815 iscurrent = False 814 iscurrent = False
816 except: 815 except:
817 bb.msg.debug(2, bb.msg.domain.RunQueue, "Exception reading %s for %s" % (stampfile2 ,stampfile)) 816 bb.msg.debug(2, bb.msg.domain.RunQueue, "Exception reading %s for %s" % (stampfile2, stampfile))
818 iscurrent = False 817 iscurrent = False
819 818
820 return iscurrent 819 return iscurrent
@@ -852,7 +851,7 @@ class RunQueue:
852 return False 851 return False
853 852
854 if self.state is runQueueChildProcess: 853 if self.state is runQueueChildProcess:
855 print "Child process" 854 print("Child process")
856 return False 855 return False
857 856
858 # Loop 857 # Loop
@@ -885,7 +884,7 @@ class RunQueue:
885 def task_complete(self, task): 884 def task_complete(self, task):
886 """ 885 """
887 Mark a task as completed 886 Mark a task as completed
888 Look at the reverse dependencies and mark any task with 887 Look at the reverse dependencies and mark any task with
889 completed dependencies as buildable 888 completed dependencies as buildable
890 """ 889 """
891 self.runq_complete[task] = 1 890 self.runq_complete[task] = 1
@@ -929,7 +928,7 @@ class RunQueue:
929 while True: 928 while True:
930 task = None 929 task = None
931 if self.stats.active < self.number_tasks: 930 if self.stats.active < self.number_tasks:
932 task = self.sched.next() 931 task = next(self.sched)
933 if task is not None: 932 if task is not None:
934 fn = self.taskData.fn_index[self.runq_fnid[task]] 933 fn = self.taskData.fn_index[self.runq_fnid[task]]
935 934
@@ -948,7 +947,7 @@ class RunQueue:
948 try: 947 try:
949 pipein, pipeout = os.pipe() 948 pipein, pipeout = os.pipe()
950 pid = os.fork() 949 pid = os.fork()
951 except OSError, e: 950 except OSError as e:
952 bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) 951 bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror))
953 if pid == 0: 952 if pid == 0:
954 os.close(pipein) 953 os.close(pipein)
@@ -982,10 +981,11 @@ class RunQueue:
982 try: 981 try:
983 self.cooker.tryBuild(fn, taskname[3:]) 982 self.cooker.tryBuild(fn, taskname[3:])
984 except bb.build.EventException: 983 except bb.build.EventException:
985 bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
986 os._exit(1) 984 os._exit(1)
987 except: 985 except Exception:
988 bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") 986 from traceback import format_exc
987 bb.msg.error(bb.msg.domain.Build, "Build of %s %s failed" % (fn, taskname))
988 bb.msg.error(bb.msg.domain.Build, format_exc())
989 os._exit(1) 989 os._exit(1)
990 os._exit(0) 990 os._exit(0)
991 991
@@ -1031,12 +1031,13 @@ class RunQueue:
1031 return 1031 return
1032 1032
1033 def finish_runqueue_now(self): 1033 def finish_runqueue_now(self):
1034 bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGINT to remaining %s tasks" % self.stats.active) 1034 if self.stats.active:
1035 for k, v in self.build_pids.iteritems(): 1035 bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGINT to remaining %s tasks" % self.stats.active)
1036 try: 1036 for k, v in self.build_pids.iteritems():
1037 os.kill(-k, signal.SIGINT) 1037 try:
1038 except: 1038 os.kill(-k, signal.SIGINT)
1039 pass 1039 except:
1040 pass
1040 for pipe in self.build_pipes: 1041 for pipe in self.build_pipes:
1041 self.build_pipes[pipe].read() 1042 self.build_pipes[pipe].read()
1042 1043
@@ -1085,30 +1086,30 @@ class RunQueue:
1085 """ 1086 """
1086 bb.msg.debug(3, bb.msg.domain.RunQueue, "run_tasks:") 1087 bb.msg.debug(3, bb.msg.domain.RunQueue, "run_tasks:")
1087 for task in range(len(self.runq_task)): 1088 for task in range(len(self.runq_task)):
1088 bb.msg.debug(3, bb.msg.domain.RunQueue, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task, 1089 bb.msg.debug(3, bb.msg.domain.RunQueue, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task,
1089 taskQueue.fn_index[self.runq_fnid[task]], 1090 taskQueue.fn_index[self.runq_fnid[task]],
1090 self.runq_task[task], 1091 self.runq_task[task],
1091 self.runq_weight[task], 1092 self.runq_weight[task],
1092 self.runq_depends[task], 1093 self.runq_depends[task],
1093 self.runq_revdeps[task])) 1094 self.runq_revdeps[task]))
1094 1095
1095 bb.msg.debug(3, bb.msg.domain.RunQueue, "sorted_tasks:") 1096 bb.msg.debug(3, bb.msg.domain.RunQueue, "sorted_tasks:")
1096 for task1 in range(len(self.runq_task)): 1097 for task1 in range(len(self.runq_task)):
1097 if task1 in self.prio_map: 1098 if task1 in self.prio_map:
1098 task = self.prio_map[task1] 1099 task = self.prio_map[task1]
1099 bb.msg.debug(3, bb.msg.domain.RunQueue, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task, 1100 bb.msg.debug(3, bb.msg.domain.RunQueue, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task,
1100 taskQueue.fn_index[self.runq_fnid[task]], 1101 taskQueue.fn_index[self.runq_fnid[task]],
1101 self.runq_task[task], 1102 self.runq_task[task],
1102 self.runq_weight[task], 1103 self.runq_weight[task],
1103 self.runq_depends[task], 1104 self.runq_depends[task],
1104 self.runq_revdeps[task])) 1105 self.runq_revdeps[task]))
1105 1106
1106 1107
1107class TaskFailure(Exception): 1108class TaskFailure(Exception):
1108 """ 1109 """
1109 Exception raised when a task in a runqueue fails 1110 Exception raised when a task in a runqueue fails
1110 """ 1111 """
1111 def __init__(self, x): 1112 def __init__(self, x):
1112 self.args = x 1113 self.args = x
1113 1114
1114 1115
@@ -1194,6 +1195,5 @@ class runQueuePipe():
1194 while self.read(): 1195 while self.read():
1195 continue 1196 continue
1196 if len(self.queue) > 0: 1197 if len(self.queue) > 0:
1197 print "Warning, worker left partial message" 1198 print("Warning, worker left partial message")
1198 os.close(self.fd) 1199 os.close(self.fd)
1199