ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/etp.c
(Generate patch)

Comparing libeio/etp.c (file contents):
Revision 1.2 by root, Mon Aug 18 04:26:03 2014 UTC vs.
Revision 1.8 by root, Thu Jun 25 18:14:19 2015 UTC

52 52
53#ifndef ETP_TYPE_GROUP 53#ifndef ETP_TYPE_GROUP
54# define ETP_TYPE_GROUP 1 54# define ETP_TYPE_GROUP 1
55#endif 55#endif
56 56
57#ifndef ETP_WANT_POLL
58# define ETP_WANT_POLL(pool) pool->want_poll_cb (pool->userdata)
59#endif
60#ifndef ETP_DONE_POLL
61# define ETP_DONE_POLL(pool) pool->done_poll_cb (pool->userdata)
62#endif
63
57#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) 64#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
58 65
59#define ETP_TICKS ((1000000 + 1023) >> 10) 66#define ETP_TICKS ((1000000 + 1023) >> 10)
67
68enum {
69 ETP_FLAG_GROUPADD = 0x04, /* some request was added to the group */
70 ETP_FLAG_DELAYED = 0x08, /* groiup request has been delayed */
71};
60 72
61/* calculate time difference in ~1/ETP_TICKS of a second */ 73/* calculate time difference in ~1/ETP_TICKS of a second */
62ecb_inline int 74ecb_inline int
63etp_tvdiff (struct timeval *tv1, struct timeval *tv2) 75etp_tvdiff (struct timeval *tv1, struct timeval *tv2)
64{ 76{
65 return (tv2->tv_sec - tv1->tv_sec ) * ETP_TICKS 77 return (tv2->tv_sec - tv1->tv_sec ) * ETP_TICKS
66 + ((tv2->tv_usec - tv1->tv_usec) >> 10); 78 + ((tv2->tv_usec - tv1->tv_usec) >> 10);
67} 79}
68 80
69static unsigned int started, idle, wanted = 4; 81struct etp_tmpbuf
70
71static void (*want_poll_cb) (void);
72static void (*done_poll_cb) (void);
73
74static unsigned int max_poll_time; /* reslock */
75static unsigned int max_poll_reqs; /* reslock */
76
77static unsigned int nreqs; /* reqlock */
78static unsigned int nready; /* reqlock */
79static unsigned int npending; /* reqlock */
80static unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */
81static unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */
82
83static xmutex_t wrklock;
84static xmutex_t reslock;
85static xmutex_t reqlock;
86static xcond_t reqwait;
87
88typedef struct etp_worker
89{ 82{
90 struct tmpbuf tmpbuf; 83 void *ptr;
84 int len;
85};
91 86
92 /* locked by wrklock */
93 struct etp_worker *prev, *next;
94
95 xthread_t tid;
96
97#ifdef ETP_WORKER_COMMON
98 ETP_WORKER_COMMON
99#endif
100} etp_worker;
101
102static etp_worker wrk_first; /* NOT etp */
103
104#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock)
105#define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (wrklock)
106
107/* worker threads management */
108
109static void 87static void *
110etp_worker_clear (etp_worker *wrk) 88etp_tmpbuf_get (struct etp_tmpbuf *buf, int len)
111{ 89{
112} 90 if (buf->len < len)
91 {
92 free (buf->ptr);
93 buf->ptr = malloc (buf->len = len);
94 }
113 95
114static void ecb_cold 96 return buf->ptr;
115etp_worker_free (etp_worker *wrk)
116{
117 free (wrk->tmpbuf.ptr);
118
119 wrk->next->prev = wrk->prev;
120 wrk->prev->next = wrk->next;
121
122 free (wrk);
123}
124
125ETP_API_DECL unsigned int
126etp_nreqs (void)
127{
128 int retval;
129 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
130 retval = nreqs;
131 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
132 return retval;
133}
134
135ETP_API_DECL unsigned int
136etp_nready (void)
137{
138 unsigned int retval;
139
140 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
141 retval = nready;
142 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
143
144 return retval;
145}
146
147ETP_API_DECL unsigned int
148etp_npending (void)
149{
150 unsigned int retval;
151
152 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
153 retval = npending;
154 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
155
156 return retval;
157}
158
159ETP_API_DECL unsigned int
160etp_nthreads (void)
161{
162 unsigned int retval;
163
164 if (WORDACCESS_UNSAFE) X_LOCK (reqlock);
165 retval = started;
166 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock);
167
168 return retval;
169} 97}
170 98
171/* 99/*
172 * a somewhat faster data structure might be nice, but 100 * a somewhat faster data structure might be nice, but
173 * with 8 priorities this actually needs <20 insns 101 * with 8 priorities this actually needs <20 insns
174 * per shift, the most expensive operation. 102 * per shift, the most expensive operation.
175 */ 103 */
176typedef struct { 104typedef struct
105{
177 ETP_REQ *qs[ETP_NUM_PRI], *qe[ETP_NUM_PRI]; /* qstart, qend */ 106 ETP_REQ *qs[ETP_NUM_PRI], *qe[ETP_NUM_PRI]; /* qstart, qend */
178 int size; 107 int size;
179} etp_reqq; 108} etp_reqq;
180 109
110typedef struct etp_pool *etp_pool;
111
112typedef struct etp_worker
113{
114 etp_pool pool;
115
116 struct etp_tmpbuf tmpbuf;
117
118 /* locked by pool->wrklock */
119 struct etp_worker *prev, *next;
120
121 xthread_t tid;
122
123#ifdef ETP_WORKER_COMMON
124 ETP_WORKER_COMMON
125#endif
126} etp_worker;
127
128struct etp_pool
129{
130 void *userdata;
131
181static etp_reqq req_queue; 132 etp_reqq req_queue;
182static etp_reqq res_queue; 133 etp_reqq res_queue;
134
135 unsigned int started, idle, wanted;
136
137 unsigned int max_poll_time; /* pool->reslock */
138 unsigned int max_poll_reqs; /* pool->reslock */
139
140 unsigned int nreqs; /* pool->reqlock */
141 unsigned int nready; /* pool->reqlock */
142 unsigned int npending; /* pool->reqlock */
143 unsigned int max_idle; /* maximum number of threads that can pool->idle indefinitely */
144 unsigned int idle_timeout; /* number of seconds after which an pool->idle threads exit */
145
146 void (*want_poll_cb) (void *userdata);
147 void (*done_poll_cb) (void *userdata);
148
149 xmutex_t wrklock;
150 xmutex_t reslock;
151 xmutex_t reqlock;
152 xcond_t reqwait;
153
154 etp_worker wrk_first;
155};
156
157#define ETP_WORKER_LOCK(wrk) X_LOCK (pool->wrklock)
158#define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (pool->wrklock)
159
160/* worker threads management */
161
162static void
163etp_worker_clear (etp_worker *wrk)
164{
165}
166
167static void ecb_cold
168etp_worker_free (etp_worker *wrk)
169{
170 free (wrk->tmpbuf.ptr);
171
172 wrk->next->prev = wrk->prev;
173 wrk->prev->next = wrk->next;
174
175 free (wrk);
176}
177
178ETP_API_DECL unsigned int
179etp_nreqs (etp_pool pool)
180{
181 int retval;
182 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
183 retval = pool->nreqs;
184 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
185 return retval;
186}
187
188ETP_API_DECL unsigned int
189etp_nready (etp_pool pool)
190{
191 unsigned int retval;
192
193 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
194 retval = pool->nready;
195 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
196
197 return retval;
198}
199
200ETP_API_DECL unsigned int
201etp_npending (etp_pool pool)
202{
203 unsigned int retval;
204
205 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
206 retval = pool->npending;
207 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
208
209 return retval;
210}
211
212ETP_API_DECL unsigned int
213etp_nthreads (etp_pool pool)
214{
215 unsigned int retval;
216
217 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
218 retval = pool->started;
219 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
220
221 return retval;
222}
183 223
184static void ecb_noinline ecb_cold 224static void ecb_noinline ecb_cold
185reqq_init (etp_reqq *q) 225reqq_init (etp_reqq *q)
186{ 226{
187 int pri; 227 int pri;
234 274
235 abort (); 275 abort ();
236} 276}
237 277
238ETP_API_DECL int ecb_cold 278ETP_API_DECL int ecb_cold
239etp_init (void (*want_poll)(void), void (*done_poll)(void)) 279etp_init (etp_pool pool, void *userdata, void (*want_poll)(void *userdata), void (*done_poll)(void *userdata))
240{ 280{
241 X_MUTEX_CREATE (wrklock); 281 X_MUTEX_CREATE (pool->wrklock);
242 X_MUTEX_CREATE (reslock); 282 X_MUTEX_CREATE (pool->reslock);
243 X_MUTEX_CREATE (reqlock); 283 X_MUTEX_CREATE (pool->reqlock);
244 X_COND_CREATE (reqwait); 284 X_COND_CREATE (pool->reqwait);
245 285
246 reqq_init (&req_queue); 286 reqq_init (&pool->req_queue);
247 reqq_init (&res_queue); 287 reqq_init (&pool->res_queue);
248 288
249 wrk_first.next = 289 pool->wrk_first.next =
250 wrk_first.prev = &wrk_first; 290 pool->wrk_first.prev = &pool->wrk_first;
251 291
252 started = 0; 292 pool->started = 0;
253 idle = 0; 293 pool->idle = 0;
254 nreqs = 0; 294 pool->nreqs = 0;
255 nready = 0; 295 pool->nready = 0;
256 npending = 0; 296 pool->npending = 0;
297 pool->wanted = 4;
257 298
299 pool->max_idle = 4; /* maximum number of threads that can pool->idle indefinitely */
300 pool->idle_timeout = 10; /* number of seconds after which an pool->idle threads exit */
301
302 pool->userdata = userdata;
258 want_poll_cb = want_poll; 303 pool->want_poll_cb = want_poll;
259 done_poll_cb = done_poll; 304 pool->done_poll_cb = done_poll;
260 305
261 return 0; 306 return 0;
262} 307}
263 308
264/* not yet in etp.c */ 309static void ecb_noinline ecb_cold
310etp_proc_init (void)
311{
312#if HAVE_PRCTL_SET_NAME
313 /* provide a more sensible "thread name" */
314 char name[16 + 1];
315 const int namelen = sizeof (name) - 1;
316 int len;
317
318 prctl (PR_GET_NAME, (unsigned long)name, 0, 0, 0);
319 name [namelen] = 0;
320 len = strlen (name);
321 strcpy (name + (len <= namelen - 4 ? len : namelen - 4), "/eio");
322 prctl (PR_SET_NAME, (unsigned long)name, 0, 0, 0);
323#endif
324}
325
265X_THREAD_PROC (etp_proc); 326X_THREAD_PROC (etp_proc)
327{
328 ETP_REQ *req;
329 struct timespec ts;
330 etp_worker *self = (etp_worker *)thr_arg;
331 etp_pool pool = self->pool;
332
333 etp_proc_init ();
334
335 /* try to distribute timeouts somewhat evenly */
336 ts.tv_nsec = ((unsigned long)self & 1023UL) * (1000000000UL / 1024UL);
337
338 for (;;)
339 {
340 ts.tv_sec = 0;
341
342 X_LOCK (pool->reqlock);
343
344 for (;;)
345 {
346 req = reqq_shift (&pool->req_queue);
347
348 if (req)
349 break;
350
351 if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */
352 {
353 X_UNLOCK (pool->reqlock);
354 X_LOCK (pool->wrklock);
355 --pool->started;
356 X_UNLOCK (pool->wrklock);
357 goto quit;
358 }
359
360 ++pool->idle;
361
362 if (pool->idle <= pool->max_idle)
363 /* we are allowed to pool->idle, so do so without any timeout */
364 X_COND_WAIT (pool->reqwait, pool->reqlock);
365 else
366 {
367 /* initialise timeout once */
368 if (!ts.tv_sec)
369 ts.tv_sec = time (0) + pool->idle_timeout;
370
371 if (X_COND_TIMEDWAIT (pool->reqwait, pool->reqlock, ts) == ETIMEDOUT)
372 ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */
373 }
374
375 --pool->idle;
376 }
377
378 --pool->nready;
379
380 X_UNLOCK (pool->reqlock);
381
382 if (req->type == ETP_TYPE_QUIT)
383 goto quit;
384
385 ETP_EXECUTE (self, req);
386
387 X_LOCK (pool->reslock);
388
389 ++pool->npending;
390
391 if (!reqq_push (&pool->res_queue, req))
392 ETP_WANT_POLL (poll);
393
394 etp_worker_clear (self);
395
396 X_UNLOCK (pool->reslock);
397 }
398
399quit:
400 free (req);
401
402 X_LOCK (pool->wrklock);
403 etp_worker_free (self);
404 X_UNLOCK (pool->wrklock);
405
406 return 0;
407}
266 408
267static void ecb_cold 409static void ecb_cold
268etp_start_thread (void) 410etp_start_thread (etp_pool pool)
269{ 411{
270 etp_worker *wrk = calloc (1, sizeof (etp_worker)); 412 etp_worker *wrk = calloc (1, sizeof (etp_worker));
271 413
272 /*TODO*/ 414 /*TODO*/
273 assert (("unable to allocate worker thread data", wrk)); 415 assert (("unable to allocate worker thread data", wrk));
274 416
417 wrk->pool = pool;
418
275 X_LOCK (wrklock); 419 X_LOCK (pool->wrklock);
276 420
277 if (xthread_create (&wrk->tid, etp_proc, (void *)wrk)) 421 if (xthread_create (&wrk->tid, etp_proc, (void *)wrk))
278 { 422 {
279 wrk->prev = &wrk_first; 423 wrk->prev = &pool->wrk_first;
280 wrk->next = wrk_first.next; 424 wrk->next = pool->wrk_first.next;
281 wrk_first.next->prev = wrk; 425 pool->wrk_first.next->prev = wrk;
282 wrk_first.next = wrk; 426 pool->wrk_first.next = wrk;
283 ++started; 427 ++pool->started;
284 } 428 }
285 else 429 else
286 free (wrk); 430 free (wrk);
287 431
288 X_UNLOCK (wrklock); 432 X_UNLOCK (pool->wrklock);
289} 433}
290 434
291static void 435static void
292etp_maybe_start_thread (void) 436etp_maybe_start_thread (etp_pool pool)
293{ 437{
294 if (ecb_expect_true (etp_nthreads () >= wanted)) 438 if (ecb_expect_true (etp_nthreads (pool) >= pool->wanted))
295 return; 439 return;
296 440
297 /* todo: maybe use idle here, but might be less exact */ 441 /* todo: maybe use pool->idle here, but might be less exact */
298 if (ecb_expect_true (0 <= (int)etp_nthreads () + (int)etp_npending () - (int)etp_nreqs ())) 442 if (ecb_expect_true (0 <= (int)etp_nthreads (pool) + (int)etp_npending (pool) - (int)etp_nreqs (pool)))
299 return; 443 return;
300 444
301 etp_start_thread (); 445 etp_start_thread (pool);
302} 446}
303 447
304static void ecb_cold 448static void ecb_cold
305etp_end_thread (void) 449etp_end_thread (etp_pool pool)
306{ 450{
307 ETP_REQ *req = calloc (1, sizeof (ETP_REQ)); /* will be freed by worker */ 451 ETP_REQ *req = calloc (1, sizeof (ETP_REQ)); /* will be freed by worker */
308 452
309 req->type = ETP_TYPE_QUIT; 453 req->type = ETP_TYPE_QUIT;
310 req->pri = ETP_PRI_MAX - ETP_PRI_MIN; 454 req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
311 455
312 X_LOCK (reqlock); 456 X_LOCK (pool->reqlock);
313 reqq_push (&req_queue, req); 457 reqq_push (&pool->req_queue, req);
314 X_COND_SIGNAL (reqwait); 458 X_COND_SIGNAL (pool->reqwait);
315 X_UNLOCK (reqlock); 459 X_UNLOCK (pool->reqlock);
316 460
317 X_LOCK (wrklock); 461 X_LOCK (pool->wrklock);
318 --started; 462 --pool->started;
319 X_UNLOCK (wrklock); 463 X_UNLOCK (pool->wrklock);
320} 464}
321 465
322ETP_API_DECL int 466ETP_API_DECL int
323etp_poll (void) 467etp_poll (etp_pool pool)
324{ 468{
325 unsigned int maxreqs; 469 unsigned int maxreqs;
326 unsigned int maxtime; 470 unsigned int maxtime;
327 struct timeval tv_start, tv_now; 471 struct timeval tv_start, tv_now;
328 472
329 X_LOCK (reslock); 473 X_LOCK (pool->reslock);
330 maxreqs = max_poll_reqs; 474 maxreqs = pool->max_poll_reqs;
331 maxtime = max_poll_time; 475 maxtime = pool->max_poll_time;
332 X_UNLOCK (reslock); 476 X_UNLOCK (pool->reslock);
333 477
334 if (maxtime) 478 if (maxtime)
335 gettimeofday (&tv_start, 0); 479 gettimeofday (&tv_start, 0);
336 480
337 for (;;) 481 for (;;)
338 { 482 {
339 ETP_REQ *req; 483 ETP_REQ *req;
340 484
341 etp_maybe_start_thread (); 485 etp_maybe_start_thread (pool);
342 486
343 X_LOCK (reslock); 487 X_LOCK (pool->reslock);
344 req = reqq_shift (&res_queue); 488 req = reqq_shift (&pool->res_queue);
345 489
346 if (req) 490 if (req)
347 { 491 {
348 --npending; 492 --pool->npending;
349 493
350 if (!res_queue.size && done_poll_cb) 494 if (!pool->res_queue.size)
351 done_poll_cb (); 495 ETP_DONE_POLL (pool->userdata);
352 } 496 }
353 497
354 X_UNLOCK (reslock); 498 X_UNLOCK (pool->reslock);
355 499
356 if (!req) 500 if (!req)
357 return 0; 501 return 0;
358 502
359 X_LOCK (reqlock); 503 X_LOCK (pool->reqlock);
360 --nreqs; 504 --pool->nreqs;
361 X_UNLOCK (reqlock); 505 X_UNLOCK (pool->reqlock);
362 506
363 if (ecb_expect_false (req->type == ETP_TYPE_GROUP && req->size)) 507 if (ecb_expect_false (req->type == ETP_TYPE_GROUP && req->size))
364 { 508 {
365 req->int1 = 1; /* mark request as delayed */ 509 req->flags |= ETP_FLAG_DELAYED; /* mark request as delayed */
366 continue; 510 continue;
367 } 511 }
368 else 512 else
369 { 513 {
370 int res = ETP_FINISH (req); 514 int res = ETP_FINISH (req);
387 errno = EAGAIN; 531 errno = EAGAIN;
388 return -1; 532 return -1;
389} 533}
390 534
391ETP_API_DECL void 535ETP_API_DECL void
392etp_grp_cancel (ETP_REQ *grp); 536etp_grp_cancel (etp_pool pool, ETP_REQ *grp);
393 537
394ETP_API_DECL void 538ETP_API_DECL void
395etp_cancel (ETP_REQ *req) 539etp_cancel (etp_pool pool, ETP_REQ *req)
396{ 540{
397 req->cancelled = 1; 541 req->cancelled = 1;
398 542
399 etp_grp_cancel (req); 543 etp_grp_cancel (pool, req);
400} 544}
401 545
402ETP_API_DECL void 546ETP_API_DECL void
403etp_grp_cancel (ETP_REQ *grp) 547etp_grp_cancel (etp_pool pool, ETP_REQ *grp)
404{ 548{
405 for (grp = grp->grp_first; grp; grp = grp->grp_next) 549 for (grp = grp->grp_first; grp; grp = grp->grp_next)
406 etp_cancel (grp); 550 etp_cancel (pool, grp);
407} 551}
408 552
409ETP_API_DECL void 553ETP_API_DECL void
410etp_submit (ETP_REQ *req) 554etp_submit (etp_pool pool, ETP_REQ *req)
411{ 555{
412 req->pri -= ETP_PRI_MIN; 556 req->pri -= ETP_PRI_MIN;
413 557
414 if (ecb_expect_false (req->pri < ETP_PRI_MIN - ETP_PRI_MIN)) req->pri = ETP_PRI_MIN - ETP_PRI_MIN; 558 if (ecb_expect_false (req->pri < ETP_PRI_MIN - ETP_PRI_MIN)) req->pri = ETP_PRI_MIN - ETP_PRI_MIN;
415 if (ecb_expect_false (req->pri > ETP_PRI_MAX - ETP_PRI_MIN)) req->pri = ETP_PRI_MAX - ETP_PRI_MIN; 559 if (ecb_expect_false (req->pri > ETP_PRI_MAX - ETP_PRI_MIN)) req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
416 560
417 if (ecb_expect_false (req->type == ETP_TYPE_GROUP)) 561 if (ecb_expect_false (req->type == ETP_TYPE_GROUP))
418 { 562 {
419 /* I hope this is worth it :/ */ 563 /* I hope this is worth it :/ */
420 X_LOCK (reqlock); 564 X_LOCK (pool->reqlock);
421 ++nreqs; 565 ++pool->nreqs;
422 X_UNLOCK (reqlock); 566 X_UNLOCK (pool->reqlock);
423 567
424 X_LOCK (reslock); 568 X_LOCK (pool->reslock);
425 569
426 ++npending; 570 ++pool->npending;
427 571
428 if (!reqq_push (&res_queue, req) && want_poll_cb) 572 if (!reqq_push (&pool->res_queue, req))
429 want_poll_cb (); 573 ETP_WANT_POLL (pool);
430 574
431 X_UNLOCK (reslock); 575 X_UNLOCK (pool->reslock);
432 } 576 }
433 else 577 else
434 { 578 {
435 X_LOCK (reqlock); 579 X_LOCK (pool->reqlock);
436 ++nreqs; 580 ++pool->nreqs;
437 ++nready; 581 ++pool->nready;
438 reqq_push (&req_queue, req); 582 reqq_push (&pool->req_queue, req);
439 X_COND_SIGNAL (reqwait); 583 X_COND_SIGNAL (pool->reqwait);
440 X_UNLOCK (reqlock); 584 X_UNLOCK (pool->reqlock);
441 585
442 etp_maybe_start_thread (); 586 etp_maybe_start_thread (pool);
443 } 587 }
444} 588}
445 589
446ETP_API_DECL void ecb_cold 590ETP_API_DECL void ecb_cold
447etp_set_max_poll_time (double nseconds) 591etp_set_max_poll_time (etp_pool pool, double nseconds)
448{ 592{
449 if (WORDACCESS_UNSAFE) X_LOCK (reslock); 593 if (WORDACCESS_UNSAFE) X_LOCK (pool->reslock);
450 max_poll_time = nseconds * ETP_TICKS; 594 pool->max_poll_time = nseconds * ETP_TICKS;
451 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock); 595 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reslock);
452} 596}
453 597
454ETP_API_DECL void ecb_cold 598ETP_API_DECL void ecb_cold
455etp_set_max_poll_reqs (unsigned int maxreqs) 599etp_set_max_poll_reqs (etp_pool pool, unsigned int maxreqs)
456{ 600{
457 if (WORDACCESS_UNSAFE) X_LOCK (reslock); 601 if (WORDACCESS_UNSAFE) X_LOCK (pool->reslock);
458 max_poll_reqs = maxreqs; 602 pool->max_poll_reqs = maxreqs;
459 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock); 603 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reslock);
460} 604}
461 605
462ETP_API_DECL void ecb_cold 606ETP_API_DECL void ecb_cold
463etp_set_max_idle (unsigned int nthreads) 607etp_set_max_idle (etp_pool pool, unsigned int nthreads)
464{ 608{
465 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 609 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
466 max_idle = nthreads; 610 pool->max_idle = nthreads;
467 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 611 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
468} 612}
469 613
470ETP_API_DECL void ecb_cold 614ETP_API_DECL void ecb_cold
471etp_set_idle_timeout (unsigned int seconds) 615etp_set_idle_timeout (etp_pool pool, unsigned int seconds)
472{ 616{
473 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 617 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
474 idle_timeout = seconds; 618 pool->idle_timeout = seconds;
475 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 619 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
476} 620}
477 621
478ETP_API_DECL void ecb_cold 622ETP_API_DECL void ecb_cold
479etp_set_min_parallel (unsigned int nthreads) 623etp_set_min_parallel (etp_pool pool, unsigned int nthreads)
480{ 624{
481 if (wanted < nthreads) 625 if (pool->wanted < nthreads)
482 wanted = nthreads; 626 pool->wanted = nthreads;
483} 627}
484 628
485ETP_API_DECL void ecb_cold 629ETP_API_DECL void ecb_cold
486etp_set_max_parallel (unsigned int nthreads) 630etp_set_max_parallel (etp_pool pool, unsigned int nthreads)
487{ 631{
488 if (wanted > nthreads) 632 if (pool->wanted > nthreads)
489 wanted = nthreads; 633 pool->wanted = nthreads;
490 634
491 while (started > wanted) 635 while (pool->started > pool->wanted)
492 etp_end_thread (); 636 etp_end_thread (pool);
493} 637}
494 638

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines