tools/deadlock: support specifies maxnum of threads and edge cases (#3455)

support to specify maxinum of threads and edge cases. The default values make map taking more than 0.5G memory which cause out-of-memory issue on some systems.
also fix an issue with python `open` so the open file is automatically closed upon file reading is done.
diff --git a/tools/deadlock.py b/tools/deadlock.py
index 81122ad..d6046c2 100755
--- a/tools/deadlock.py
+++ b/tools/deadlock.py
@@ -457,6 +457,16 @@
         help='Comma-separated list of unlock symbols to trace. Default is '
         'pthread_mutex_unlock. These symbols cannot be inlined in the binary.',
     )
+    parser.add_argument(
+        '-t', '--threads', type=int, default=65536,
+        help='Specifies the maximum number of threads to trace. default 65536. '
+             'Note. 40 bytes per thread.'
+    )
+    parser.add_argument(
+        '-e', '--edges', type=int, default=65536,
+        help='Specifies the maximum number of edge cases that can be recorded. '
+             'default 65536. Note. 88 bytes per edge case.'
+    )
     args = parser.parse_args()
     if not args.binary:
         try:
@@ -465,7 +475,11 @@
             print('%s. Is the process (pid=%d) running?' % (str(e), args.pid))
             sys.exit(1)
 
-    bpf = BPF(src_file=b'deadlock.c')
+    with open('deadlock.c') as f:
+        text = f.read()
+    text = text.replace(b'MAX_THREADS', str(args.threads));
+    text = text.replace(b'MAX_EDGES', str(args.edges));
+    bpf = BPF(text=text)
 
     # Trace where threads are created
     bpf.attach_kretprobe(event=bpf.get_syscall_fnname('clone'), fn_name='trace_clone')