Browse code

fuck mmap_sem!

acab authored on 2009/09/10 10:20:02
Showing 1 changed files
... ...
@@ -37,6 +37,9 @@
37 37
 #endif
38 38
 #endif
39 39
 
40
+#include <pthread.h>
41
+
42
+
40 43
 #include "others.h"
41 44
 #include "cltypes.h"
42 45
 
... ...
@@ -54,9 +57,14 @@
54 54
 /* FIXME: tune this stuff */
55 55
 #define UNPAGE_THRSHLD_LO 4*1024*1024
56 56
 #define UNPAGE_THRSHLD_HI 8*1024*1024
57
-#define DUMB_SIZE 1*1024*1024
57
+#define READAHEAD_PAGES 8
58
+
59
+/* FIXME: remove the malloc fallback, it only makes thing slower */
60
+#define DUMB_SIZE 0
61
+
62
+/* DON'T ASK ME */
63
+pthread_mutex_t fmap_mutex = PTHREAD_MUTEX_INITIALIZER;
58 64
 
59
-#define READAHEAD_PAGES 4
60 65
 
61 66
 static unsigned int fmap_align_items(unsigned int sz, unsigned int al) {
62 67
     return sz / al + (sz % al != 0);
... ...
@@ -99,10 +107,15 @@ struct F_MAP *fmap(int fd, off_t offset, size_t len) {
99 99
     mapsz = pages * pgsz + hdrsz;
100 100
 #if HAVE_MMAP
101 101
     if(mapsz >= DUMB_SIZE) {
102
-	if ((m = (struct F_MAP *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|ANONYMOUS_MAP, -1, 0)) == MAP_FAILED)
102
+	pthread_mutex_lock(&fmap_mutex);
103
+	if ((m = (struct F_MAP *)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)
103 104
 	    m = NULL;
104
-	else
105
+	else {
105 106
 	    dumb = 0;
107
+	    madvise(m, mapsz, MADV_RANDOM|MADV_DONTFORK);
108
+	    madvise(m, hdrsz, MADV_WILLNEED);
109
+	}
110
+	pthread_mutex_unlock(&fmap_mutex);
106 111
     } else
107 112
 #endif
108 113
 	m = (struct F_MAP *)cli_malloc(mapsz);
... ...
@@ -120,7 +133,13 @@ struct F_MAP *fmap(int fd, off_t offset, size_t len) {
120 120
     m->pgsz = pgsz;
121 121
     m->paged = 0;
122 122
     memset(m->bitmap, 0, sizeof(uint32_t) * pages);
123
-//    cli_errmsg("FMAPDBG: created %p - len %u pages %u hdrsz %u\n", m, len, pages, hdrsz);
123
+#ifdef FMAPDEBUG
124
+    m->page_needs = 0;
125
+    m->page_reads = 0;
126
+    m->page_locks = 0;
127
+    m->page_unlocks = 0;
128
+    m->page_unmaps = 0;
129
+#endif
124 130
     return m;
125 131
 }
126 132
 
... ...
@@ -179,8 +198,13 @@ static void fmap_aging(struct F_MAP *m) {
179 179
 		m->bitmap[freeme[i]] = FM_MASK_SEEN;
180 180
 		m->paged--;
181 181
 		/* and we mmap the page over so the kernel knows there's nothing good in there */
182
+		pthread_mutex_lock(&fmap_mutex);
182 183
 		if(mmap(pptr, m->pgsz, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_PRIVATE|ANONYMOUS_MAP, -1, 0) == MAP_FAILED)
183 184
 		    cli_warnmsg("fmap_aging: kernel hates you\n");
185
+		pthread_mutex_unlock(&fmap_mutex);
186
+#ifdef FMAPDEBUG
187
+		m->page_unmaps++;
188
+#endif
184 189
 	    }
185 190
 	}
186 191
 	free(freeme);
... ...
@@ -192,9 +216,16 @@ static void fmap_aging(struct F_MAP *m) {
192 192
 static int fmap_readpage(struct F_MAP *m, unsigned int first_page, unsigned int count, unsigned int lock_count) {
193 193
     size_t readsz = 0, got;
194 194
     char *pptr = NULL;
195
-    uint32_t s;
195
+    volatile uint32_t s;
196 196
     unsigned int i, page = first_page, force_read = 0;
197 197
 
198
+    for(i=0; i<count; i++) { /* REAL MEN DON'T MADVISE: seriously, it sucks! */
199
+	volatile char faultme = ((char *)m)[(first_page+i) * m->pgsz + m->hdrsz];
200
+    }
201
+#ifdef FMAPDEBUG
202
+    m->page_needs += count;
203
+    m->page_locks += lock_count;
204
+#endif
198 205
     for(i=0; i<=count; i++, page++) {
199 206
 	int lock;
200 207
 	if(lock_count) {
... ...
@@ -254,6 +285,9 @@ static int fmap_readpage(struct F_MAP *m, unsigned int first_page, unsigned int
254 254
 		cli_warnmsg("pread fail: page %u pages %u map-offset %lu - asked for %lu bytes, got %lu\n", first_page, m->pages, (long unsigned int)m->offset, (long unsigned int)readsz, (long unsigned int)got);
255 255
 		return 1;
256 256
 	    }
257
+#ifdef FMAPDEBUG
258
+	    m->page_reads += count;
259
+#endif
257 260
 	    pptr = NULL;
258 261
 	    force_read = 0;
259 262
 	    readsz = 0;
... ...
@@ -285,12 +319,12 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
285 285
     char *ret;
286 286
 
287 287
     if(!len) {
288
-	cli_warnmsg("fmap: attempted void need\n");
288
+//	cli_warnmsg("fmap: attempted void need\n");
289 289
 	return NULL;
290 290
     }
291 291
 
292 292
     if(!CLI_ISCONTAINED(0, m->len, at, len)) {
293
-	cli_warnmsg("fmap: attempted oof need\n");
293
+      //	cli_warnmsg("fmap: attempted oof need\n");
294 294
 	return NULL;
295 295
     }
296 296
 
... ...
@@ -304,8 +338,6 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
304 304
     if(last_page >= m->pages) last_page = m->pages - 1;
305 305
 #endif
306 306
 
307
-//    cli_errmsg("FMAPDBG: +++ map %p - len %u lock: %d (page %u to %u)\n", m, len, lock, first_page, last_page);
308
-
309 307
     if(fmap_readpage(m, first_page, last_page-first_page+1, lock_count))
310 308
 	return NULL;
311 309
 
... ...
@@ -315,19 +347,15 @@ static void *fmap_need(struct F_MAP *m, size_t at, size_t len, int lock) {
315 315
 }
316 316
 
317 317
 void *fmap_need_off(struct F_MAP *m, size_t at, size_t len) {
318
-//    cli_errmsg("FMAPDBG: need_off map %p at %u len %u\n", m, at, len);
319 318
     return fmap_need(m, at, len, 1);
320 319
 }
321 320
 void *fmap_need_off_once(struct F_MAP *m, size_t at, size_t len) {
322
-//    cli_errmsg("FMAPDBG: need_off_once map %p at %u len %u\n", m, at, len);
323 321
     return fmap_need(m, at, len, 0);
324 322
 }
325 323
 void *fmap_need_ptr(struct F_MAP *m, void *ptr, size_t len) {
326
-//    cli_errmsg("FMAPDBG: need_ptr map %p at %p len %u\n", m, ptr, len);
327 324
     return fmap_need_off(m, (char *)ptr - (char *)m - m->hdrsz, len);
328 325
 }
329 326
 void *fmap_need_ptr_once(struct F_MAP *m, void *ptr, size_t len) {
330
-//    cli_errmsg("FMAPDBG: need_ptr_once map %p at %p len %u\n", m, ptr, len);
331 327
     return fmap_need_off_once(m, (char *)ptr - (char *)m - m->hdrsz, len);
332 328
 }
333 329
 
... ...
@@ -339,11 +367,12 @@ void *fmap_need_str(struct F_MAP *m, void *ptr, size_t len_hint) {
339 339
 static void fmap_unneed_page(struct F_MAP *m, unsigned int page) {
340 340
     uint32_t s = m->bitmap[page];
341 341
 
342
-//    cli_errmsg("FMAPDBG: --- map %p - page %u status %u count %u\n", m, page, s>>30, s & FM_MASK_COUNT);
343
-
344 342
     if((s & (FM_MASK_PAGED | FM_MASK_LOCKED)) == (FM_MASK_PAGED | FM_MASK_LOCKED)) {
345 343
 	/* page is paged and locked: check lock count */
346 344
 	s &= FM_MASK_COUNT;
345
+#ifdef FMAPDEBUG
346
+	m->page_unlocks ++;
347
+#endif
347 348
 	if(s > 1) /* locked more than once: dec lock count */
348 349
 	    m->bitmap[page]--;
349 350
 	else if (s == 1) /* only one lock left: unlock and begin aging */
... ...
@@ -399,10 +428,16 @@ int fmap_readn(struct F_MAP *m, void *dst, size_t at, size_t len) {
399 399
 }
400 400
 
401 401
 void fmunmap(struct F_MAP *m) {
402
+#ifdef FMAPDEBUG
403
+  cli_errmsg("FMAPDEBUG: Needs:%u reads:%u locks:%u unlocks:%u unmaps:%u\n", m->page_needs, m->page_reads, m->page_locks, m->page_unlocks, m->page_unmaps);
404
+#endif
405
+
402 406
 #if HAVE_MMAP
403 407
     if(!m->dumb) {
404 408
 	size_t len = m->pages * m->pgsz + m->hdrsz;
409
+	pthread_mutex_lock(&fmap_mutex);
405 410
 	munmap((void *)m, len);
411
+	pthread_mutex_unlock(&fmap_mutex);
406 412
     } else
407 413
 #endif
408 414
 	free((void *)m);
... ...
@@ -416,7 +451,7 @@ void *fmap_need_offstr(struct F_MAP *m, size_t at, size_t len_hint) {
416 416
 	len_hint = m->len - at;
417 417
 
418 418
     if(!CLI_ISCONTAINED(0, m->len, at, len_hint)) {
419
-	cli_warnmsg("fmap: attempted oof need_str\n");
419
+      //	cli_warnmsg("fmap: attempted oof need_str\n");
420 420
 	return NULL;
421 421
     }
422 422
 
... ...
@@ -435,11 +470,12 @@ void *fmap_need_offstr(struct F_MAP *m, size_t at, size_t len_hint) {
435 435
 	}
436 436
 	if(i == first_page) {
437 437
 	    scanat = at % m->pgsz;
438
-	    scansz = m->pgsz - scanat;
438
+	    scansz = MIN(len_hint, m->pgsz - scanat);
439 439
 	} else {
440 440
 	    scanat = 0;
441
-	    scansz = m->pgsz;
441
+	    scansz = MIN(len_hint, m->pgsz);
442 442
 	}
443
+	len_hint -= scansz;
443 444
 	if(memchr(&thispage[scanat], 0, scansz))
444 445
 	    return ptr;
445 446
     }
... ...
@@ -447,3 +483,52 @@ void *fmap_need_offstr(struct F_MAP *m, size_t at, size_t len_hint) {
447 447
 	fmap_unneed_page(m, i);
448 448
     return NULL;
449 449
 }
450
+
451
+
452
+void *fmap_gets(struct F_MAP *m, char *dst, size_t *at, size_t max_len) {
453
+    unsigned int i, first_page, last_page;
454
+    char *src = (void *)((char *)m + m->hdrsz + *at), *endptr = NULL;
455
+    size_t len = MIN(max_len-1, m->len - *at), fullen = len;
456
+
457
+    if(!len || !CLI_ISCONTAINED(0, m->len, *at, len)) {
458
+        //cli_warnmsg("fmap: attempted oof need_str\n");
459
+	return NULL;
460
+    }
461
+
462
+    fmap_aging(m);
463
+
464
+    first_page = fmap_which_page(m, *at);
465
+    last_page = fmap_which_page(m, *at + len - 1);
466
+
467
+    for(i=first_page; i<=last_page; i++) {
468
+	char *thispage = (char *)m + m->hdrsz + i * m->pgsz;
469
+	unsigned int scanat, scansz;
470
+
471
+	if(fmap_readpage(m, i, 1, 0))
472
+	    return NULL;
473
+
474
+	if(i == first_page) {
475
+	    scanat = *at % m->pgsz;
476
+	    scansz = MIN(len, m->pgsz - scanat);
477
+	} else {
478
+	    scanat = 0;
479
+	    scansz = MIN(len, m->pgsz);
480
+	}
481
+	len -= scansz;
482
+
483
+	if((endptr = memchr(&thispage[scanat], '\n', scansz))) {
484
+	    endptr++;
485
+	    break;
486
+	}
487
+    }
488
+    if(endptr) {
489
+	memcpy(dst, src, endptr - src);
490
+	dst[endptr - src] = '\0';
491
+	*at += endptr - src;
492
+    } else {
493
+	memcpy(dst, src, fullen);
494
+	dst[fullen] = '\0';
495
+	*at += fullen;
496
+    }
497
+    return dst;
498
+}