… | |
… | |
23 | static sigset_t cursigset, fullsigset; |
23 | static sigset_t cursigset, fullsigset; |
24 | |
24 | |
25 | struct tctx |
25 | struct tctx |
26 | { |
26 | { |
27 | void *coro; |
27 | void *coro; |
|
|
28 | xcond_t wait_c; |
|
|
29 | int wait_f; |
28 | }; |
30 | }; |
29 | |
31 | |
30 | static struct tctx *tctx_free; |
32 | static struct tctx *tctx_free; |
31 | |
33 | |
32 | static int available; |
34 | static int available; |
33 | static int max_idle = 8; |
35 | static int max_idle = 8; |
34 | |
36 | |
35 | static xmutex_t perl_m = X_MUTEX_INIT; static xcond_t perl_c = X_COND_INIT; static struct tctx *perl_f; |
37 | static xmutex_t perl_m = X_MUTEX_INIT; |
36 | static xmutex_t wait_m = X_MUTEX_INIT; static xcond_t wait_c = X_COND_INIT; static int wait_f; |
38 | static xcond_t perl_c = X_COND_INIT; |
|
|
39 | static struct tctx *perl_f; |
|
|
40 | |
|
|
41 | static xmutex_t wait_m = X_MUTEX_INIT; |
37 | |
42 | |
38 | static int wakeup_f; |
43 | static int wakeup_f; |
39 | static struct tctx **waiters; |
44 | static struct tctx **waiters; |
40 | static int waiters_count, waiters_max; |
45 | static int waiters_count, waiters_max; |
41 | |
46 | |
… | |
… | |
43 | tctx_get (void) |
48 | tctx_get (void) |
44 | { |
49 | { |
45 | struct tctx *ctx; |
50 | struct tctx *ctx; |
46 | |
51 | |
47 | if (!tctx_free) |
52 | if (!tctx_free) |
|
|
53 | { |
48 | ctx = malloc (sizeof (*tctx_free)); |
54 | ctx = malloc (sizeof (*tctx_free)); |
|
|
55 | X_COND_CREATE (ctx->wait_c); |
|
|
56 | } |
49 | else |
57 | else |
50 | { |
58 | { |
51 | ctx = tctx_free; |
59 | ctx = tctx_free; |
52 | tctx_free = tctx_free->coro; |
60 | tctx_free = tctx_free->coro; |
53 | } |
61 | } |
… | |
… | |
77 | while (!perl_f) |
85 | while (!perl_f) |
78 | X_COND_WAIT (perl_c, perl_m); |
86 | X_COND_WAIT (perl_c, perl_m); |
79 | ctx = perl_f; |
87 | ctx = perl_f; |
80 | perl_f = 0; |
88 | perl_f = 0; |
81 | --available; |
89 | --available; |
|
|
90 | X_UNLOCK (perl_m); |
|
|
91 | |
82 | pthread_sigmask (SIG_SETMASK, &cursigset, 0); |
92 | pthread_sigmask (SIG_SETMASK, &cursigset, 0); |
83 | X_UNLOCK (perl_m); |
|
|
84 | |
93 | |
85 | while (ctx->coro) |
94 | while (ctx->coro) |
86 | CORO_SCHEDULE; |
95 | CORO_SCHEDULE; |
87 | |
96 | |
|
|
97 | pthread_sigmask (SIG_SETMASK, &fullsigset, &cursigset); |
|
|
98 | |
88 | X_LOCK (wait_m); |
99 | X_LOCK (wait_m); |
89 | pthread_sigmask (SIG_SETMASK, &fullsigset, &cursigset); |
|
|
90 | wait_f = 1; |
100 | ctx->wait_f = 1; |
91 | X_COND_SIGNAL (wait_c); |
101 | X_COND_SIGNAL (ctx->wait_c); |
92 | |
102 | |
93 | if (available >= max_idle) |
103 | if (available >= max_idle) |
94 | { |
104 | { |
95 | X_UNLOCK (wait_m); |
105 | X_UNLOCK (wait_m); |
96 | break; |
106 | break; |
… | |
… | |
114 | static void |
124 | static void |
115 | pmapi_release (void) |
125 | pmapi_release (void) |
116 | { |
126 | { |
117 | struct tctx *ctx = tctx_get (); |
127 | struct tctx *ctx = tctx_get (); |
118 | ctx->coro = SvREFCNT_inc_NN (CORO_CURRENT); |
128 | ctx->coro = SvREFCNT_inc_NN (CORO_CURRENT); |
|
|
129 | ctx->wait_f = 0; |
|
|
130 | |
119 | pthread_setspecific (current_key, ctx); |
131 | pthread_setspecific (current_key, ctx); |
120 | pthread_sigmask (SIG_SETMASK, &fullsigset, &cursigset); |
132 | pthread_sigmask (SIG_SETMASK, &fullsigset, &cursigset); |
121 | |
133 | |
122 | if (!available) |
134 | if (!available) |
123 | start_thread (); |
135 | start_thread (); |
… | |
… | |
142 | } |
154 | } |
143 | |
155 | |
144 | waiters [waiters_count++] = ctx; |
156 | waiters [waiters_count++] = ctx; |
145 | |
157 | |
146 | s_epipe_signal (&ep); |
158 | s_epipe_signal (&ep); |
147 | while (!wait_f) |
159 | while (!ctx->wait_f) |
148 | X_COND_WAIT (wait_c, wait_m); |
160 | X_COND_WAIT (ctx->wait_c, wait_m); |
149 | wait_f = 0; |
|
|
150 | X_UNLOCK (wait_m); |
161 | X_UNLOCK (wait_m); |
151 | |
162 | |
152 | tctx_put (ctx); |
163 | tctx_put (ctx); |
153 | pthread_sigmask (SIG_SETMASK, &cursigset, 0); |
164 | pthread_sigmask (SIG_SETMASK, &cursigset, 0); |
154 | } |
165 | } |