... | ... |
@@ -24,9 +24,6 @@ |
24 | 24 |
#include "clamav-config.h" |
25 | 25 |
#endif |
26 | 26 |
|
27 |
-#define _XOPEN_SOURCE 500 |
|
28 |
-#define _BSD_SOURCE |
|
29 |
- |
|
30 | 27 |
#include <sys/types.h> |
31 | 28 |
#include <sys/stat.h> |
32 | 29 |
#include <string.h> |
... | ... |
@@ -37,8 +34,9 @@ |
37 | 37 |
#endif |
38 | 38 |
#endif |
39 | 39 |
|
40 |
+#ifdef C_LINUX |
|
40 | 41 |
#include <pthread.h> |
41 |
- |
|
42 |
+#endif |
|
42 | 43 |
|
43 | 44 |
#include "others.h" |
44 | 45 |
#include "cltypes.h" |
... | ... |
@@ -59,9 +57,25 @@ |
59 | 59 |
#define UNPAGE_THRSHLD_HI 8*1024*1024 |
60 | 60 |
#define READAHEAD_PAGES 8 |
61 | 61 |
|
62 |
-/* DON'T ASK ME */ |
|
62 |
+#ifdef C_LINUX |
|
63 |
+/* |
|
64 |
+ WORKAROUND |
|
65 |
+ Relieve some stress on mmap_sem. |
|
66 |
+ When mmap_sem is heavily hammered, the scheduler |
|
67 |
+ tends to fail to wake us up properly. |
|
68 |
+*/ |
|
63 | 69 |
pthread_mutex_t fmap_mutex = PTHREAD_MUTEX_INITIALIZER; |
70 |
+#define fmap_lock pthread_mutex_lock(&fmap_mutex) |
|
71 |
+#define fmap_unlock pthread_mutex_unlock(&fmap_mutex); |
|
72 |
+#else |
|
73 |
+#define fmap_lock |
|
74 |
+#define fmap_unlock |
|
75 |
+#endif |
|
76 |
+ |
|
64 | 77 |
|
78 |
+/* pread proto here in order to avoid the use of XOPEN and BSD_SOURCE |
|
79 |
+ which may in turn prevent some mmap constants to be defined */ |
|
80 |
+ssize_t pread(int fd, void *buf, size_t count, off_t offset); |
|
65 | 81 |
|
66 | 82 |
static unsigned int fmap_align_items(unsigned int sz, unsigned int al) { |
67 | 83 |
return sz / al + (sz % al != 0); |
... | ... |
@@ -102,7 +116,7 @@ fmap_t *fmap(int fd, off_t offset, size_t len) { |
102 | 102 |
pages = fmap_align_items(len, pgsz); |
103 | 103 |
hdrsz = fmap_align_to(sizeof(fmap_t) + pages * sizeof(uint32_t), pgsz); |
104 | 104 |
mapsz = pages * pgsz + hdrsz; |
105 |
- pthread_mutex_lock(&fmap_mutex); |
|
105 |
+ fmap_lock; |
|
106 | 106 |
#if HAVE_MMAP |
107 | 107 |
if ((m = (fmap_t *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) { |
108 | 108 |
m = NULL; |
... | ... |
@@ -115,12 +129,12 @@ fmap_t *fmap(int fd, off_t offset, size_t len) { |
115 | 115 |
#endif |
116 | 116 |
if(!m) { |
117 | 117 |
cli_warnmsg("fmap: map allocation failed\n"); |
118 |
- pthread_mutex_unlock(&fmap_mutex); |
|
118 |
+ fmap_unlock; |
|
119 | 119 |
return NULL; |
120 | 120 |
} |
121 | 121 |
/* fault the header while we still have the lock - we DO context switch here a lot here :@ */ |
122 | 122 |
memset(m->bitmap, 0, sizeof(uint32_t) * pages); |
123 |
- pthread_mutex_unlock(&fmap_mutex); |
|
123 |
+ fmap_unlock; |
|
124 | 124 |
m->fd = fd; |
125 | 125 |
m->dumb = dumb; |
126 | 126 |
m->mtime = st.st_mtime; |
... | ... |
@@ -177,10 +191,10 @@ static void fmap_aging(fmap_t *m) { |
177 | 177 |
/* we mark the page as seen */ |
178 | 178 |
m->bitmap[freeme[i]] = FM_MASK_SEEN; |
179 | 179 |
/* and we mmap the page over so the kernel knows there's nothing good in there */ |
180 |
- pthread_mutex_lock(&fmap_mutex); |
|
180 |
+ fmap_lock; |
|
181 | 181 |
if(mmap(pptr, m->pgsz, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_PRIVATE|ANONYMOUS_MAP, -1, 0) == MAP_FAILED) |
182 | 182 |
cli_warnmsg("fmap_aging: kernel hates you\n"); |
183 |
- pthread_mutex_unlock(&fmap_mutex); |
|
183 |
+ fmap_unlock; |
|
184 | 184 |
} |
185 | 185 |
m->paged -= avail; |
186 | 186 |
#ifdef FMAPDEBUG |
... | ... |
@@ -198,13 +212,14 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count, |
198 | 198 |
uint32_t s; |
199 | 199 |
unsigned int i, page = first_page, force_read = 0; |
200 | 200 |
|
201 |
- pthread_mutex_lock(&fmap_mutex); |
|
201 |
+ fmap_lock; |
|
202 | 202 |
for(i=0; i<count; i++) { /* prefault */ |
203 | 203 |
/* Not worth checking if the page is already paged, just ping each */ |
204 | 204 |
/* Also not worth reusing the loop below */ |
205 |
- volatile char faultme = ((char *)m)[(first_page+i) * m->pgsz + m->hdrsz]; |
|
205 |
+ volatile char faultme; |
|
206 |
+ faultme = ((char *)m)[(first_page+i) * m->pgsz + m->hdrsz]; |
|
206 | 207 |
} |
207 |
- pthread_mutex_unlock(&fmap_mutex); |
|
208 |
+ fmap_unlock; |
|
208 | 209 |
#ifdef FMAPDEBUG |
209 | 210 |
m->page_needs += count; |
210 | 211 |
m->page_locks += lock_count; |
... | ... |
@@ -301,13 +316,11 @@ static void *fmap_need(fmap_t *m, size_t at, size_t len, int lock) { |
301 | 301 |
unsigned int first_page, last_page, lock_count; |
302 | 302 |
char *ret; |
303 | 303 |
|
304 |
- if(!len) { |
|
305 |
-// cli_warnmsg("fmap: attempted void need\n"); |
|
304 |
+ if(!len) |
|
306 | 305 |
return NULL; |
307 |
- } |
|
308 | 306 |
|
309 | 307 |
if(!CLI_ISCONTAINED(0, m->len, at, len)) { |
310 |
- // cli_warnmsg("fmap: attempted oof need\n"); |
|
308 |
+ cli_warnmsg("fmap: attempted oof need\n"); |
|
311 | 309 |
return NULL; |
312 | 310 |
} |
313 | 311 |
|
... | ... |
@@ -381,8 +394,6 @@ void fmap_unneed_off(fmap_t *m, size_t at, size_t len) { |
381 | 381 |
return; |
382 | 382 |
} |
383 | 383 |
|
384 |
-// cli_errmsg("FMAPDBG: unneed_off map %p at %u len %u\n", m, at, len); |
|
385 |
- |
|
386 | 384 |
first_page = fmap_which_page(m, at); |
387 | 385 |
last_page = fmap_which_page(m, at + len - 1); |
388 | 386 |
|
... | ... |
@@ -392,7 +403,6 @@ void fmap_unneed_off(fmap_t *m, size_t at, size_t len) { |
392 | 392 |
} |
393 | 393 |
|
394 | 394 |
void fmap_unneed_ptr(fmap_t *m, void *ptr, size_t len) { |
395 |
-// cli_errmsg("FMAPDBG: unneed_ptr map %p at %p len %u\n", m, ptr, len); |
|
396 | 395 |
fmap_unneed_off(m, (char *)ptr - (char *)m - m->hdrsz, len); |
397 | 396 |
} |
398 | 397 |
|
... | ... |
@@ -418,9 +428,9 @@ void funmap(fmap_t *m) { |
418 | 418 |
#if HAVE_MMAP |
419 | 419 |
if(!m->dumb) { |
420 | 420 |
size_t len = m->pages * m->pgsz + m->hdrsz; |
421 |
- pthread_mutex_lock(&fmap_mutex); |
|
421 |
+ fmap_lock; |
|
422 | 422 |
munmap((void *)m, len); |
423 |
- pthread_mutex_unlock(&fmap_mutex); |
|
423 |
+ fmap_unlock; |
|
424 | 424 |
} else |
425 | 425 |
#endif |
426 | 426 |
free((void *)m); |
... | ... |
@@ -434,7 +444,7 @@ void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint) { |
434 | 434 |
len_hint = m->len - at; |
435 | 435 |
|
436 | 436 |
if(!CLI_ISCONTAINED(0, m->len, at, len_hint)) { |
437 |
- // cli_warnmsg("fmap: attempted oof need_str\n"); |
|
437 |
+ cli_warnmsg("fmap: attempted oof need_str\n"); |
|
438 | 438 |
return NULL; |
439 | 439 |
} |
440 | 440 |
|
... | ... |
@@ -474,7 +484,7 @@ void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) { |
474 | 474 |
size_t len = MIN(max_len-1, m->len - *at), fullen = len; |
475 | 475 |
|
476 | 476 |
if(!len || !CLI_ISCONTAINED(0, m->len, *at, len)) { |
477 |
- //cli_warnmsg("fmap: attempted oof need_str\n"); |
|
477 |
+ cli_warnmsg("fmap: attempted oof need_str\n"); |
|
478 | 478 |
return NULL; |
479 | 479 |
} |
480 | 480 |
|