ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/BDB/BDB.xs
(Generate patch)

Comparing BDB/BDB.xs (file contents):
Revision 1.10 by root, Mon Mar 5 19:47:01 2007 UTC vs.
Revision 1.11 by root, Wed May 9 06:42:24 2007 UTC

1/* solaris */ 1#include "xthread.h"
2#define _POSIX_PTHREAD_SEMANTICS 1
3
4#if __linux && !defined(_GNU_SOURCE)
5# define _GNU_SOURCE
6#endif
7
8/* just in case */
9#define _REENTRANT 1
10 2
11#include <errno.h> 3#include <errno.h>
12 4
13#include "EXTERN.h" 5#include "EXTERN.h"
14#include "perl.h" 6#include "perl.h"
15#include "XSUB.h" 7#include "XSUB.h"
16
17#include <pthread.h>
18 8
19#include <stddef.h> 9#include <stddef.h>
20#include <stdlib.h> 10#include <stdlib.h>
21#include <errno.h> 11#include <errno.h>
22#include <sys/time.h> 12#include <sys/time.h>
31# error you need Berkeley DB 4.5 or newer installed 21# error you need Berkeley DB 4.5 or newer installed
32#endif 22#endif
33 23
34/* number of seconds after which idle threads exit */ 24/* number of seconds after which idle threads exit */
35#define IDLE_TIMEOUT 10 25#define IDLE_TIMEOUT 10
36
37/* wether word reads are potentially non-atomic.
38 * this is conservatice, likely most arches this runs
39 * on have atomic word read/writes.
40 */
41#ifndef WORDACCESS_UNSAFE
42# if __i386 || __x86_64
43# define WORDACCESS_UNSAFE 0
44# else
45# define WORDACCESS_UNSAFE 1
46# endif
47#endif
48 26
49typedef DB_ENV DB_ENV_ornull; 27typedef DB_ENV DB_ENV_ornull;
50typedef DB_TXN DB_TXN_ornull; 28typedef DB_TXN DB_TXN_ornull;
51typedef DBC DBC_ornull; 29typedef DBC DBC_ornull;
52typedef DB DB_ornull; 30typedef DB DB_ornull;
147 125
148static int next_pri = DEFAULT_PRI + PRI_BIAS; 126static int next_pri = DEFAULT_PRI + PRI_BIAS;
149 127
150static unsigned int started, idle, wanted; 128static unsigned int started, idle, wanted;
151 129
152#if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
153# define AIO_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
154#else
155# define AIO_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
156#endif
157
158#define LOCK(mutex) pthread_mutex_lock (&(mutex))
159#define UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
160
161/* worker threads management */ 130/* worker threads management */
162static pthread_mutex_t wrklock = AIO_MUTEX_INIT; 131static mutex_t wrklock = MUTEX_INIT;
163 132
164typedef struct worker { 133typedef struct worker {
165 /* locked by wrklock */ 134 /* locked by wrklock */
166 struct worker *prev, *next; 135 struct worker *prev, *next;
167 136
168 pthread_t tid; 137 thread_t tid;
169 138
170 /* locked by reslock, reqlock or wrklock */ 139 /* locked by reslock, reqlock or wrklock */
171 aio_req req; /* currently processed request */ 140 aio_req req; /* currently processed request */
172 void *dbuf; 141 void *dbuf;
173 DIR *dirp; 142 DIR *dirp;
190static volatile unsigned int nreqs, nready, npending; 159static volatile unsigned int nreqs, nready, npending;
191static volatile unsigned int max_idle = 4; 160static volatile unsigned int max_idle = 4;
192static volatile unsigned int max_outstanding = 0xffffffff; 161static volatile unsigned int max_outstanding = 0xffffffff;
193static int respipe [2]; 162static int respipe [2];
194 163
195static pthread_mutex_t reslock = AIO_MUTEX_INIT; 164static mutex_t reslock = MUTEX_INIT;
196static pthread_mutex_t reqlock = AIO_MUTEX_INIT; 165static mutex_t reqlock = MUTEX_INIT;
197static pthread_cond_t reqwait = PTHREAD_COND_INITIALIZER; 166static cond_t reqwait = COND_INIT;
198 167
199#if WORDACCESS_UNSAFE 168#if WORDACCESS_UNSAFE
200 169
201static unsigned int get_nready () 170static unsigned int get_nready ()
202{ 171{
373 342
374static void *aio_proc (void *arg); 343static void *aio_proc (void *arg);
375 344
376static void start_thread (void) 345static void start_thread (void)
377{ 346{
378 sigset_t fullsigset, oldsigset;
379 pthread_attr_t attr;
380
381 worker *wrk = calloc (1, sizeof (worker)); 347 worker *wrk = calloc (1, sizeof (worker));
382 348
383 if (!wrk) 349 if (!wrk)
384 croak ("unable to allocate worker thread data"); 350 croak ("unable to allocate worker thread data");
385 351
386 pthread_attr_init (&attr);
387 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
388#ifdef PTHREAD_SCOPE_PROCESS
389 pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
390#endif
391
392 sigfillset (&fullsigset);
393
394 LOCK (wrklock); 352 LOCK (wrklock);
395 pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
396
397 if (pthread_create (&wrk->tid, &attr, aio_proc, (void *)wrk) == 0) 353 if (thread_create (&wrk->tid, aio_proc, (void *)wrk))
398 { 354 {
399 wrk->prev = &wrk_first; 355 wrk->prev = &wrk_first;
400 wrk->next = wrk_first.next; 356 wrk->next = wrk_first.next;
401 wrk_first.next->prev = wrk; 357 wrk_first.next->prev = wrk;
402 wrk_first.next = wrk; 358 wrk_first.next = wrk;
403 ++started; 359 ++started;
404 } 360 }
405 else 361 else
406 free (wrk); 362 free (wrk);
407 363
408 pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
409 UNLOCK (wrklock); 364 UNLOCK (wrklock);
410} 365}
411 366
412static void maybe_start_thread () 367static void maybe_start_thread ()
413{ 368{
445 ++nreqs; 400 ++nreqs;
446 401
447 LOCK (reqlock); 402 LOCK (reqlock);
448 ++nready; 403 ++nready;
449 reqq_push (&req_queue, req); 404 reqq_push (&req_queue, req);
450 pthread_cond_signal (&reqwait); 405 COND_SIGNAL (reqwait);
451 UNLOCK (reqlock); 406 UNLOCK (reqlock);
452 407
453 maybe_start_thread (); 408 maybe_start_thread ();
454 409
455 if (wait_callback) 410 if (wait_callback)
471 req->type = REQ_QUIT; 426 req->type = REQ_QUIT;
472 req->pri = PRI_MAX + PRI_BIAS; 427 req->pri = PRI_MAX + PRI_BIAS;
473 428
474 LOCK (reqlock); 429 LOCK (reqlock);
475 reqq_push (&req_queue, req); 430 reqq_push (&req_queue, req);
476 pthread_cond_signal (&reqwait); 431 COND_SIGNAL (reqwait);
477 UNLOCK (reqlock); 432 UNLOCK (reqlock);
478 433
479 LOCK (wrklock); 434 LOCK (wrklock);
480 --started; 435 --started;
481 UNLOCK (wrklock); 436 UNLOCK (wrklock);
637 if (req) 592 if (req)
638 break; 593 break;
639 594
640 ++idle; 595 ++idle;
641 596
642 if (pthread_cond_timedwait (&reqwait, &reqlock, &ts) 597 if (COND_TIMEDWAIT (reqwait, reqlock, ts)
643 == ETIMEDOUT) 598 == ETIMEDOUT)
644 { 599 {
645 if (idle > max_idle) 600 if (idle > max_idle)
646 { 601 {
647 --idle; 602 --idle;
651 UNLOCK (wrklock); 606 UNLOCK (wrklock);
652 goto quit; 607 goto quit;
653 } 608 }
654 609
655 /* we are allowed to idle, so do so without any timeout */ 610 /* we are allowed to idle, so do so without any timeout */
656 pthread_cond_wait (&reqwait, &reqlock); 611 COND_WAIT (reqwait, reqlock);
657 ts.tv_sec = time (0) + IDLE_TIMEOUT; 612 ts.tv_sec = time (0) + IDLE_TIMEOUT;
658 } 613 }
659 614
660 --idle; 615 --idle;
661 } 616 }
1045 1000
1046 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 1001 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1047 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 1002 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1048 1003
1049 create_pipe (); 1004 create_pipe ();
1050 pthread_atfork (atfork_prepare, atfork_parent, atfork_child); 1005 ATFORK (atfork_prepare, atfork_parent, atfork_child);
1051} 1006}
1052 1007
1053void 1008void
1054max_poll_reqs (int nreqs) 1009max_poll_reqs (int nreqs)
1055 PROTOTYPE: $ 1010 PROTOTYPE: $

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines