1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
Avoid creating too many threads by limiting them to 250.
Work around a problem in ext2 where this would case a deadlock since we would
sometimes not create the thread needed for reading the superblock...
--- libports/manage-multithread.c.orig 2005-08-10 13:38:18.000000000 +0200
+++ libports/manage-multithread.c 2005-08-10 13:34:30.000000000 +0200
@@ -23,6 +23,19 @@
#include <assert.h>
#include <cthreads.h>
#include <mach/message.h>
+#include <unistd.h> /* For sleep() */
+
+#define LP_DEBUG 0
+
+#if LP_DEBUG
+#include <stdio.h> /* For printf() */
+#endif
+
+#define THREAD_MAX 250 /* Maximum number of threads */
+#define THREAD_DELAY 64 /* Number of threads created as needed
+ without delay */
+#define DELAY 2 /* Time to sleep() each delayed thread
+ (in seconds) */
void
ports_manage_port_operations_multithread (struct port_bucket *bucket,
@@ -43,6 +56,7 @@
{
int spawn = 0;
int status;
+ int type = 0; /* 0 = standard, 1 = master, 2 = delayed */
struct port_info *pi;
struct rpc_info link;
register mig_reply_header_t *outp = (mig_reply_header_t *) outheadp;
@@ -59,8 +73,11 @@
spin_lock (&lock);
assert (nreqthreads);
nreqthreads--;
- if (nreqthreads == 0)
- spawn = 1;
+ if (nreqthreads == 0 && totalthreads <= THREAD_MAX) {
+ spawn = 1;
+ if (totalthreads >= THREAD_DELAY)
+ type = 2;
+ }
spin_unlock (&lock);
if (spawn)
@@ -69,7 +86,8 @@
totalthreads++;
nreqthreads++;
spin_unlock (&lock);
- cthread_detach (cthread_fork ((cthread_fn_t) thread_function, 0));
+ cthread_detach (cthread_fork ((cthread_fn_t) thread_function,
+ (any_t)(intptr_t) type));
}
/* Fill in default response. */
@@ -117,15 +135,31 @@
}
int
- thread_function (int master)
+ thread_function (int type)
{
int timeout;
error_t err;
-
+
+ if (type == 2) {
+#if LP_DEBUG
+ printf("libports: delayed thread number: %d || ", totalthreads);
+ fflush(stdout);
+#endif
+ sleep(DELAY); /* Take a little break */
+#if LP_DEBUG
+ printf("libports: delayed thread running (%d)\n", totalthreads);
+ fflush(stdout);
+#endif
+ }
+#if LP_DEBUG
+ else {
+ printf("libports: new thread without delay running\n");
+ }
+#endif
if (hook)
(*hook) ();
- if (master)
+ if (type == 1)
timeout = global_timeout;
else
timeout = thread_timeout;
@@ -138,7 +172,7 @@
timeout);
while (err != MACH_RCV_TIMED_OUT);
- if (master)
+ if (type == 1)
{
spin_lock (&lock);
if (totalthreads != 1)
--- ext2fs/hyper.c 2008-03-10 01:14:16.643969000 +0000
+++ ext2fs/hyper.c 2008-03-01 23:41:53.227511000 +0000
@@ -55,17 +55,22 @@
static int ext2fs_clean; /* fs clean before we started writing? */
+struct ext2_super_block *__sblock = NULL;
void
get_hypermetadata (void)
{
error_t err;
size_t read;
+ static struct ext2_super_block _sblock;
assert (! sblock);
err = store_read (store, SBLOCK_OFFS >> store->log2_block_size,
- SBLOCK_SIZE, (void **)&sblock, &read);
+ SBLOCK_SIZE, (void **)&__sblock, &read);
if (err || read != SBLOCK_SIZE)
ext2_panic ("Cannot read hypermetadata");
+
+ sblock = &_sblock;
+ *sblock = *__sblock;
if (sblock->s_magic != EXT2_SUPER_MAGIC
#ifdef EXT2FS_PRE_02B_COMPAT
@@ -159,18 +164,18 @@
if (zeroblock == 0)
zeroblock = (vm_address_t) mmap (0, block_size, PROT_READ, MAP_ANON, 0, 0);
- munmap (sblock, SBLOCK_SIZE);
- sblock = NULL;
+ munmap (__sblock, SBLOCK_SIZE);
+ __sblock = NULL;
}
void
map_hypermetadata (void)
{
- sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS);
+ __sblock = (struct ext2_super_block *) boffs_ptr (SBLOCK_OFFS);
/* Cache a convenient pointer to the block group descriptors for allocation.
These are stored in the filesystem blocks following the superblock. */
- group_desc_image = (struct ext2_group_desc *) bptr (bptr_block (sblock) + 1);
+ group_desc_image = (struct ext2_group_desc *) bptr (bptr_block (__sblock) + 1);
}
error_t
@@ -193,8 +198,9 @@
if (sblock_dirty)
{
sblock_dirty = 0;
- disk_cache_block_ref_ptr (sblock);
- record_global_poke (sblock);
+ *__sblock = *sblock;
+ disk_cache_block_ref_ptr (__sblock);
+ record_global_poke (__sblock);
}
sync_global (wait);
|